很多地方已讲解得十分详细,在这里把自己的理解用几句话记录下来以后回顾用。
tf.nn.conv2d()简介
TensorFlow中函数conv2d主要实现了输入张量与设定卷积核的卷积操作,其函数形式如下:
tf.nn.conv2d(
input,
filter,
strides,
padding,
use_cudnn_on_gpu=True,
data_format='NHWC',
dilations=[1, 1, 1, 1],
name=None
)
1.input,filter是设定的输入和卷积核,参数strides,padding分别决定了卷积操作中滑动步长和图像边沿填充的方式。
2.参数 strides = [1, strides[1], strides[2], strides[3]]
为长度为4的一阶张量,并且要求strides[0]=strides[3]=1,strides[1],strides[2]决定卷积核在输入图像in_hight,in_width方向的滑动步长。
3.参数padding
为什么要有padding?
卷积核的大小和图像的大小有时候不是完全匹配,再考虑到滑动步长strides,需要在边界填充数值。padding参数的两个值SAME,VALID决定了其填充方式。
重点
关于padding设置成SAME、VALID后不同的工作方式如何不重要,
我只想知道最后输出的feature map尺寸size如何。
先上几句话结论:
output_size=( input_size + padding * 2 - conv_size ) / strides + 1
得出的结果若是小数,就取其整数部分
padding=‘SAME’ —> padding =1 ;
padding=‘VALID’ —> padding = 0.
想求长或是宽的output_size,input_size、conv_size就代入长或宽,当然大多情况下都一样。
(按照CNN的理论知识:feature map的size会有4个值,首尾的值分别代表输入的样本个数和输出多少个feature map,需要求的output_size是指中间位置的2个值)
看如下代码示例:
情况1:公式计算的结果本身就是整数
padding = ‘SAME’
// output_size=( input_size + padding * 2 - conv_size ) / strides + 1
// 公式计算的结果本身就是整数
// (5 + 2 * 1 - 3)/1 + 1 = 5
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()
input = tf.Variable(tf.ones([1,5,5,1]))
# 第一个'1'指样本个数,相当于xs = tf.placeholder(tf.float32,[None,25])中的None;后面的'1'指channel是1通道(RGB的话就是3);25=5*5
filter = tf.Variable(tf.ones([3,3,1,1]))
# 3*3指卷积核size,前一个'1'指一个卷积核,因为输入就1个channel;后一个'1'指设定输出的feature_map有1个,自己设置的,一般64,128...
op = tf.nn.conv2d(input,filter,strides=[1,1,1,1],padding='SAME')
# strides默认其为长度为4的一阶张量,并且要求strides[0]=strides[3]=1,strides[1],strides[2]决定卷积核在输入图像in_hight,in_width方向的滑动步长
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print(sess.run(op).shape)
print('-'*33)
print(sess.run(op))
// sess.run(op).shape 为 (1, 5, 5, 1)
padding = ‘VALID’
// 设置参数padding='VALID'后,结果为 (1, 3, 3, 1)
// (5 + 2 * 0 - 3)/1 + 1 = 3
情况2:公式计算的结果是小数
padding = ‘SAME’
// output_size=( input_size + padding * 2 - conv_size ) / strides + 1
// 公式计算的结果是小数
// (28 + 2 * 1 - 3)/2 + 1 = 14.5
// 取计算结果整数部分 14
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()
input = tf.Variable(tf.ones([1,28,28,1]))
filter = tf.Variable(tf.ones([3,3,1,1]))
op = tf.nn.conv2d(input,filter,strides=[1,2,2,1],padding='SAME')
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print(sess.run(op).shape)
print('-'*33)
print(sess.run(op))
// sess.run(op).shape 为(1, 14, 14, 1)
padding = ‘VALID’
// 设置参数padding='VALID'后,结果为 (1, 13, 13, 1)
// (28 + 2 * 0 - 3)/2 + 1 = 13.5
// 取整数部分 13
参考:https://blog.csdn.net/wangpengfei163/article/details/80987145?spm=1001.2014.3001.5506