卷积神经网络(Convolutional Neural Network, CNN)
- CNN的结构
首先CNN适合提取图像信息,输入往往是一张图片(计算机将图片理解为若干个矩阵),常见的有RGB信息的图片就是一个三层矩阵。
接着是卷积层(Convolution Layer),卷积层的激活函数使用的是ReLU。这个激活函数前面也有看到过,其实很简单,就是
ReLU(x)=max(0,x)
在卷积层后面是池化层(Pooling layer),池化层没有激活函数。
![51b6e5d17bfc7debb38ce2256e3e1041.png](https://i-blog.csdnimg.cn/blog_migrate/b8bb2e8f963032b3492d834c737a8ccb.jpeg)
池化层和卷基层的搭配可以在隐藏层中出现多次,也可以自由搭配组合卷积层+卷积层,或者卷积层+卷积层+池化层,这个在建模时并没有限制,可以根据自己的需求来。不过比较常见的都是卷积层+池化层的组合。
最后一层就之前看过的是全链接层(Fully Connected Layer, 简称FC)。
- 卷积层
卷积层一般是一个尺寸比输入图片小的比如5*5*3的一个filter(感受野),filter需要和输入图片的深度相同,比如一张彩色图片有RGB三个通道,深度为3,那么对应的filter深度也应该是3。
![89b4489b798138364ac4d93c4bf6b08a.png](https://i-blog.csdnimg.cn/blog_migrate/637b799074dfb2d41e3c3c076f05da1d.jpeg)
如果输入图像是32*32*3,通过5*5*3的一个filter,可以得到一个28*28*1的特征图,通常会有多个卷积层来获取特征:
![22b57827dec9d35afddeb2b81313687f.png](https://i-blog.csdnimg.cn/blog_migrate/d68698c5813633d5758f096c8e9a089f.jpeg)
卷积层的原理其实就是对输入的图像的不同局部的矩阵和卷积核矩阵各个位置的元素相乘,然后相加得到。
比如输入是一个二维的3x4的矩阵,而filter是一个2x2的矩阵。这里我们假设卷积是一次移动一个像素来卷积的,那么首先我们对输入的左上角2x2局部和卷积核卷积,即各个位置的元素相乘再相加,得到的输出矩阵S的S00的元素,值为 + + + 。再把filter向右移动一次重复操作来得到S01的值。
![0b6f673e30bd15e3722c3b5d000d82b8.png](https://i-blog.csdnimg.cn/blog_migrate/4682a9bca817826c7405127f0a929810.jpeg)
- 池化层
个人理解的池化层就是提取信息,压缩数据。池化层有很多作用:
1保留原有特征
2减少冗长度(特征降维)
3防止过拟合
有很多池化方法,最大值池化,均值池化,随机池化,中值池化,组合池化等。
下面这个例子用的是最大值池化的方法:
![8fa0689b933016bce389f14035228b69.png](https://i-blog.csdnimg.cn/blog_migrate/95c587adc514477c38fe9acbd86c217b.jpeg)
- 总结
比如有一张4*4的图片和22(4个)神经元的网络,filter每往后滑动一次相当于加入了一张新的图片,也就是将图片分解做解析。如果是全链接网络的话,分析这张图片需要4*16个参数,做一次运算,CNN则是4*9次运算,运算效率得到了提升。但是这样做的代价是:参数是被共享的,也就是说神经网络或许会无视掉一部分特征,只对图片的部分产生反应。
比如:
![13553626c37b6c53e83cdb25ed3550af.png](https://i-blog.csdnimg.cn/blog_migrate/84bddf3662d22b5e022c0ecae68f8a07.jpeg)
这种情况只对45度倾斜角时,才能给出信号反应,也就是说一种filter只能提取一种特殊特征,虽然有局限性,但是使用的参数少。
多个filter可能最终会关注不同的特征,但是要注意初始值不能一样。
说白了,CNN是对一种特征(信号)的投票,它非常适合(也只适合)提取图片信息,因为图片信息天然产生于欧几里得(3维)空间。
- TensorFlow代码实现部分
import
可以看到,在使用和上次FC同样的数据集时,CNN的效率是高于FC的。
(亲测Flatten效果更好,图一为global_average_fooling,图二为Flatten(看看这厉害的准确率!):)
![cd595a0e72dbf3eef5b6f193affb4014.png](https://i-blog.csdnimg.cn/blog_migrate/3b03de93eb25cd9034735f9ce14fd041.jpeg)
![7d26f018e4c9e111e9cab6719a25e0b7.png](https://i-blog.csdnimg.cn/blog_migrate/84608c1b659e43c0d5febde7dbb87147.jpeg)
- CNN参数计算
代码中输入的是一个16*16*1的图片和16个3*3的filter,那么它的第一层参数就应该是:
(3*3+1)*16 = 160
16为filter的个数,1为激活函数最后加的一位dense。
输出的图片应该是(16-3+1)*(16-3+1)*16
16为深度,与filter的个数保持一致。
第二层的参数就也很简单了:
(3*3*16+1)*16 = 2320
根据代码输出可知
这层输出的global_average_pooling为16
第三层为就也很简单了:
(16+1)*10 = 170
计算得到的答案和代码的输出结果也是一致的:
![3ab4df88e6f3822252579d3b56e3ace8.png](https://i-blog.csdnimg.cn/blog_migrate/50e5f74a92efebc3b53d0de29292723a.jpeg)