OpenCL与CNN篇四:CNN从入门到使用

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/ShiAokai/article/details/72954649
  1. 文中比较重要的引用了几个篇博客,开篇给与博主感谢
  2. 记录我从零到实现一个具体CNN网络中最有用的知识干货
  3. 以细节为切入点,分享我对CNN网络的简洁
  4. 本文致力于让你一篇文章理解CNN的具体实现与训练方法
  5. 涉及理论不一一追述背景,主要讲解其如何应用
  6. 开源的优秀CNN代码很多,我选择的入门可能不是最棒的,但对我是最容易理解的

开始

一、神经网络与卷积

1、如果你不了解神经网络,这篇 CNN笔记:通俗理解卷积神经网络 够了。
2、如果你不了解神经网络,这篇 CNN笔记:通俗理解卷积神经网络 也够了。
3、看黑板标重点,看完文章请确保理解:卷积、池化(采样)、全连接
4、这一条只是单纯地给上文的博主点10个贊。。。。。。。。。

二、一个简单的CNN结构

1、首先我们需要了解一个数据集MINST,刚去搜了一篇介绍比较详细的博客MNIST数据集解析,不过代码是Python如果不懂请选择忽略,看他关于MINST的介绍就好。不过你也可以先跳过这步,这只是输入数据,并不关乎我们的CNN构架。
2、如果上文你了解了卷积,那么现在可以给你介绍一个简单的CNN手写识别网络了。这也有一篇很好的博客编写C语言版本的卷积神经网络CNN之网络的总体结构,篇末有一份博主的C语言代码连接,纯C语言的自己注意修改一下代码中加载的文件路径,运行起来不是很难。不过文章的配图,和公式说明比较复杂,所以就只建议阅读tostq的专栏的篇二(就是上一个连接)。
3、在此送一张我自己画的图,姑且称为图一

简单的CNN网络

三、根据图一而来的 正向计算

先说明一下本文采用的激活函数Sigmoid(),表达式S(x)=1/[1+exp(x)]。它有一个很好的特性其导函数与其输出有关,即S~(x)=S(x)[1S(x)]
在之后的文章里我们用f(y)=y(1y)=S(x)[1S(x)]=S~(x) 表示激活函数的导函数,文章内引用不再重复说明。

3.1、卷积层C1、C3的计算

ym(x,y)表示第m张输出图位置(x,y)的像素信息,bm表示偏置,Xp(x,y)示第p张输入图,Kpm(j,i)表示当前输入图与输出图之间的卷积核,W、H分别表示卷积核的宽、高。可以得到输出图每个像素值的计算公式,如下:

ym(x,y)=S([pNiHjWXp(x+j,y+i)Kpm(j,i)]+bm)

这里解释多说一下卷积一般来说有三种:1、种卷积操作之后图像变大(原图补充mapSize-1圈像素);2、种卷积操作之后图像不变(原图补充(mapSize-1)/2圈像素);3、一种卷积操作之后图像减小(原图像大小不变)。
这里采用第三种,上式中(i,j)范围是[0,0]~[4,4],那么(x+j,y+i)的范围是[0,0]~[x+4,y+4]。所以如果输入图像大小是12*12,那么得到的输出图只有8*8 (inputSize-mapSize+1)。这也就是为什么会有前两种卷积拓展像素的做法。

3.2、采样层S2、S4的计算

如果看到这你已经知道了采样的含义,那么这将是最简单的一部分实现。我想偷懒原谅我。在本文中的做法是每次从前一层互不重叠的取2*2矩阵并计算平均值。所以本文采样层较之前一层边界会缩小一半。

3.3、输出层O5

由3.1和3.2得到采样层S4以后,我们将S4的12张图展开,可以得到12*4*4 =192个数据,由于数据规模相对较小,这里采用全连接方式与输出层O5连接。如图一所示计算公式如下:

ym=S([pNXS4pWO5pm]+bm)

四、根据图一而来的 误差反向传播

训练时先有网络的输出结果与输入图片的标签对比,用一个合适的损失函数来度量训练样本的输出损失,接着对这个损失函数进行优化求最小化的极值。损失函数优化极值求解的过程最常见的一般是通过梯度下降法来一步步迭代完成的。计算输出误差;得到输出层O5的误差,再经神经网络反向传递到各层,用于更新权值。用W表示权重,E表示损失函数,n表示第n轮更新迭代,η表示学习参数(可用来控制单次学习速率),u表示激活函数的输入,δ表示局域梯度。梯度下降法更新权重更新公式如下,姑且标记一下叫做公式一

Wn+1=WnΔWnun=WnXn+bΔWn=ηEnWn=ηEnununWn=ηδnXn

这里我们采用平方误差代价函数,误差能量定义为实际输出与理想输出的差,我们讨论的多类问题,共c类,N个训练样本:

EN=12n=1Nk=1c(tnkynk)2

这里tnk表示第n个样本对应标签的第k维。ynk表示第n个样本对应的网络输出的第k个输出。
值得说明的是所有层的δ,无论是单个值矩阵,其数据规模是和对应层的输出大小相同的。比如O5层有10个,C3层有12*8*8个,S2层有6*24*24个。这一点在之后的计算中你会很容易明白。

4.1、输出层O5的δ计算

因为在全部训练集上的误差只是每个训练样本的误差的总和,所以这里我们先考虑对于一个样本的BP。对于第n个样本的误差,表示为:

En=12k=1c(tnkynk)2=12tnyn2

这一层的局域误差梯度,在本例中 i 范围最大到输出层数据的个数:

δO5i=E(W,b)uO5i=E(W,b)yO5iyO5uO5i=(yO5itO5i)f(yO5i)

4.2、采样层S4的δ计算

这里计算展开后那个一维S4的δ,S4层共有12*4*4=192个输出像素,所以j=[1~192]或者[0~191]。

δS4j=i=110WO5jiδO5i=i=110WO5jiδO5i

4.3、卷积层C1/C3的δ计算

此处需要用到一个专业术语叫upsample(上采样),这个相当与正向计算中池化采样操作的逆操作,具体怎么操作呢,这篇卷积神经网络(CNN)反向传播算法第3节有很清晰的展示。对于卷积层第m张图(x,y)位置的δ计算如下:

δC3m(x,y)=upsample(δS4m)S~[uC3m(x,y)]=upsample(δS4m)f[yC3m(x,y)]

4.4、采样层S2的δ计算

到4.3我们已经可以计算得到C3层的δ,现在要据此计算S2的δ。统称起来就是已知卷积层δ,求其前一个采样层的δ。采样层S2同样没有激活函数。先给出更新公式:

δS2i=jδC3jS~(uS2)rot180(WC3ij)=jδC3jrot180(WC3ij)

采样层S2有6张图i取0~5,卷积层C3有12张图j取0~11,公式中涉及的矩阵间乘法均为卷积操作。
有一点可能会引起你的兴趣,上式中卷积核被旋转了180度,不过这是必要的;我觉得 CNN误差反传时旋转卷积核的简明分析应该可以很好的解答你的疑惑。

五、由图一而来的 权值更新

在公式一(第四节标红字体)中写明了权重(也就是卷积核)的更新公式,现在再给出偏置的更新公式:

bn+1m=bnmbnmbnm=xwyhδnm(x,y)

展开阅读全文

没有更多推荐了,返回首页