手写体识别一般是神经网络入门必备的demo,在传统的神经网络进行手写体识别的时候,需要更多的人工对特征进行处理,一般是如下的步骤:
>1.将原始图片的像素值栅格化为一维向量,如原始图片为8\*8, 则栅格化之后的向量为164; >2.将栅格化的向量作为神经网络的输入,手写体对应的数字编码之后作为神经网络的输出;
然后在MNIST数据集上也能有96%以上的正确率,但是MNIST数据集给的都是28*28大小的数据,如果图片的像素规模很大呢?这里可能就会考虑两个方案:要么就是直接将全部的像素作为神经网络的输入;要么就是人工去对像素进行采样降维。那么可行性又如何?对于第一种,假设隐层神经元的数量为1000,那么输入层-隐含层权值矩阵就达到了 109 的规模,一般的机器根本训不动,更别提用梯度下降这种可能会陷入局部最优的算法了(参数多,解空间大);对于第二种可能就是无尽的特征提取工作了。
谈到第二点,深度学习某种意义可以认为是对特征的学习. 领域知识在传统机器学习中十分重要,不管是CTR预估亦或是信用评级、LTR等,都需要在相关领域有较多的经验,往往某几个特征的发现能够给整个系统带来质的飞跃,当然这也使得传统机器学习的解释性更好。
通常而言,我们在观察事物的时候,都是会将注意力集中到某一块部分,可能一块还足以让我们判断这个东西的类型,但是多观察几个局部,就能大概知道所观察的东西是个啥了。这个给我们的启发是对于输入的1000*1000像素的图片,我们并不需要所有像素的信息,提取局部的特征也能够给我们勾勒出该图片所代表的事物的特征。这个在卷积神经网络中对应的就是卷积核。另外,对图片进行采样模糊等变换,某种程度上也不会改变图片中事物的主要特征,这个在卷积神经网络中对应的就是pooling,也就是向下采样.
那么卷积神经网络是如何处理类似于图片这种结构的输入呢?卷积神经网络中采用了两种十分有效的思路:局部感知和权值共享;前面提到如果直接将图像的像素作为神经网络的输入,需要学习的参数较多。表观上图像所代表的信息通过局部也能够表达,对于神经网络而言,虽然单个神经元只感受到了局部,但是整体的特征已经被整个模型所接收,最后的效果也不会差到哪里去,而随之带来的就是学习参数数目的下降。比如原始图像为1000*1000,隐层为1000000个节点,每个节点只与输入图像的5*5的区域相连,此时需要学习的参数为2.5*10^7,是原先的四万分之一.
但是这些参数的学习仍然是一个不小的挑战,但是如果隐层节点与输入层区域相连的权值都一样呢,那样子需要学习的参数仅仅为25个,而这个25个参数一般也被称之为卷积核,也有叫滤波器的,总而言之就是对局部特征进行某种线性变换的参数!如此而来,用较小的参数规模实现了对图像局部特征的学习!单个的卷积核造成的问题就是特征提取不够充分,所以一般采用的都是多个卷积核,每种卷积核所体现的就是图像局部不同的特征!卷积过后,如果直接用这些特征进行分类,一是维度过大导致训练不便,二是有可能导致过拟合,所以一般在卷积之后会加一个对卷积层特征的聚合过程,也即Pooling层。
表达卷积神经网络一般是卷积层与pooling层交替组合,构成深度神经网络,多层卷积能够组合局部特征从而表征全局,像下图中经典的LeNet-5网络结构,就是由3个卷积层和两个pooling层以及一个全连接层组成。
卷积层和pooling层可以认为是对特征的学习过程,然后将学习到的特征再输入到一个分类器中进行训练. 在卷积层,是利用卷积核对上一层的特征图进行卷积操作,然后将卷积结果重新输出到新的特征图中,在LeNet5中的C1层中,利用的就是6个5*5的卷积核对输入图像进行卷积,然后得到6个特征图,每个特征图的大小是28*28.
这里需要注意的是,卷积层的特征图并不仅仅是来自于前一层的一个特征图,有可能是前一层的多个特征图和多个卷积核进行联合操作之后得到,如LeNet-5中Pooling层S2到卷积层C3就是按照如下的排列进行连接的, 其中C3的第一个特征图来自于S2中的0,1,2号3个特征图,最后一个特征图与S2中的所有特征图相连,此时需要60个卷积核. 加上偏置,需要学习的参数为60*5*5+16.
令 Xlj 为第 l 层(卷积层)第j个特征图,当 l=1 时即为原始图像特征, Mlj 为与第 l 层(卷积层)第 j 个特征图相连的前一层特征图集合的某个子集,那么第l层的第j个特征图的计算:
其中, ∗ 为卷积运算, blj 为一维的实数,假设图片像素矩阵 P ,卷积核为 K , 如下:
那么对图像进行卷积之后的结果 F=K∗P 为:
此时需要注意卷积不是直接算矩阵点乘,而是将卷积矩阵旋转180度之后再算点乘。并且F中的元素与P中的元素有如下的对应关系,其中u,v为输出特征图的下标,卷积核大小为d*d, Kd−h,d−j 为卷积核参数 Kh,j 旋转180度之后对应的值, Pu+h,v+j 为与输入特征图进行卷积的位置的像素值。
卷积核的大小d一般选奇数,卷积时候的步长(一般为1)也可以根据具体的场景进行调整,当然如果为了保证卷积之后维度不变,也可以进行边缘扩展,在原始特征图的边缘补充新的像素值。
Pooling层主要的作用是降噪降维,缓解过拟合的尴尬。为什么这么说呢?因为就典型的max pooling(取最大)或者averaging pooling(取平均)操作而言,它能够使得模型关注于局部某一部分,而不是具体的像素,模型的鲁棒性和泛化能力得到了一定程度的保障。
Pooling层的特征图与上一层的卷积层一一对应,只不过特征图的维度变小。令 Xlj 为Pooling层的第j个特征图, down() 为向下采样。则有:
对于Pooling层的输入特征图,其每一个采样局部共享同一个采样尺度和偏置,也即 βlj 和 blj 都是一个实数. Pooling层之后,维度一般会减半。假设学习到的采样尺度为0.25, 偏执为0.1,采样窗口为2*2,激励函数f才用的sigmoid函数,则在Pooling层由输入特征图到输出特征图的过程如下:
卷积层和Pooling层可以认为是对特征的学习,在这个交替的层次之后,原始的数据被转换到新的特征空间中,然后通过全连接层将特征空间和样本空间进行关联。在通常情况下,全连接层可由卷积操作实现:对前层是全连接的全连接层可以转化为卷积核为1x1的卷积;而前层是卷积层的全连接层可以转化为卷积核为hxw的全局卷积,h和w分别为前层卷积结果的高和宽。
CNN的推导和基本的全连接神经网络无异,没什么特别的地方,关键在于两点:
令 δlj 为第 l 层第 j 个特征图 Xlj 对应的误差项,其维度和 Xlj 一致, (δlj)u,v 为 Xlj 下标为u,v对应的误差项,即有:
当 l 层为卷积层时,需要学习的参数为卷积核和偏执,假设卷积层输出N个特征图,有m个卷积核,卷积核大小为 r∗c ,则一共需要学习的参数个数为 (r∗c+1)∗m 。令卷积层第 j 个输出特征图的误差项为 δlj=∂E∂netjl .
其中 ⋅ 是点乘,up(x)表示向上采样,如果是mean pooling,则每个元素按照原先向下采样的比率进行复制,如果是max pooling, 则需要记住最大值的位置,然后除了最大位置的元素之外,都置为0。得到卷积层的误差项之后,便可以进行权值更新了。卷积层每一个输出特征图 xlj 对应一个为偏执 blj , 且 blj 为标量,其与每一个 (δlj)u,v 都有关联,所以对偏执的求导为:
每一个输出特征图由若干个卷积核与输入特征图卷积得来,对于卷积核 Kli,j 而言,其求导的结果为一个 d∗d 的矩阵,对于其中的某个值 (Ki,j)r,s 求导为(其中r,s为卷积核中的下标,大小在[0,d-1]范围内,u,v为输出特征图的下标):
此时又有:
所以:
也即:
其中, PTl−1i 为 Xl−1i 中与卷积核进行卷积的部分,我们来看个例子,对于 xl−1i(X) 、以及卷积 Ki,j(K) 如下:
此时的 a 即为 δ ,所以:
当 l 层为Pooling层时,需要学习的参数为偏执和采样尺度,每一个特征图对应两个参数。令 δli 为Pooling层的误差项, δli=∂E∂netli 。Pooling层下一层一般是卷积层,所以有:
这里的conv2指的是对 δl+1j 作宽卷积运算,其具体含义见:http://blog.csdn.net/zy3381/article/details/43274029, 要推导这个公式,首先来看个例子。
假设Pooling层的第i个输出特征图 xli 大小为3*3,卷积核为K,大小为2*2, 即:
令 Al+1i=xli∗K , 则 netl+1j=∑iAl+1i+bl+1j ,所以有:
那么,由此可以看出, x11 只参与到 (netl+1j)11 的计算, x12 参与到 (netl+1j)11 和 (netl+1j)12 的计算
上面求解的结果实际上就是 (δl+1j) 和 K 宽卷积的结果,首先以 (δl+1j) 为中心(假设 (δl+1j) 大小为 w∗h , 卷积核K大小为 d∗d ),扩展出大小为 (w+2(d−1)) 的矩阵NK,新增的部分用0填充,上面例子中的NK即为: