一 实例描述
通过手动生成一个5*5的矩阵来模拟图片,定义一个2*2的卷积核,来测试tf.nn.conv2d函数里的不同参数,验证其结果
在这个例子中,分为如下几个步骤
1 定义输入变量
2 定义卷积核变量
3 定义卷积操作
4 运行卷积操作
二 代码
import tensorflow as tf ''' 定义输入变量 定义3个输入变量用来模拟输入图片,分别是5*5大小的1通道矩阵、5*5大小的2通道矩阵、4*4通道的矩阵,并将里面的值都赋值为1 ''' # [batch, in_height, in_width, in_channels] [训练时一个batch的图片数量, 图片高度, 图片宽度, 图像通道数] input = tf.Variable(tf.constant(1.0,shape = [1, 5, 5, 1])) input2 = tf.Variable(tf.constant(1.0,shape = [1, 5, 5, 2])) input3 = tf.Variable(tf.constant(1.0,shape = [1, 4, 4, 1])) '''定义卷积 定义5个卷积核,每个卷积核都是2*2的矩阵,只是出入和输出通道数有差别,分别为1ch输入、1ch输出,1ch输入、2ch输出,1ch输入、3ch输出,2ch输入、2ch输出,2ch输入、1ch输出,并分别在里面填入指定的数值 ''' # [filter_height, filter_width, in_channels, out_channels] [卷积核的高度,卷积核的宽度,图像通道数,卷积核个数] filter1 = tf.Variable(tf.constant([-1.0,0,0,-1],shape = [2, 2, 1, 1])) filter2 = tf.Variable(tf.constant([-1.0,0,0,-1,-1.0,0,0,-1],shape = [2, 2, 1, 2])) filter3 = tf.Variable(tf.constant([-1.0,0,0,-1,-1.0,0,0,-1,-1.0,0,0,-1],shape = [2, 2, 1, 3])) filter4 = tf.Variable(tf.constant([-1.0,0,0,-1, -1.0,0,0,-1, -1.0,0,0,-1, -1.0,0,0,-1],shape = [2, 2, 2, 2])) filter5 = tf.Variable(tf.constant([-1.0,0,0,-1,-1.0,0,0,-1],shape = [2, 2, 2, 1])) ''' 按步骤1的输入和步骤2的卷积核组合起来,建立8个卷积操作,看看生成的内容与前面讲述的规则是否一致。 这些卷积操作演示了 1 演示padding补0的情况 2 演示多通道输出时的内存排列 3 演示卷积核对多通道输入的卷积处理 4 验证不同尺寸受padding未SAME和VALID的影响 ''' # padding的值为‘VALID’,表示边缘不填充, 当其为‘SAME’时,表示填充到卷积核可以到达图像边缘 op1 = tf.nn.conv2d(input, filter1, strides=[1, 2, 2, 1], padding='SAME') #1个通道输入,生成1个feature ma op2 = tf.nn.conv2d(input, filter2, strides=[1, 2, 2, 1], padding='SAME') #1个通道输入,生成2个feature map op3 = tf.nn.conv2d(input, filter3, strides=[1, 2, 2, 1], padding='SAME') #1个通道输入,生成3个feature map op4 = tf.nn.conv2d(input2, filter4, strides=[1, 2, 2, 1], padding='SAME') # 2个通道输入,生成2个feature op5 = tf.nn.conv2d(input2, filter5, strides=[1, 2, 2, 1], padding='SAME') # 2个通道输入,生成一个feature map vop1 = tf.nn.conv2d(input, filter1, strides=[1, 2, 2, 1], padding='VALID') # 5*5 对于pading不同而不同 op6 = tf.nn.conv2d(input3, filter1, strides=[1, 2, 2, 1], padding='SAME') vop6 = tf.nn.conv2d(input3, filter1, strides=[1, 2, 2, 1], padding='VALID') #4*4与pading无关 ''' 运行卷积操作的结果 ''' init = tf.global_variables_initializer() with tf.Session() as sess: sess.run(init) print("op1:\n",sess.run([op1,filter1]))#1-1 后面补0 print("------------------") print("op2:\n",sess.run([op2,filter2])) #1-2多卷积核 按列取 print("op3:\n",sess.run([op3,filter3])) #1-3 print("------------------") print("op4:\n",sess.run([op4,filter4]))#2-2 通道叠加 print("op5:\n",sess.run([op5,filter5]))#2-1 print("------------------") print("op1:\n",sess.run([op1,filter1]))#1-1 print("vop1:\n",sess.run([vop1,filter1])) print("op6:\n",sess.run([op6,filter1])) print("vop6:\n",sess.run([vop6,filter1]))
三 运行结果
op1:
[array([[[[-2.],
[-2.],
[-1.]],
[[-2.],
[-2.],
[-1.]],
[[-1.],
[-1.],
[-1.]]]], dtype=float32), array([[[[-1.]],
[[ 0.]]],
[[[ 0.]],
[[-1.]]]], dtype=float32)]
------------------
op2:
[array([[[[-2., -2.],
[-2., -2.],
[-2., 0.]],
[[-2., -2.],
[-2., -2.],
[-2., 0.]],
[[-1., -1.],
[-1., -1.],
[-1., 0.]]]], dtype=float32), array([[[[-1., 0.]],
[[ 0., -1.]]],
[[[-1., 0.]],
[[ 0., -1.]]]], dtype=float32)]
op3:
[array([[[[-2., -2., -2.],
[-2., -2., -2.],
[-1., -1., -1.]],
[[-2., -2., -2.],
[-2., -2., -2.],
[-1., -1., -1.]],
[[-2., -1., 0.],
[-2., -1., 0.],
[-1., 0., 0.]]]], dtype=float32), array([[[[-1., 0., 0.]],
[[-1., -1., 0.]]],
[[[ 0., -1., -1.]],
[[ 0., 0., -1.]]]], dtype=float32)]
------------------
op4:
[array([[[[-4., -4.],
[-4., -4.],
[-2., -2.]],
[[-4., -4.],
[-4., -4.],
[-2., -2.]],
[[-2., -2.],
[-2., -2.],
[-1., -1.]]]], dtype=float32), array([[[[-1., 0.],
[ 0., -1.]],
[[-1., 0.],
[ 0., -1.]]],
[[[-1., 0.],
[ 0., -1.]],
[[-1., 0.],
[ 0., -1.]]]], dtype=float32)]
op5:
[array([[[[-4.],
[-4.],
[-2.]],
[[-4.],
[-4.],
[-2.]],
[[-2.],
[-2.],
[-1.]]]], dtype=float32), array([[[[-1.],
[ 0.]],
[[ 0.],
[-1.]]],
[[[-1.],
[ 0.]],
[[ 0.],
[-1.]]]], dtype=float32)]
------------------
op1:
[array([[[[-2.],
[-2.],
[-1.]],
[[-2.],
[-2.],
[-1.]],
[[-1.],
[-1.],
[-1.]]]], dtype=float32), array([[[[-1.]],
[[ 0.]]],
[[[ 0.]],
[[-1.]]]], dtype=float32)]
vop1:
[array([[[[-2.],
[-2.]],
[[-2.],
[-2.]]]], dtype=float32), array([[[[-1.]],
[[ 0.]]],
[[[ 0.]],
[[-1.]]]], dtype=float32)]
op6:
[array([[[[-2.],
[-2.]],
[[-2.],
[-2.]]]], dtype=float32), array([[[[-1.]],
[[ 0.]]],
[[[ 0.]],
[[-1.]]]], dtype=float32)]
vop6:
[array([[[[-2.],
[-2.]],
[[-2.],
[-2.]]]], dtype=float32), array([[[[-1.]],
[[ 0.]]],
[[[ 0.]],
[[-1.]]]], dtype=float32)]
四 结果说明
1 op1和filter1的输出如下,为了看起来方便,将格式进行了整理
op1:
[array([[[[-2.],
[-2.],
[-1.]],
[[-2.],
[-2.],
[-1.]],
[[-1.],
[-1.],
[-1.]]]], dtype=float32),
array([[[[-1.]],
[[ 0.]]],
[[[ 0.]],
[[-1.]]]], dtype=float32)]
上面输出中5*5矩阵通过卷积操作生成3*3矩阵,对padding的补0情况是在后面和下面补0
2 op2和filter2,op3和filter3的输出如下
op2:
[array([[[[-2., -2.],
[-2., -2.],
[-2., 0.]],
[[-2., -2.],
[-2., -2.],
[-2., 0.]],
[[-1., -1.],
[-1., -1.],
[-1., 0.]]]], dtype=float32),
array([[[[-1., 0.]],
[[ 0., -1.]]],
[[[-1., 0.]],
[[ 0., -1.]]]], dtype=float32)]
op3:
[array([[[[-2., -2., -2.],
[-2., -2., -2.],
[-1., -1., -1.]],
[[-2., -2., -2.],
[-2., -2., -2.],
[-1., -1., -1.]],
[[-2., -1., 0.],
[-2., -1., 0.],
[-1., 0., 0.]]]], dtype=float32),
array([[[[-1., 0., 0.]],
[[-1., -1., 0.]]],
[[[ 0., -1., -1.]],
[[ 0., 0., -1.]]]], dtype=float32)]
3 op4和filter4,op5和filter6的输出如下
卷积核对多通道输入的卷积处理,是多通道的结果叠加,以op5为例展开。是将每个通道的feature map叠加生成了最终的结果。
op4:
[array([[[[-4., -4.],
[-4., -4.],
[-2., -2.]],
[[-4., -4.],
[-4., -4.],
[-2., -2.]],
[[-2., -2.],
[-2., -2.],
[-1., -1.]]]], dtype=float32),
array([[[[-1., 0.],
[ 0., -1.]],
[[-1., 0.],
[ 0., -1.]]],
[[[-1., 0.],
[ 0., -1.]],
[[-1., 0.],
[ 0., -1.]]]], dtype=float32)]
op5:
[array([[[[-4.],
[-4.],
[-2.]],
[[-4.],
[-4.],
[-2.]],
[[-2.],
[-2.],
[-1.]]]], dtype=float32),
array([[[[-1.],
[ 0.]],
[[ 0.],
[-1.]]],
[[[-1.],
[ 0.]],
[[ 0.],
[-1.]]]], dtype=float32)]
4 op1 vop1 op6 vop6结果对比
op1:
[array([[[[-2.],
[-2.],
[-1.]],
[[-2.],
[-2.],
[-1.]],
[[-1.],
[-1.],
[-1.]]]], dtype=float32),
array([[[[-1.]],
[[ 0.]]],
[[[ 0.]],
[[-1.]]]], dtype=float32)]
vop1:
[array([[[[-2.],
[-2.]],
[[-2.],
[-2.]]]], dtype=float32),
array([[[[-1.]],
[[ 0.]]],
[[[ 0.]],
[[-1.]]]], dtype=float32)]
op6:
[array([[[[-2.],
[-2.]],
[[-2.],
[-2.]]]], dtype=float32),
array([[[[-1.]],
[[ 0.]]],
[[[ 0.]],
[[-1.]]]], dtype=float32)]
vop6:
[array([[[[-2.],
[-2.]],
[[-2.],
[-2.]]]], dtype=float32),
array([[[[-1.]],
[[ 0.]]],
[[[ 0.]],
[[-1.]]]], dtype=float32)]