二、RGB图片的卷积操作¶
1、RGB图像的立方体卷积
对于一个6∗6∗36∗6∗3的彩色图片,有三个通道,filter需要对应扫描每一个通道,所以图片有几个通道,filter就要有几个通道。
把一个filter视为一个立方体去扫描RGB图片,立方体对应位置的数值像矩阵一样做乘法,得到对应位置的一个值,扫描整张图片,得到4∗44∗4的
2、多个卷积操作
????????∗??????=????????
????????=(?−?+1)∗(?−?+1)∗??
相应的有stride和padding操作时,输出结果也会有对应的改变:????????=((?+2?−?)/?)+1)∗((?+2?−?)/?)+1)∗??
三、单层卷积层
卷积神经网络的一层:输入一张三通道RBG图片,用两个相同尺寸的卷积核对图像进行卷积,得到两张特征图,线性的卷积结果需要加上偏置项,一个卷积核对应一组权重参数,需要加上一个偏置项,因此有几个卷积核就加几个偏置项。再使用非线性激活函数处理,使结果非线性化,得到输出 ????(????+?)
四、池化
1、池化层
池化的作用在于缩减模型的规模,提升计算速度,提高特征提取的鲁棒性
池化具有两种方式:Max Pooling与Average Pooling
池化操作也可以视为一个卷积核的扫描,它的超参数为尺寸f与步长s,其中超参数就是人为直接设定不需要学习的参数,只是卷积核的操作不再是做矩阵乘法,而是一个max操作,取区域内最大值
最大池化的操作帮助我们缩减了图像的大小,同时保留了每个区域最为突出的特征
对于多通道的图像,池化窗口会在每一个通道进行操作,每一个通道的特征图池化结果相互独立,最终不会改变图像的通道数量
还有一种池化方式,叫做平均池化,和最大池化操作类似,只是每个元素是取相应区域元素的平均值,一般来说最大池化用的更多。
对于图像数据,数字越大意味着特征越明显,做最大池化则是保留池化窗口对应区域最明显的特征,从而增强该特征的稳定性,当某区域不存在该特征时,即使取了最大值,这个最大值还是很小,因此最大池化更多的保留图像纹理信息。
当做平均池化的时候,取池化窗口内的平均值,扫描到的图像特征值可能会被特征边缘的较小值弱化,因此平均池化更多的保留图像的背景信息
因此在图像识别与分类中,更多的会使用到最大池化,此方法在很多实验中效果都很好。
2、池化层的代码实现
tf.nn.avg_pool(value,ksize,strides,padding,data_format,name)
tf.nn.max_pool(value,ksize,strides,padding,data_format,name)
参数是四个,和卷积很类似:
第一个参数value:需要池化的输入,一般池化层接在卷积层后面,依然是[batch, height, width, channels]这样的shape
第二个参数ksize:池化窗口的大小,取一个四维向量,一般是[1, height, width, 1],因为我们不想在batch和channels上做池化,所以这两个维度设为了1
第三个参数strides:和卷积类似,窗口在每一个维度上滑动的步长,一般也是[1, stride,stride, 1]
第四个参数padding:和卷积类似,可以取'VALID' 或者'SAME'
返回一个Tensor,类型不变,shape仍然是[batch, height, width, channels]这种形式
1. tf.nn.max_pool举例
#tf.nn.max_pool举例
import tensorflow as tf
a=tf.constant([
[[1.0,2.0,3.0,4.0],
[5.0,6.0,7.0,8.0],
[8.0,7.0,6.0,5.0],
[4.0,3.0,2.0,1.0]],
[[4.0,3.0,2.0,1.0],
[8.0,7.0,6.0,5.0],
[1.0,2.0,3.0,4.0],
[5.0,6.0,7.0,8.0]]
])
a=tf.reshape(a,[1,4,4,2])
pooling=tf.nn.max_pool(a,[1,2,2,1],[1,1,1,1],padding='VALID')
with tf.Session() as sess:
print("image:")
image=sess.run(a)
print (image)
print("reslut:")
result=sess.run(pooling)
print (result)
import tensorflow as tf
import numpy as np
M = np.array([[[-2],[2],[0],[3]],
[[1],[2],[-1],[2]],
[[0],[-1],[1],[0]]],dtype="float32").reshape(1, 3, 4, 1)
filter_weight = tf.get_variable("weights",[2, 2, 1, 1],initializer = tf.constant_initializer([[2, 0],[-1, 1]]))
biases = tf.get_variable('biases', [1], initializer = tf.constant_initializer(1))
x = tf.placeholder('float32', [1, None, None, 1])
conv = tf.nn.conv2d(x, filter_weight, strides=[1, 1, 1, 1], padding="SAME")
add_bias = tf.nn.bias_add(conv, biases)
#max_pool()函数实现了最大池化层的前向传播过程
#原型为max_pool(value,strides,padding,data_format,name)
#参数value为输入数据,strides为提供了步长信息,padding提供了是否使用全0填充。
pool1 = tf.nn.max_pool(add_bias, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")
pool2 = tf.nn.max_pool(add_bias, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="VALID")
with tf.Session() as sess:
tf.global_variables_initializer().run()
M_conv = sess.run(add_bias, feed_dict={x: M})
M_pool1 = sess.run(pool1, feed_dict={x: M})
M_pool2 = sess.run(pool2, feed_dict={x: M})
print("M after convolution: \n", M_conv)
print(" after max pooled1: \n", M_pool1)
print(" after max pooled2: \n", M_pool2)