首页 文章

卷积层不匹配中的Keras维数

提问于
浏览
1

我正在尝试与Keras一起构建我的第一个神经网络 . 我没有经验,我似乎无法弄清楚为什么我的维度不对 . 我无法从他们的文档中弄清楚这个错误是抱怨什么,甚至是什么层导致它 .

我的模型接受一个32字节的数字数组,并且应该在另一侧给出一个布尔值 . 我想在输入字节数组上进行一维卷积 .

arr1是32byte数组,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行,在fit initial_epoch = initial_epoch中)文件”/home/steve/Documents/cnn/env/local/lib/python2.7/site-packages/keras/engine/training.py“,第1358行,in fit 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)

1 回答

  • 2

    那么在我看来,你需要谷歌更多关于卷积网络:-)

    您将在每个步骤中应用32个长度为2的过滤器 . 因此,如果我们在每一层之后遵循张量的尺寸:

    Dimensions : (None, 32, 1)

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

    Dimensions : (None, 31, 32) (您的长度为2的过滤器遍历整个序列,因此序列现在的长度为31)

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

    Dimensions : (None, 30, 32) (由于您的长度为2的过滤器,您再次失去一个值,但您仍然有32个)

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

    Dimensions : (None, 29, 32) (同......)

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

    Dimensions : (None, 28, 32)

    现在你想在它上面使用Dense图层...事实是Dense图层将在你的3D输入上如下工作:

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

    Dimensions : (None, 28, 32)

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

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

    Dimensions : (None, 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'))
    

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

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

    我希望这可以帮助你 .

    PS . 如果你想知道什么是无,那就是批次的维度,你没有在onces上提供1000个样本,你逐批地提供它,并且因为值取决于所选择的内容,所以我们把无 .

    EDIT :

    更详细地解释为什么序列长度在每一步失去一个值 .

    假设您有一个4个值的序列 [x1 x2 x3 x4] ,您希望使用长度为2 [f1 f2] 的过滤器来对序列进行卷积 . 第一个值将由 y1 = [f1 f2] * [x1 x2] 给出,第二个值为 y2 = [f1 f2] * [x2 x3] ,第三个值为 y3 = [f1 f2] * [x3 x4] . 然后你到达序列的末尾,不能再往前走了 . 你有一个sequnce [y1 y2 y3] 的结果 .

    这是由于过滤器长度和序列边界的影响 . 有多个选项,有些选项用0填充序列以获得完全相同的输出长度...您可以使用参数 'padding' 选择该选项 . 你可以read more about this here找到不同的values possible for the padding argument here . 我鼓励你阅读最后一个链接,它提供有关输入和输出形状的信息......

    从文档:

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

    默认值为“有效”,因此您不需要填写示例 .

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

相关问题