卷积层不匹配中的 Keras 维度
Keras dimensionality in convolutional layer mismatch
我正在尝试使用 Keras 构建我的第一个神经网络。我的经验为零,我似乎无法弄清楚为什么我的维度不对。我无法从他们的文档中弄清楚这个错误是在抱怨什么,甚至是什么层导致了它。
我的模型接受一个 32 字节的数字数组,并且应该在另一侧给出一个布尔值。我想在输入字节数组上进行一维卷积。
arr1 是 32 字节数组,arr2 是布尔数组。
inputData = np.array(arr1)
inputData = np.expand_dims(inputData, axis = 2)
labelData = np.array(arr2)
print inputData.shape
print labelData.shape
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'))
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)
好吧,在我看来,您需要 google 了解更多关于卷积网络的知识 :-)
您在每个步骤中对您的序列应用 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)
现在您想在其上使用 Dense 层...问题是 Dense 层将按以下方式在您的 3D 输入上工作:
model.add(k.layers.core.Dense(32))
model.add(k.layers.Activation('sigmoid'))
尺寸:(None, 28, 32)
这是你的输出。我觉得奇怪的第一件事是你想要从密集层输出 32 个输出......你应该放 1 个而不是 32 个。但即使这样也不能解决你的问题。看看如果我们更改最后一层会发生什么:
model.add(k.layers.core.Dense(1))
model.add(k.layers.Activation('sigmoid'))
尺寸:(None, 28, 1)
发生这种情况是因为您将致密层应用于“2D”张量。如果您将 dense(1) 层应用于输入 [28, 32],它会产生一个形状为 (32,1) 的权重矩阵,并将其应用于 28 个向量,这样您会发现自己有 28 个输出尺寸 1。
我建议解决这个问题的方法是像这样更改最后 2 层:
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'))
# Only use one filter so that the output will be a sequence of 28 values, not a matrix.
model.add(k.layers.convolutional.Convolution1D(1,2))
model.add(k.layers.Activation('relu'))
# Change the shape from (None, 28, 1) to (None, 28)
model.add(k.layers.core.Flatten())
# Only one neuron as output to get the binary target.
model.add(k.layers.core.Dense(1))
model.add(k.layers.Activation('sigmoid'))
现在最后两个 steps 将从
获取你的张量
(None, 29, 32) -> (None, 28, 1) -> (None, 28) -> (None, 1)
我希望这个帮助ps你。
ps。如果您想知道 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'
选择该选项。你可以read more about this here and find the different values possible for the padding
argument here。我鼓励您阅读最后一篇 link,它提供了有关输入和输出形状的信息...
来自文档:
padding: One of "valid" or "same" (case-insensitive). "valid" means "no padding". "same" results in padding the input such that the output has the same length as the original input.
默认值为 'valid',因此您无需在示例中填充。
我也建议你把你的keras版本升级到最新的。 Convolution1D 现在是 Conv1D,因此您可能会发现文档和教程令人困惑。
我正在尝试使用 Keras 构建我的第一个神经网络。我的经验为零,我似乎无法弄清楚为什么我的维度不对。我无法从他们的文档中弄清楚这个错误是在抱怨什么,甚至是什么层导致了它。
我的模型接受一个 32 字节的数字数组,并且应该在另一侧给出一个布尔值。我想在输入字节数组上进行一维卷积。
arr1 是 32 字节数组,arr2 是布尔数组。
inputData = np.array(arr1)
inputData = np.expand_dims(inputData, axis = 2)
labelData = np.array(arr2)
print inputData.shape
print labelData.shape
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'))
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)
好吧,在我看来,您需要 google 了解更多关于卷积网络的知识 :-)
您在每个步骤中对您的序列应用 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)
现在您想在其上使用 Dense 层...问题是 Dense 层将按以下方式在您的 3D 输入上工作:
model.add(k.layers.core.Dense(32))
model.add(k.layers.Activation('sigmoid'))
尺寸:(None, 28, 32)
这是你的输出。我觉得奇怪的第一件事是你想要从密集层输出 32 个输出......你应该放 1 个而不是 32 个。但即使这样也不能解决你的问题。看看如果我们更改最后一层会发生什么:
model.add(k.layers.core.Dense(1))
model.add(k.layers.Activation('sigmoid'))
尺寸:(None, 28, 1)
发生这种情况是因为您将致密层应用于“2D”张量。如果您将 dense(1) 层应用于输入 [28, 32],它会产生一个形状为 (32,1) 的权重矩阵,并将其应用于 28 个向量,这样您会发现自己有 28 个输出尺寸 1。
我建议解决这个问题的方法是像这样更改最后 2 层:
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'))
# Only use one filter so that the output will be a sequence of 28 values, not a matrix.
model.add(k.layers.convolutional.Convolution1D(1,2))
model.add(k.layers.Activation('relu'))
# Change the shape from (None, 28, 1) to (None, 28)
model.add(k.layers.core.Flatten())
# Only one neuron as output to get the binary target.
model.add(k.layers.core.Dense(1))
model.add(k.layers.Activation('sigmoid'))
现在最后两个 steps 将从
获取你的张量(None, 29, 32) -> (None, 28, 1) -> (None, 28) -> (None, 1)
我希望这个帮助ps你。
ps。如果您想知道 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'
选择该选项。你可以read more about this here and find the different values possible for the padding
argument here。我鼓励您阅读最后一篇 link,它提供了有关输入和输出形状的信息...
来自文档:
padding: One of "valid" or "same" (case-insensitive). "valid" means "no padding". "same" results in padding the input such that the output has the same length as the original input.
默认值为 'valid',因此您无需在示例中填充。
我也建议你把你的keras版本升级到最新的。 Convolution1D 现在是 Conv1D,因此您可能会发现文档和教程令人困惑。