【问题标题】:Keras dimensionality in convolutional layer mismatch卷积层不匹配中的 Keras 维度
【发布时间】:2017-12-20 14:03:16
【问题描述】:

我正在尝试使用 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(最近一次调用最后一次):文件“cnn/init.py”,行 50,在 inputData,labelData 文件 "/home/steve/Documents/cnn/env/local/lib/python2.7/site-packages/keras/models.py", 第 863 行,合适 initial_epoch=initial_epoch)文件“/home/steve/Documents/cnn/env/local/lib/python2.7/site-packages/keras/engine/training.py”, 第 1358 行,合适 batch_size=batch_size) 文件 "/home/steve/Documents/cnn/env/local/lib/python2.7/site-packages/keras/engine/training.py", 第 1238 行,在 _standardize_user_data 中 exception_prefix='target') 文件 "/home/steve/Documents/cnn/env/local/lib/python2.7/site-packages/keras/engine/training.py", 第 128 行,在 _standardize_input_data 中 str(array.shape)) ValueError: 检查目标时出错:预期activation_5 有 3 个维度,但得到了形状为 (1000, 1) 的数组

【问题讨论】:

    标签: python machine-learning neural-network keras convolution


    【解决方案1】:

    在我看来,您需要在谷歌上搜索更多关于卷积网络的信息 :-)

    您在每个步骤中对您的序列应用 32 个长度为 2 的过滤器。因此,如果我们在每一层之后遵循张量的维度:

    维度:(无、32、1)

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

    尺寸:(无、31、32) (长度为 2 的过滤器遍历整个序列,因此序列现在的长度为 31)

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

    尺寸:(无、30、32) (由于长度为 2 的过滤器,您再次丢失了一个值,但您仍然有 32 个)

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

    尺寸:(无、29、32) (同样...)

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

    尺寸:(无、28、32)

    现在您想在其上使用 Dense 层...问题是 Dense 层将在您的 3D 输入上按以下方式工作:

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

    尺寸:(无、28、32)

    这是你的输出。我觉得奇怪的第一件事是你想要从密集层中输出 32 个输出......你应该放 1 而不是 32。但即使这样也不能解决你的问题。看看如果我们改变最后一层会发生什么:

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

    维度:(无、28、1)

    发生这种情况是因为您将密集层应用于“2D”张量。如果您将密集(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'))
    

    现在最后两步将从

    中获取您的张量

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

    希望对你有帮助。

    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 并找到不同的values possible for the padding argument here。我鼓励您阅读最后一个链接,它提供了有关输入和输出形状的信息...

    来自文档:

    填充:“有效”或“相同”之一(不区分大小写)。 “有效”表示“无填充”。 “相同”导致填充输入,以使输出与原始输入具有相同的长度。

    默认值为“有效”,因此您无需在示例中填充。

    我还建议您将 keras 版本升级到最新版本。 Convolution1D 现在是 Conv1D,因此您可能会发现文档和教程令人困惑。

    【讨论】:

    • 谢谢!!我明白为什么我现在遇到维度问题了。我不明白为什么卷积步骤会丢失一个字节?在我看来,卷积正在穿过行,并且对于每个 x,它都将其与自身以及每个其他 x 进行卷积。所以在我心目中的代码中,这就像一个嵌套的 for 循环迭代同一个数组两次
    • 我已经编辑了我的答案,提供了更多关于此的信息:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-21
    • 1970-01-01
    • 2016-12-04
    • 1970-01-01
    相关资源
    最近更新 更多