featureMap的大小有什么规律,怎么计算呢?
padding就是扩充图片,在输入图片外围补充一些像素点,并初始化为0。目的是保持feature map 不要太小。
Tensorflow中的填充只有两种类型:SAME:是填充;VALID:是不填充。
# VALID 对应的是不填充,即不做任何处理。
# SAME 这种填充方式在strides=1的情况下,使得输出能够保持和输入尺寸一致。Theano中的填充则有不填充、半填充、全填充三种,它的半填充对应Tensorflow的SAME。
总结公式:
设输入为W,卷积核F,池化核K,步幅S, 填充P(VALID时为0,SAME时为1)。
卷积层输出:
Padding='SAME',输出尺寸为: ceil(W / S)
Padding='VALID',P=0,输出尺寸为:(W+2P-F)/S + 1
池化层输出:
Padding='SAME',P=1,输出尺寸为: ceil(W / S)
Padding='VALID',P=0,输出尺寸为:(W+2P-K)/S + 1。
测试过程:
直接命令行依次操作即可,
print输出类似:Tensor("Relu:0", shape=(?, 28, 28, 32), dtype=float32)
import tensorflow as tf
x_image = tf.placeholder(tf.float32, [None, 28, 28, 1])
W_conv1 = tf.Variable(tf.truncated_normal([5,5,1,32], stddev=0.1))
b_conv1 = tf.Variable(tf.constant(0.1, shape=[32]))
h_conv1 = tf.nn.relu(tf.nn.conv2d(x_image, W_conv1, strides=[1, 1, 1, 1], padding='SAME') + b_conv1)
print(h_conv1)
#shape=(?, 28, 28, 32), 其中W=28,S=1, 所以28 = ceil(28/1)
h_pool1 = tf.nn.max_pool(h_conv1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
#shape=(?, 14, 14, 32), W=28,strides的S=2, 所以14 = ceil(28/2) = 14
##----------------
## x_image = tf.placeholder(tf.float32, [None, 28, 28, 1])
## W_conv1和b_conv1不变
h_conv1_valid = tf.nn.relu(tf.nn.conv2d(x_image, W_conv1, strides=[1, 1, 1, 1], padding='VALID') + b_conv1)
# shape=(?, 24, 24, 32),输入W=28,W_conv1的F=5,P=0,S=1, 所以(28 + 2*0 - 5)/1 + 1 = 24
h_pool1_valid = tf.nn.max_pool(h_conv1_valid, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='VALID')
# shape=(?, 12, 12, 32),输入W=24,ksize的K=2,P=0,S=2, 所以(24+2*0-2)/2 + 1 = 12
## 在h_pool1之后加第二层卷积:
W_conv2 = tf.Variable(tf.truncated_normal([5, 5, 32, 64], stddev=0.1))
b_conv2 = tf.Variable(tf.constant(0.1, shape=[64]))
输入shape=(?, 14, 14, 32)
h_conv2 = tf.nn.relu(tf.nn.conv2d(h_pool1, W_conv2, strides=[1, 1, 1, 1], padding='SAME') + b_conv2)
输出shape=(?, 14, 14, 64) W=14,S=1, 所以14=(14/1)
输入h_pool1,如果padding='VALID':
h_conv2_valid = tf.nn.relu(tf.nn.conv2d(h_pool1, W_conv2, strides=[1, 1, 1, 1], padding='VALID') + b_conv2)
输出shape=(?, 10, 10, 64) W=14,P=0,F=5,S=1, 所以(14+0-5)/1+1=10
# h_conv2之后加一层池化:
输入h_conv2的shape=(?, 14, 14, 64)
h_pool2 = tf.nn.max_pool(h_conv2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
输出shape=(?, 7, 7, 64),输入W=14, strides的S=2, 所以 ceil(14/2) = 7
输入h_conv2,如果padding='VALID':
h_pool2 = tf.nn.max_pool(h_conv2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='VALID')
输出shape=(?, 7, 7, 64),W=14,P=0,K=2,S=2, 所以(W+2P-K)/S+1 = (14-2)/2+1 = 7
参考:
https://zhuanlan.zhihu.com/p/36278093
https://blog.csdn.net/qq_26552071/article/details/81171161
https://flat2010.github.io/2018/06/15/%E6%89%8B%E7%AE%97CNN%E4%B8%AD%E7%9A%84%E5%8F%82%E6%95%B0/