在tensorflow对图片的卷积操作,常用到2D卷积层Conv2D与2D反卷积层Conv2DTranspose。
这些卷积层中都有两个个padding方式,“same"与"valid”
same 保持输入输出宽高一致
公式:
Conv2D : W = ceil(W`/S)
Conv2DTranspose : W = W`*S
W`: 输入宽或高
S: strides 步长
ceil:向上取整
import tensorflow as tf
x = tf.random.normal((2,7,7,1))
x.shape # TensorShape([2, 7, 7, 1])
cx0 = tf.keras.layers.Conv2D(4,kernel_size=3,strides=2,padding='same',use_bias=False)(x)
cx0.shape # W = ceil(W`/S) = ceil(7/2) = 4
# TensorShape([2, 4, 4, 4])
x0 = tf.keras.layers.Conv2DTranspose(64*8,4,3,'same',use_bias=False)(cx0)
x0.shap # W = W`*S = 4*3 = 12
# TensorShape([2, 12, 12, 512])
same填充方式下
对于Conv2D:
输入宽高为 7x7,strides=1则输出还是7x7,如果strides=2,则输出为(72)x(72) = 14*14
对于Conv2DTranspose:
输入宽高为 7x7,strides=1则输出还是7x7,如果strides=2,则输出为ceil(7/2)xceil(7/2) = 4x4
valid 不填充
对于Conv2D的计算公式为:
W = ceil((W`-F+1)/S)
对于Conv2DTranspose的计算公式为:
W = (W`-1)*S + F
其中:
W` : 输入的宽或高
F:宽高对应kernal_size值
S:strides 步长
x = tf.random.normal((2,7,7,1))
x.shape # TensorShape([2, 7, 7, 1])
c1 = tf.keras.layers.Conv2D(32,kernel_size=3,strides=1,'valid',use_bias=False)(x)
c1.shape # W = ceil((W`-F+1)/S) = ceil((7-3+1)/1) = 5
# TensorShape([2, 5, 5, 32])
c2 = tf.keras.layers.Conv2D(32,3,2,'valid',use_bias=False)(x)
c2.shape # = ceil((W`-F+1)/S) = ceil((7-3+2)/2) = 3
# TensorShape([2, 3, 3, 32])
x1 = tf.keras.layers.Conv2DTranspose(4,kernel_size=3,strides=1,'valid',use_bias=False)(x)
x1.shape # W = (W`-1)*S + F = (7-1)*1 + 3 = 9
# TensorShape([2, 9, 9, 512])
x2 = tf.keras.layers.Conv2DTranspose(64*8,3,2,'valid',use_bias=False)(x)
x2.shape # W = (W`-1)*S + F = (7-1)*2 + 3 = 15
# TensorShape([2, 15, 15, 512])
valid不填充
对于Conv2D:
输入宽高为 7x7,kernel_size=3 ,strides=1则输出为ceil((W`-F+1)/S) =ceil((7-3+1)/1) =5 宽高一样都是7所有输出是 5x5 ,如果strides=2,则输出为ceil((7-3+2)/2) =3, 输出为 3x3
对于Conv2DTranspose:
输入宽高为 7x7,kernel_size=3,strides=1则输出为(W`-1)*S + F = (7-1)*1+3=9,输出为9x9.如果strides=2,则输出为(7-1)*2+3=15,输出为15x15
总结
对于same模式,只受strides步长影响输出尺寸。
对于valid模式,不仅受到strides影响而且也受到卷积核尺寸kernel_size的影响。
在两种模式下Conv2D与Conv2DTranspose计算输出尺寸方法都不一样。