python人脸识别项目之学习笔记(五):卷积神经网络
1. 卷积神经网络
卷积神经网络(Convolutional Neural Network)简称CNN,CNN是所有深度学
习课程、书籍必教的模型,CNN在影像识别方面的为例特别强大,许多影像识别
的模型也都是以CNN的架构为基础去做延伸。另外值得一提的是CNN模型也是
少数参考人的大脑视觉组织来建立的深度学习模型,学会CNN之后,对于学习其
他深度学习的模型也很有帮助,通过一个例子来讲解CNN的原理以及使用CNN
来达成99%正确度的手写字体识别。
从上面三张图片我们可以看出,CNN架构简单来说就是:图片经过各两次的
Convolution, Pooling, Fully Connected就是CNN的架构了,因此只要搞懂Convolution,
Pooling, Fully Connected三个部分的内容就可以完全掌握了CNN!
CNN在图像识别的案例:
假设给定一张图(可能是字母X或者字母O),通过CNN即可识别出是X还是O,
如下图所示,那怎么做到的呢
提取特征
如果字母X、字母O是固定不变的,那么最简单的方式就是图像之间的像素一一
比对就行,但在现实生活中,字体都有着各个形态上的变化(例如手写文字识
别),例如平移、缩放、旋转、微变形等等,如下图所示
我们的目标是对于各种形态变化的X和O,都能通过CNN准确地识别出来,这就涉
及到应该如何有效地提取特征,作为识别的关键因子。
对于CNN来说,它是一小块一小块地来进行比对,在两幅图像中大致相同的位置找到一些粗糙的特征(小块图像)进行匹配,相比起传统的整幅图逐一比对的方式,CNN的这种小块匹配方式能够更好的比较两幅图像之间的相似性。如下图:
以字母X为例,可以提取出三个重要特征(两个交叉线、一个对角线),
如下图所示:
假如以像素值"1"代表白色,像素值"-1"代表黑色,则字母X的三个重要特征如下:
卷积
当给定一张新图时,CNN并不能准确地知道这些特征到底要匹配原图的哪些部分,所以它会在原图
中把每一个可能的位置都进行尝试,相当于把这个feature(特征)变成了一个过滤器。这个用来匹
配的过程就被称为卷积操作,这也是卷积神经网络名字的由来。
在本案例中,要计算一个feature(特征)和其在原图上对应的某一小块的结果,只需将两个
小块内对应位置的像素值进行乘法运算,然后将整个小块内乘法运算的结果累加起来,最后
再除以小块内像素点总个数即可(注:也可不除以总个数的)。
如果两个像素点都是白色(值均为1),那么1 * 1 = 1,如果均为黑色 ,那么 (-1)*(-1) = 1,也就是说,每一对能够匹配上的像素,其相乘结果为1。类似地,任何不匹配的像素相乘结果为-1。具体过程如下(第一个、第二个……、最后一个像素的匹配结果):
根据卷积的计算方式,第一块特征匹配后的卷积计算如下,结果为1
对于其它位置的匹配,也是类似(例如中间部分的匹配)
计算之后的卷积如下
以此类推,对三个特征图像不断地重复着上述过程,通过每一个feature(特征)的卷积操作,
会得到一个新的二维数组,称之为feature map。其中的值,越接近1表示对应位置和feature
的匹配越完整,越是接近-1,表示对应位置和feature的反面匹配越完整,而值接近0的表示对
应位置没有任何匹配或者说没有什么关联。如下图所示:
代码实现
tf.nn.conv2d (input, filter, strides, padding, use_cudnn_on_gpu=None, data_format=None, name=None)
'参数:
input : 输入的要做卷积的图片,要求为一个张量,shape为 [ batch, in_height, in_weight, in_channel ],其中batch为图片的数量,in_height 为图片高度,in_weight 为图片宽度,in_channel 为图片的通道数,灰度图该值为1,彩色图为3
filter: 相当于CNN中的卷积核,它要求是一个Tensor,具有[filter_height, filter_width, in_channels, out_channels]这样的shape,具体含义是[卷积核的高度,卷积核的宽度,图像通道数,卷积核个数],要求类型与参数input相同,有一个地方需要注意,第三维in_channels,就是参数input的第四维;
卷积时在图像每一维的步长,这是一个一维的向量,长度4
padding: string类型的量,只能是”SAME”,”VALID”其中之一,这个值决定了不同的卷积方式
use_cudnn_on_gpu:bool类型,是否使用cudnn加速,默认为true结果返回一个Tensor,这个输出,就是我们常说的feature map
分析:
- 需要做卷积的图片是一个3*3的彩色图片
import tensorflow as tf
input = tf.constant(
[
[
[
[100., 100., 100.],
[100., 100., 100.],
[100., 100., 100.]
],
[
[100., 100., 100.],
[100., 100., 100.],
[100., 100., 100.]
],
[
[100., 100., 100.],
[100., 100., 100.],
[100., 100., 100.],
]
]
]
)
filter = tf.constant(
[
[
[
[0.5, 0.1],
[0.5, 0.1],
[0.5, 0.1]
],
[
[0.5, 0.1],
[0.5, 0.1],
[0.5, 0.1]
]
],
[
[
[0.5, 0.1],
[0.5, 0.1],
[0.5, 0.1]
],
[
[0.5, 0.1],
[0.5, 0.1],
[0.5, 0.1]
]
],
]
)
result1 = tf.nn.convolution(input, filter, padding='VALID')
result2 = tf.nn.convolution(input, filter, padding='SAME')
with tf.Session() as sess:
print(sess.run([result1, result2]))