我需要帮助将自定义权重设置为用于2D卷积的小型自定义Keras模型。我有一个看起来像这样的输入:
X = [[[3, 2, -4],
[0, 5, 4],
[2, -1, -7],
[-7, 0, 1]],
[[-8, 9, 1],
[-3, 6, 0],
[0, -4, 2],
[5, 1, 1]]]
因此,可以想象只有两个通道的4x3图像。我的内核看起来像这样:
kernel = [[[2, 1],
[0, -1],
[0, -1]],
[[1, 2],
[2, -1],
[2, -2]]]
所以,一个二维3x2内核。手动执行2D卷积,步长为1且无填充,产生:
[[10, 14],
[27, 16]]
不幸的是,以下Keras代码:
model = Sequential()
conv2d = Conv2D(filters=1, kernel_size=(3,2), strides=1, input_shape=(2,4,3), use_bias=False)
model.add(conv2d)
layer = model.layers[0]
layer.set_weights([np.array(kernel).reshape(3, 2, 2, 1)])
print(model.predict(np.array(X).reshape((1,) + np.shape(X))))
输出:
[[19, -6],
[-39, 16]]
我无法弄清楚Keras如何为卷积组织其内核。到目前为止,看起来非常违反直觉,但我可能错过了一些东西。
我使用Keras 2.0.9和Tensorflow 1.4.0作为后端。
答案 0 :(得分:4)
keras中的内核遵循以下形式:(height, width, input_channels, output_channels)
- 即使您正在使用channels_first
。
您认为它使用形状(3,2,2,1)
但是您的手动计算正在考虑倒置形状。在您的手动计算中,您使用(input_channels, height, width)
。
当您reshape
内核时,您并未正确重新排序这些维度。重新塑造并不等同于"转置"数组。重塑只是重新组合数据而不进行任何重新排序。
要在keras中获得正确的结果,您需要正确交换轴:
#start as (input_channels, height, width) = (2,3,2)
kernel = np.array([[[2, 1],
[0, -1],
[0, -1]],
[[1, 2],
[2, -1],
[2, -2]]])
#change to (height, input_channels, width) = (3,2,2)
kernel = kernel.swapaxes(0,1)
#change to (height, width, input_channels) = (3,2,2)
kernel = kernel.swapaxes(1,2)
#add output_channels
kernel = kernel.reshape((3,2,2,1))