卷积函数使用实战

一 实例描述
通过手动生成一个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)]

猜你喜欢

转载自blog.csdn.net/chengqiuming/article/details/80288902