我正在尝试在Keras中实现对称填充层,就像Caffe实施该填充层一样,我遇到了一个奇怪的问题。
假设我们有一个带有1x1280x1280x3
个通道的3
图像,并且我们想对其进行卷积,以便它返回一个{{1} }频道。在Caffe中,我们可以在卷积层中直接设置1x320x320x96
参数:
96
如果您尝试使用Caffe进行编译,则输出pad
的形状确实为input: "image"
input_shape {
dim: 1
dim: 3
dim: 1280
dim: 1280
}
layer {
name: "conv1"
type: "Convolution"
bottom: "image"
top: "conv1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 96
kernel_size: 11
pad: 5 # Padding parameter
stride: 4
}
}
layer {
name: "relu1"
type: "ReLU"
bottom: "conv1"
top: "conv1"
}
。
现在让我们使用conv1
和1x320x320x96
层对Keras进行相同的尝试:
tf.pad
问题:
如果我们测量以上代码中定义的Lambda
的形状,它将是from keras.layers import Input, Lambda
import tensorflow as tf
image = Input(shape=(1280, 1280, 3),
dtype='float32',
name='image')
sym_pad = Lambda(lamda x: tf.pad(x, [[0, 0], [0, 5], [0, 5], [0, 0]])) # padding = 5
conv1 = Conv2D(filters=96,
kernel_size=11,
strides=(4, 4),
activation=relu,
padding='valid', # valid instead of 'same'
name='conv1')(image)
而不是conv1
。
但是,如果我们增加1x319x319x96
的填充,请使用1x320x320x96
填充而不是2
,如下所示:
7x7
当我们传递带有5x5
而不是sym_pad = Lambda(lamda x: tf.pad(x, [[0, 0], [0, 5+2], [0, 5+2], [0, 0]])) # padding = 7
形状的conv1
填充输入时, 1x320x320x96
将具有期望的形状image
(注意,只有偶数形图像上的奇数填充会改变卷积的形状,这可能与步幅有关。
为什么会这样? Caffe是否将每个填充参数自动增加1x1287x1287x3
?还是我做错了什么?
谢谢!
P.S
我知道Keras层中的1x1285x1285x3
参数,但是我正在寻找对称填充而不是非对称填充。
答案 0 :(得分:2)
如果您正在谈论对称填充,那么我假设您想在图像的左侧和右侧填充相同数量的像素(顶部和底部相同)。 tf.pad
当前正在执行的操作是在右侧填充5个像素,在底部填充5个像素。因此,从理论上来说,您要在两边填充2.5像素。
输出形状如下:
floor((input_size-kernel_size+2*padding_size)/stride_size) + 1
因此,在您的情况下,填充2.5像素时会产生319的输出形状。 如果您在两侧都填充5个像素,则可以得到320的期望值。
答案 1 :(得分:2)
在您的示例中,将输入仅填充到底部和右侧。使用:
sym_pad = Lambda(lamda x: tf.pad(x, [[0, 0], [5, 5], [5, 5], [0, 0]]))
获得与Caffe相同的填充。