Keras Conv1D 用于简单的数据目标预测

数据挖掘 神经网络 喀拉斯 预测建模 卷积 卷积神经网络
2021-09-20 02:22:52

我正在尝试使用 Keras 的 conv1D 层来预测iris 数据集中的物种(它有 4 个数字特征和一个分类目标)。以下是我的代码:

import numpy as np
import pandas as pd

irisdf = pd.read_csv('iris.csv')

Xall = irisdf.drop('Species', axis=1)
print(Xall.shape)
Xall = np.expand_dims(Xall.values, axis=2) 
print(Xall.shape)

Yall = irisdf['Species']
nb_classes =  3

import keras
from keras.models import Sequential
from keras.layers import Dense, InputLayer, Dropout, Flatten, BatchNormalization, Conv1D
input_shape = (Xall.shape[1:],)
print(input_shape)
model = Sequential([
    InputLayer(input_shape=input_shape), 
    Conv1D(32, 2),
    Dense(nb_classes, activation='softmax')
])
model.compile(loss=keras.losses.mean_squared_error,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])
model.summary()
model.fit(Xall, Yall, epochs=25, verbose=True)

但是,它给出了以下错误:

Traceback (most recent call last):
  File "/home/abcde/.local/lib/python3.5/site-packages/tensorflow/python/eager/execute.py", line 141, in make_shape
    shape = tensor_shape.as_shape(v)
  File "/home/abcde/.local/lib/python3.5/site-packages/tensorflow/python/framework/tensor_shape.py", line 946, in as_shape
    return TensorShape(shape)
  File "/home/abcde/.local/lib/python3.5/site-packages/tensorflow/python/framework/tensor_shape.py", line 541, in __init__
    self._dims = [as_dimension(d) for d in dims_iter]
  File "/home/abcde/.local/lib/python3.5/site-packages/tensorflow/python/framework/tensor_shape.py", line 541, in <listcomp>
    self._dims = [as_dimension(d) for d in dims_iter]
  File "/home/abcde/.local/lib/python3.5/site-packages/tensorflow/python/framework/tensor_shape.py", line 482, in as_dimension
    return Dimension(value)
  File "/home/abcde/.local/lib/python3.5/site-packages/tensorflow/python/framework/tensor_shape.py", line 37, in __init__
    self._value = int(value)
TypeError: int() argument must be a string, a bytes-like object or a number, not 'tuple'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "rnkeras_conv1d_iris.py", line 40, in <module>
    InputLayer(input_shape=input_shape), 
  File "/home/abcde/.local/lib/python3.5/site-packages/keras/legacy/interfaces.py", line 91, in wrapper
    return func(*args, **kwargs)
  File "/home/abcde/.local/lib/python3.5/site-packages/keras/engine/input_layer.py", line 86, in __init__
    name=self.name)
  File "/home/abcde/.local/lib/python3.5/site-packages/keras/backend/tensorflow_backend.py", line 515, in placeholder
    x = tf.placeholder(dtype, shape=shape, name=name)
  File "/home/abcde/.local/lib/python3.5/site-packages/tensorflow/python/ops/array_ops.py", line 1735, in placeholder
    return gen_array_ops.placeholder(dtype=dtype, shape=shape, name=name)
  File "/home/abcde/.local/lib/python3.5/site-packages/tensorflow/python/ops/gen_array_ops.py", line 4923, in placeholder
    shape = _execute.make_shape(shape, "shape")
  File "/home/abcde/.local/lib/python3.5/site-packages/tensorflow/python/eager/execute.py", line 143, in make_shape
    raise TypeError("Error converting %s to a TensorShape: %s." % (arg_name, e))
TypeError: Error converting shape to a TensorShape: int() argument must be a string, a bytes-like object or a number, not 'tuple'.

问题出在哪里,如何解决?

(PS:如果你觉得这个问题很有趣/很重要,请点赞;)

1个回答

您的错误来自 Keras 框架没有使用字符串作为输出标签。您需要将这些转换为 1-hot 编码向量来训练您的模型。这是一些执行此操作的代码。

获取数据

import pandas as pd
df = pd.read_csv('iris.csv', header=None, names=['sepal_length', 'sepal_width', 'petal_length', 'petal_width', 'species'])

这将分配一个类标签,我们稍后将对其进行 one-hot 编码

df['labels'] =df['species'].astype('category').cat.codes

在此处输入图像描述

拆分数据和重塑数据

首先,我们将数据拆分为训练和测试集。然后我们将对标签进行 one-hot 编码。最后,我们将构建输入以匹配 Keras 的预期。要使用一维卷积,我们需要添加一个空间维度。

from sklearn.model_selection import train_test_split
import keras

X = df[['sepal_length', 'sepal_width', 'petal_length', 'petal_width']]
Y = df['labels']
x_train, x_test, y_train, y_test = train_test_split(np.asarray(X), np.asarray(Y), test_size=0.33, shuffle= True)

# The known number of output classes.
num_classes = 3

# Input image dimensions
input_shape = (4,)

# Convert class vectors to binary class matrices. This uses 1 hot encoding.
y_train_binary = keras.utils.to_categorical(y_train, num_classes)
y_test_binary = keras.utils.to_categorical(y_test, num_classes)

x_train = x_train.reshape(100, 4,1)
x_test = x_test.reshape(50, 4,1)

该模型

您的模型不足以获得良好的结果,因此我在混合中添加了一个额外的隐藏层以获得可接受的结果。

from __future__ import print_function    
from keras.models import Sequential
import keras
from keras.models import Sequential
from keras.layers import Dense, Flatten, Conv1D
from keras.callbacks import ModelCheckpoint
from keras.models import model_from_json
from keras import backend as K

model = Sequential()
model.add(Conv1D(32, (3), input_shape=(1,4), activation='relu'))
model.add(Flatten())
model.add(Dense(64, activation='relu'))
model.add(Dense(num_classes, activation='softmax'))

model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])

model.summary()

现在让我们训练模型

batch_size = 128
epochs = 10
model = model.fit(x_train, y_train_binary,
          batch_size=batch_size,
          epochs=epochs,
          verbose=1,
          validation_data=(x_test, y_test_binary))

100/100 [==============================] - 0s 50us/步 - 损失:1.0906 - acc: 0.6400 - val_loss : 1.0893 - val_acc: 0.7000

我们得到 70% 的准确率,这还不错。但是可以通过更改模型以更好地适应数据源来改进它。

绘制收敛

plt.plot(model.history['loss'])
plt.plot(model.history['val_loss'])
plt.title('model train vs validation loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'validation'], loc='upper right')
plt.show()