Keras卷积层维度不匹配

我正在尝试使用Keras构建我的第一个神经网络。我完全没有经验,搞不清楚为什么我的维度设置不正确。我无法从他们的文档中弄明白这个错误在抱怨什么,甚至不知道是哪一层引起了这个问题。

我的模型接收一个32字节的数字数组,并应该在另一端输出一个布尔值。我希望对输入的字节数组进行一维卷积。

arr1是32字节的数组,arr2是一个布尔值数组。

inputData = np.array(arr1)inputData = np.expand_dims(inputData, axis = 2)labelData = np.array(arr2)print inputData.shapeprint labelData.shapemodel = k.models.Sequential()model.add(k.layers.convolutional.Convolution1D(32,2, input_shape = (32, 1)))model.add(k.layers.Activation('relu'))model.add(k.layers.convolutional.Convolution1D(32,2))model.add(k.layers.Activation('relu'))model.add(k.layers.convolutional.Convolution1D(32,2))model.add(k.layers.Activation('relu'))model.add(k.layers.convolutional.Convolution1D(32,2))model.add(k.layers.Activation('relu'))model.add(k.layers.core.Dense(32))model.add(k.layers.Activation('sigmoid'))model.compile(loss = 'binary_crossentropy',              optimizer = 'rmsprop',              metrics=['accuracy'])model.fit(    inputData,labelData)

打印形状的输出是(1000, 32, 1)和(1000,)

我收到的错误是:

Traceback (most recent call last): File “cnn/init.py”, line 50, in inputData,labelData File “/home/steve/Documents/cnn/env/local/lib/python2.7/site-packages/keras/models.py”, line 863, in fit initial_epoch=initial_epoch) File “/home/steve/Documents/cnn/env/local/lib/python2.7/site-packages/keras/engine/training.py”, line 1358, in fit batch_size=batch_size) File “/home/steve/Documents/cnn/env/local/lib/python2.7/site-packages/keras/engine/training.py”, line 1238, in _standardize_user_data exception_prefix=’target’) File “/home/steve/Documents/cnn/env/local/lib/python2.7/site-packages/keras/engine/training.py”, line 128, in _standardize_input_data str(array.shape)) ValueError: Error when checking target: expected activation_5 to have 3 dimensions, but got array with shape (1000, 1)


回答:

看起来你需要多搜索一些关于卷积网络的信息 🙂

你在每一步应用32个长度为2的滤波器到你的序列上。所以我们来看看每层之后张量的维度变化:

维度:(None, 32, 1)

model.add(k.layers.convolutional.Convolution1D(32,2, input_shape = (32, 1)))model.add(k.layers.Activation('relu'))

维度:(None, 31, 32)(你的长度为2的滤波器扫过整个序列,所以序列长度变为31)

model.add(k.layers.convolutional.Convolution1D(32,2))model.add(k.layers.Activation('relu'))

维度:(None, 30, 32)(由于你的滤波器长度为2,你再次损失了一个值,但仍有32个滤波器)

model.add(k.layers.convolutional.Convolution1D(32,2))model.add(k.layers.Activation('relu'))

维度:(None, 29, 32)(同样…)

model.add(k.layers.convolutional.Convolution1D(32,2))model.add(k.layers.Activation('relu'))

维度:(None, 28, 32)

现在你想在上面添加一个全连接层…问题是全连接层会像下面这样处理你的3D输入:

model.add(k.layers.core.Dense(32))model.add(k.layers.Activation('sigmoid'))

维度:(None, 28, 32)

这是你的输出。首先让我觉得奇怪的是你希望从全连接层得到32个输出…你应该把32改为1。但即使这样也无法解决你的问题。看看我们更改最后一层会发生什么:

model.add(k.layers.core.Dense(1))model.add(k.layers.Activation('sigmoid'))

维度:(None, 28, 1)

这是因为你对一个’2D’张量应用了全连接层。当你对一个[28, 32]的输入应用dense(1)层时,它会生成一个形状为(32,1)的权重矩阵,并应用于28个向量,所以你得到28个大小为1的输出。

为了解决这个问题,我建议你像这样更改最后两层:

model = k.models.Sequential()model.add(k.layers.convolutional.Convolution1D(32,2, input_shape = (32, 1)))model.add(k.layers.Activation('relu'))model.add(k.layers.convolutional.Convolution1D(32,2))model.add(k.layers.Activation('relu'))model.add(k.layers.convolutional.Convolution1D(32,2))model.add(k.layers.Activation('relu'))# 只使用一个滤波器,这样输出将是28个值的序列,而不是矩阵。model.add(k.layers.convolutional.Convolution1D(1,2))model.add(k.layers.Activation('relu'))# 将形状从(None, 28, 1)更改为(None, 28)model.add(k.layers.core.Flatten())# 只有一个神经元作为输出,以获得二进制目标。model.add(k.layers.core.Dense(1))model.add(k.layers.Activation('sigmoid'))

现在最后两步将把你的张量从

(None, 29, 32) -> (None, 28, 1) -> (None, 28) -> (None, 1)

希望这对你有帮助。

附注:如果你在想None是什么,它是批次的维度,你不是一次性输入1000个样本,而是批次批次输入的,因为值取决于选择什么,按惯例我们使用None。

编辑:

进一步解释为什么序列长度在每一步都减少一个值。

假设你有一个长度为4的值序列[x1 x2 x3 x4],你想用长度为2的滤波器[f1 f2]来卷积这个序列。第一个值将由y1 = [f1 f2] * [x1 x2]给出,第二个值将由y2 = [f1 f2] * [x2 x3]给出,第三个值将由y3 = [f1 f2] * [x3 x4]给出。然后你到达了序列的末尾,无法继续。你得到的结果序列是[y1 y2 y3]

这是由于滤波器长度和序列边界效应造成的。有多种选择,有些会用0填充序列以获得完全相同的输出长度…你可以使用'padding'参数选择这个选项。你可以在这里阅读更多相关信息,并找到padding参数的不同可能值。我鼓励你阅读最后一个链接,它提供了关于输入和输出形状的信息…

从文档中:

padding: “valid”或”same”之一(不区分大小写)。”valid”表示”无填充”。”same”表示填充输入,使输出与原始输入长度相同。

默认是’valid’,所以在你的例子中没有填充。

我还建议你升级到最新的Keras版本。Convolution1D现在是Conv1D,所以你可能会发现文档和教程令人困惑。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注