面对更加复杂的问题时,基于卷积神经网络的算法模型表现更加优异,远远超过了传统的机器学习算法,特别是在图像分类数据集上有非常突出的表现。
卷积神经网络
卷积神经网络与全连接神经网络在整体架构上比较相似,都是通过一层一层的节点组织起来,每一个节点都是一个神经元。
卷积神经网络相邻层之间只有部分节点相连。
这是卷积神经网络和全连接神经网络唯一的区别,因为全连接神经网络处理图像的问题在于全连接层的参数太多。参数增多除了导致计算速度减慢,还很容易导致过拟合问题,而卷积神经网络可以有效减少神经网络中的参数个数。
卷积神经网络的输入图像就是原始图像的原始像素,而输出层中的每一各节点代表了不同类别的可信度。
定义损失函数以及参数的优化过程都使用于卷积神经网络。
卷积神经网络的结构
一般卷积神经网络主要包含5种结构:
- 输入层:整个神经网络的输入,一般代表一张图片的像素矩阵,一般为三维矩阵,长和宽代表了图像的大小,第三维是图像深度,灰度图像时为1,RGB图像为3。
- 卷积层:卷积层中每一个节点的输入只是上一层神经网络的一小块,这个小块常用的大小为3X3或者5X5,卷积层试图对每一小块进行更加深度分析从而得到抽象程度更高的特征。经过卷积层的节点矩阵的深度会增加。
- 池化层:也叫采样层。可以认为该操作是将一张分辨率较高的图片转化为分辨率较低的图片。池化层不会改变三维矩阵的深度,但它可以缩小矩阵的大小,从而达到减少整个神经网络中参数的目的。
- 全连接层:卷积神经网络最后一般会是1到2个全连接层来给出最后的分类结果,即经过卷积和池化层后的图像已经完成了特征提取,但仍然需要使用全连接来完成分类任务。
- Softmax层:主要用于分类,得到当前样例属于不同种类概率分布情况。
卷积层
该部分是卷积神经网络结构中最重要的部分,被称之为过滤器或者内核。
过滤器可以将当前层神经网络上的一个子节点矩阵转化为下一层神经网络上一个单位节点矩阵,单位节点矩阵指的是一个长和宽都为1,深度不限的节点。
过滤器处理的矩阵深度和当前层的神经网络节点的矩阵深度是一致的。过滤器的尺寸需要指定两个参数,另一个需要人工指定的参数是处理得到的单位节点矩阵的深度,这个深度称之为过滤器深度。过滤器尺寸指的是一个过滤器输入节点矩阵的大小。
卷积层结构的前向传播过程就是通过将一个过滤器从神经网络当前层的左上角移动到右下角,并且在移动中计算每一个对应的单位矩阵。过滤器每移动一次,可以计算得到一个值(当深度为K时会计算出K个值),将这些数值拼接成一个新的矩阵,就完成了前向传播过程。
卷积前向传播过程得到的矩阵尺寸要小于当前层矩阵的尺寸。为了避免尺寸大小的变化,可以在当前层矩阵的边上加入全0填充。同时可以通过过设置过滤器移动的步长来调整结果矩阵的大小。
同时,每一个卷积层中使用的过滤器中的参数都是一样的,这样做有以下优点:
- 通过共享过滤器的参数可以使得图像上的内容不受位置的影响,因为无论目标出现在图片在什么位置得到的结果都一眼。
- 可以巨幅减小神经网络上的参数。
- 卷积层的参数个数和图片的大小无关,可以使得过滤器可以扩展到更大的图像数据上。
# 卷积层的参数个数只和过滤器的尺寸有关、深度及当前层节点矩阵的深度有关
#所以声明的参数变量是一个四维矩阵,前两个维度代表过滤器尺寸,第三个维度表示当前层的深度,第四个维度表示过滤器深度
filter_weight = tf.get_variable('weight', [5, 5, 3, 16], initializer=tf.truncated_normal_initializer(stddev=0.1))
# 当前层矩阵上的不同位置的偏置项也是也是共享,所以共有下一层深度个不同的偏置
biases = tf.get_variable('biases', [16], initializer=tf.constant_initializer(0.1))
# conv2d()是一个实现卷积层前向传播的算法,第一个参数为输入节点矩阵,第二个参数是卷积层权重,第三个参数为不同维度的步长,最后一个参数为填充,SAME=0表示全零填充
conv = tf.nn.conv2d(input, filter_weights, strides=[1, 1, 1, 1], padding='SAME')
bias = tf.nn.bias_add(conv, biases)
actived_conv = tf.nn.relu(bias)
池化层
也叫pooling layer,池化层可以非常有效缩小矩阵的尺寸,从而减少全连接层中的参数,同时也可以加快计算速度和防止过拟合问题。
与卷积层类似,池化层前向传播过程也是通过移动一个类似过滤器的结构完成的。但是池化层不是计算节点的加权和,而是采用更加简单的最大或者平均值运算。卷积层和池化层中过滤器移动的方式是类似的,唯一区别在于池化层不改变矩阵的深度,所以池化层过滤器除了在长和宽两个维度移动之外,还需要在深度上移动。
# max_pool()实现了最大池化层的前向传播过程,参数和conv2d()类似。ksize提供了过滤器的尺寸,strides提供了步长信息。
pool = tf.nn.max_pool(actived_conv, ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1], padding='SAME')
经典卷积神经网络
Let-Ned-5:
一个比较经典的卷积神经网络模型是Let-Ned-5,结构如下:
第一层:卷积层
第二层:池化层
第三层:卷积层
第四层:池化层
第五层:全连接层
第六层:全连接层
第七层:全连接层
经典的用于图片分类问题的卷积神经网络架构:
输入层—>(卷积层+—>池化层?)+—>全连接层+
+表示一层或者多层,?表示没有或者有一层。
Inception-v3:
该结构是一种完全不同的卷积神经网络结构,不同于串联的连接方式,而是将不同的卷积层通过并联的方式结合在一起。虽然滤波器的大小不同,但是使用全0填充且步长为1的过滤器处理之后他们拥有相同的长和宽。
# TensorFlow-Slim工具可以更加简洁的实现一个卷积层
# slim.conv2d()有三个参数比必填,第一个参数是输入节点矩阵,第二个参数是当前卷积层过滤器的深度,第三个参数是过滤器的尺寸
with tf.variable_scope('layer'):
# concat()第一个参数指定了拼接的维度
branch_1 = tf.concat(3, [
slim.conv2d(input_tensor, 384, [1, 3], scope='conv2d_ob_1X3'),
slim.conv2d(input_tensor, 384, [3, 1], scope='conv2d_ob_3X1')])
迁移学习
所谓迁移学习,就是将一个问题上训练好的模型通过简单的调整使其使用于一个新的问题。通常的做法是保留所有卷积层的参数,替换最后的全连接层。