卷积神经网络,相邻两层之间只有部分节点相连,相比于全连接神经网络,参数个数会少的多,计算量能大大的减少。

一:TensorFlow卷积层的简单实现
# 通过tf.get_variable的方式创建过滤器的权重变量和偏置项变量。上面介绍了卷积层
# 的参数个数只和过滤器的尺寸、深度以及当前层节点矩阵的深度有关,所以这里声明的参数变
# 量是一个四维矩阵,前面两个维度代表了过滤器的尺寸,第三个维度表示当前层的深度,第四
# 个维度表示过滤器的深度。
filter_weight = tf.get_variable(
'weights', [5, 5, 3, 16],
initializer=tf.truncated_normal_initializer(stddev=0.1))
# 和卷积层的权重类似,当前层矩阵上不同位置的偏置项也是共享的,所以总共有下一层深度个不
# 同的偏置项。本样例代码中16为过滤器的深度,也是神经网络中下一层节点矩阵的深度。
biases = tf.get_variable(
'biases', [16], initializer=tf.constant_initializer(0.1))
# tf.nn.conv2d提供了一个非常方便的函数来实现卷积层前向传播的算法。这个函数的第一个输
# 入为当前层的节点矩阵。注意这个矩阵是一个四维矩阵,后面三个维度对应一个节点矩阵,第一
# 维对应一个输入batch。比如在输入层,input[0,:,:,:]表示第一张图片,input[1,:,:,:]
# 表示第二张图片,以此类推。tf.nn.conv2d第二个参数提供了卷积层的权重,第三个参数为不
# 同维度上的步长。虽然第三个参数提供的是一个长度为4的数组,但是第一维和最后一维的数字
# 要求一定是1。这是因为卷积层的步长只对矩阵的长和宽有效。最后一个参数是填充(padding)
# 的方法,TensorFlow中提供SAME或是VALID两种选择。其中SAME表示添加全0填充,
# “VALID”表示不添加。
conv = tf.nn.conv2d(
input, filter_weight, strides=[1, 1, 1, 1], padding='SAME')
# tf.nn.bias_add提供了一个方便的函数给每一个节点加上偏置项。注意这里不能直接使用加
# 法,因为矩阵上不同位置上的节点都需要加上同样的偏置项。虽然下一层神经网络的大小为
# 2×2,但是偏置项只有一个数(因为深度为1),而2×2矩阵中的每一个值都需要加上这个
# 偏置项。
bias = tf.nn.bias_add(conv, biases)
# 将计算结果通过ReLU激活函数完成去线性化。
actived_conv = tf.nn.relu(bias)
二:池化层
在卷积神经网络中,卷积层之间往往会加上一个池化层(pooling layer)。池化层可以非常有效地缩小矩阵的尺寸,从而减少最后全连接层中的参数。使用池化层既可以加快计算速度也有防止过拟合问题的作用。和卷积层类似,池化层前向传播的过程也是通过移动一个类似过滤器的结构完成的。不过池化层过滤器中的计算不是节点的加权和,而是采用更加简单的最大值或者平均值运算。使用最大值操作的池化层被称之为最大池化层(max pooling),这是被使用得最多的池化层结构。使用平均值操作的池化层被称之为平均池化层(average pooling)。
与卷积层的过滤器类似,池化层的过滤器也需要人工设定过滤器的尺寸、是否使用全0填充以及过滤器移动的步长等设置,而且这些设置的意义也是一样的。卷积层和池化层中过滤器移动的方式是相似的,唯一的区别在于卷积层使用的过滤器是横跨整个深度的,而池化层使用的过滤器只影响一个深度上的节点。所以池化层的过滤器除了在长和宽两个维度移动之外,它还需要在深度这个维度移动。下面的TensorFlow程序实现了最大池化层的前向传播算法。
# tf.nn. max_pool实现了最大池化层的前向传播过程,它的参数和tf.nn.conv2d函数类似。
# ksize提供了过滤器的尺寸(池化层边长为3),strides提供了步长信息,padding提供了是否使用全0填充。
pool = tf.nn.max_pool(actived_conv, ksize=[1, 3, 3, 1],
strides=[1, 2, 2, 1], padding='SAME')
对比池化层和卷积层前向传播在TensorFlow中的实现,可以发现函数的参数形式是相似的。在tf.nn.max_pool函数中,首先需要传入当前层的节点矩阵,这个矩阵是一个四维矩阵,格式和tf.nn.conv2d函数中的第一个参数一致。第二个参数为过滤器的尺寸。虽然给出的是一个长度为4的一维数组,但是这个数组的第一个和最后一个数必须为1。这意味着池化层的过滤器是不可以跨不同输入样例或者节点矩阵深度的。在实际应用中使用得最多的池化层过滤器尺寸为[1,2,2,1]或者[1,3,3,1]。
tf.nn.max_pool函数的第三个参数为步长,它和tf.nn.conv2d函数中步长的意义是一样的,而且第一维和最后一维也只能为1。这意味着在TensorFlow中,池化层不能减少节点矩阵的深度或者输入样例的个数。tf.nn.max_pool函数的最后一个参数指定了是否使用全0填充。这个参数也只有两种取值——VALID或者SAME,其中VALID表示不使用全0填充,SAME表示使用全0填充。TensorFlow还提供了tf.nn.avg_pool来实现平均池化层。tf.nn.avg_pool函数的调用格式和tf.nn.max_pool函数是一致的。