目录
1.前言
2.神经网络基本原理
卷积
池化
激活函数
多个隐藏层累加
全连接层
训练过程
深度学习的黑盒性质一直被人所诟病,我们不知道里面的发生了什么,如果能用图片或者动画来展示这个过程,那么他会变得更加大众化,易于理解,今天我们就以一个实际图像分类的例子来揭开这个面纱。
这里要给大家介绍一个非常不错的网站:深度学习平台Tensorflow游乐场,以图和动画的形式展示网络训练的动态过程。
http://playground.tensorflow.org
我们的例子是要通过一个卷积神经网络来对图像分类,一类是字母X:,另一类是字母O。
为了简化演示过程,我们尽量将神经网络设计地简单些,网络结构如下:
在神经网络出现之前,图像模式识别一般使用手工设计的特征提取器提取图像特征,然后将提取到的特征输入到分类器中,深度学习的本质就是要取代人工设计,通过学习得到这个特征提取器,在卷积神经网络中,这个特征提取器被称为卷积核,我们假设1.2中的网络每个卷积层有三个卷积核,每个卷积核负责提取一个特征,为了演示深度学习对图像分类过程,我们假设训练过程已经完成,如图1.3,通过训练卷积核分别学到了下面的参数。
根据以往图像处理的经验,图1.3中,第一个卷积核对负45度的线会特别敏感,第二个卷积核对具有交叉形状的线会特别敏感,同理,第三个卷积核对正45度的线会特别敏感:
假设现在让我们输入一张字母X的图像,1代表字母区域,-1代表背景:
图像首先经过网络的第一个卷积层,按照卷积操作的原理,三个卷积核分别在X图像上滑动做卷积操作,得到如图1.6中的特征图。
图1.6中计算的特征图白色的区域值最大,值越大特征匹配的越完整,这说明与我们前面的假设一致,第一个卷积核提取到了负45度的线,第二个卷积核提取到了中间的交叉部位,第三个卷积核提取到了正45度的线。
在图1.6的特征图中,值为1的特征周边还有一些比较小的值甚至还有负值,这些值说明该点对应的原图像这个区域内没有匹配到上面三个特征,或者匹配度不是很高,这些值对于后面的分类作用不大,也还会消耗计算时间,那怎么办呢?我们发现卷积层后面跟了一个池化层,以最常用的最大值池化为例,它选取池化窗口内最大的值,其他值被过滤掉了,最终得到图1.8的结果。
至此,输入图像经过了卷积和核池化操作,但这些操作本质上都是线性的,即使是累加多个卷积和池化,也改变不了线性的本质,线性系统拟合能力有限,而神经网络的复杂度能拟合任意复杂函数,这是通过什么做到的呢?答案是激活函数,我们以relu激活函数为例,特征图小于0的都被统一设置为0,大于0的不变,图2.0是经过激活函数后的特征图。
至此,输入图像经过了一个卷积,池化和激活操作,这三个操作组合通常被称为卷积层,只经过一个卷积层,这时提取的特征还很抽象,例如,其他字母也有45度的线,所以如果直接使用这些特征进行分类效果不会很好,为了抽取更加具体的特征,还需要累加多个卷积层,经过多个卷积层后的输出见图2.2。
经过多个卷积层后,输出的特征图是2*2大小,这些特征图与前面的特征图相比,感受野变大,且具有丰富的语义信息,适合用来做分类,可能有人会有疑问:输入图像的大小是9*9,输出变成2*2了,这是怎么做到的?
答案就在网络各个操作中,卷积操作输出的特征图大小要取决于卷积的方式,跟卷积核的大小,步长,padding有关,其输出特征图大小的计算公式:
同样池化操作后特征图大小的计算公式:
激活函数不改变特征图的大小,另外,如果是maxpool,激活函数和池化的顺序没有关系。
我们网络的每个卷积操作设置padding=1,所以卷积输出的特征图与输入大小一致,尺寸不变,但经过池化后,特征图尺寸降为输入的一半,图2.3标出每个操作后输出特征图的大小。
经过上面的网络后我们已经能得到特征图了,但要想得到分类结果还需要通过一个全连接层,首先需要将上面2*2的特征图展开成向量形式,多个特征图向量拼接到一起送入全连接层,最终经过softmax分类器输出属于每个类别的概率,取概率最大值对应的类别作为最终输出结果。
图2.5中,每一条绿色的线对应的都是一个参数,线越粗代表参数越大,参数越大代表与之相连的特征对于该类别越重要,例如,X类别最关注第1,4,5,10,11位置的特征值,这些特征就是对应字母X的斜线和交叉点,最终的结果是该图像92%的概率是X,51%的概率是O。
文章的一开始我们假设卷积核的参数以及全连接层的参数都已知的,是通过训练过程得到的,那这些是怎么得到的呢?
对于神经网络,网络的参数在训练开始的时候,一般会按照某个概率分布进行初始化,例如使用高斯分布初始化参数,也有的进行随机初始化;这些随机初始化的参数是杂乱无章的,没有提取特征的能力,所以输出的结果会偏离真实标签值,例如,输入一张X图像,网络输出是X的概率0.01,属于O的概率是0.8;这明显是错误的,我们希望网络输出属于X的概率越接近1越好,那如何去优化参数才能达到这个效果呢?
要想优化网络参数,首先要有一个能衡量网络输出与标签的差距的函数,这个函数我们称为目标函数,或者损失函数,在回归任务中我们使用均方误差,分类任务中一般使用交叉熵;我们的目的是让损失函数达到最小,在数学中,这是一个求极值问题,求极值问题一般会用到导数,能让导数为0的参数值就是我们要求的参数值;但神经网络要复杂的多,用倒数求极值需要目标函数是凸函数,但现实中并不是所有目标函数都是凸函数,而且神经网络的参数有很多,并不是简单的一元函数,这就涉及到目标函数对参数的偏微分,然后按照一定的学习率采用随机梯度下降的方式进行参数更新,直到达到最优值。