卷积神经网络(CNN)

介绍

  • 卷积核: 用来和图像做卷积运算的小矩阵
  • stride 步长:每一次卷积运算之后,卷积核沿着图像移动的像素点的长度
  • Padding: 在图像边沿位置做卷积运算时,需要补充的像素点,一般像素点值补0就可以

步骤

  1. 图像卷积(将特征值平均化,提取特征值),根据需要 可以/不 将图像padding补0,定义一个需要的卷积核(如果定义多个不同的卷积核,每一个卷积核可以对应于一个图像的通道(ex. rgb/hsv 三个通道),卷积和池化之后就可以得到不同的通道对应的新的图像
  2. 池化(降采样,减少图像运算的像素点的个数),con-max-pooling 就是取一片区域当中的最大值,对每一个通道都进行池化操作
    1,2步骤可以重复多次
    最后将图像的每一个通道都flattern(展开成一维数组),每一个通道都作为一个输入量,输入到全连接的前馈神经网络中进行训练(一般在网络中会对不同通道的值进行融合)

CNN用于手写数字识别

整个项目的框架如下图所示:
项目框架
通过摄像头捕获手写数字,输入到计算机中,运行手写数字算法,将识别结果通过无线设备发送到智能硬件
算法的框图入如下图所示
算法框图
整个神经网络共包含了5层(除去第一层输入层)
其中包含了二层卷积层、一层全连接层、一层dropout层以及一层的输出层
在每一层的卷积层中,每一个卷积操作,定义stride为1,Padding补充为0;每一个池化操作,都使用2x2的矩阵块中取出最大值

第一层神经网络

第一个卷积层

定义了32个通道(对应了32个卷积核),每一个卷积核是5x5的矩阵块

1
2
3
4
# First convolutional layer - maps one grayscale image to 32 feature maps.
W_conv1 = weight_variable([5, 5, 1, 32])
b_conv1 = bias_variable([32])
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)

其中weight_variable([5, 5, 1, 32])
前两个参数对应了卷积核的大小,第三个参数是输入的通道数(原始为灰度图像1个通道),第四个参数为输出的通道数
最后用卷积后的结果作为relu神经元的构造函数,神经元里面定义了对应的激活函数

第一个池化层

1
h_pool1 = max_pool_2x2(h_conv1)

第一个卷积层输出为32个通道,每一个通道的图像是28x28
经过一个2x2的池化层之后,输出的每一个通道的图像是14x14

第二层神经网络

第二个卷积层

定义了64个通道(对应了64个卷积核),每一个卷积核是5x5的矩阵块

1
2
3
W_conv2 = weight_variable([5, 5, 32, 64])
b_conv2 = bias_variable([64])
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)

输入为32个通道每个通道为14x14的图像
经过卷积运算,输出为64个通道每个通道14x14的图像

1
h_pool2 = max_pool_2x2(h_conv2)

第二个池化层

输入为64个通道每个通道14x14的图像
输出为64个通道每个通道7x7的图像

第三层神经网络

经过前两层已经完成了卷积运算,特征提取和降维
第三层叫做全连接层fully connected layer 也叫做 Densely Connected Layer
第二层的输出为64通道,每个通道为7x7的图像
所以先将第二层的输出flattern

1
h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])

第三层我们定了了1024个神经元
所以做乘法需要1024(77*64)个权重的参数
以及1024个bias偏差量

1
2
3
4
W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)

最后构造成relu神经元

Dropout层

为了避免过拟合添加了Dropout层
dropout的概念:就是在训练时,对每一批次的训练数据,关闭部分神经元,这样每一批次的数据只训练了部分神经元的参数,最后把这些参数累加并乘以一个系数得到训练后模型的参数

1
2
keep_prob = tf.placeholder(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

通过keep_prob参数来控制需要关闭的神经元的比例

输出层

经过第三层之后输出为1024shape的数据
我们希望得到的属于10个数据的证据,可以将证据转为为概率
所以这一层的输出为10维的向量

1
2
3
4
W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])
y_conv = tf.matmul(h_fc1_drop, W_fc2) + b_fc2

代码链接

最后附上训练好的模型、图像预处理代码以及测试集的下载地址

资料

http://www.jeyzhang.com/cnn-learning-notes-1.html
http://www.jeyzhang.com/cnn-learning-notes-2.html

模型算法历史

图像分类模型

参考:https://www.cnblogs.com/bonelee/p/8972139.html

Alexnet

创新点:最早出现,使用Relu作为激活函数,引入了dropout
缺点:卷积核太大,都是11x11以及5x5的

VGG16

创新点:使用小的卷积核3x3的
缺点:最后几层的通道数太多512,导致参数太多

GoogleNet

创新点:设计了inception的模块,用稀疏矩阵去做运算

Reset50

创新点:模型层数多了以后,反向更新参数的时候,最开始几层的梯度接近于0,无法学习

图像定位和检测

Yolo和SSD是1stage的,快但是精度稍差
Faster-RCNN 精度高,但是速度没有这么快

Yolo

SSD-VGG

Faster-RCNN