卷积神经网络CNN原理详解(一)——基本原理

卷积神经⽹络CNN原理详解(⼀)——基本原理
上篇⽂章我们给出了⽤paddlepaddle来做⼿写数字识别的⽰例,并对⽹络结构进⾏到了调整,提⾼了识别的精度。有的同学表⽰不是很理解原理,为什么传统的机器学习算法,简单的神经⽹络(如多层感知机)都可以识别⼿写数字,我们要采⽤卷积神经⽹络CNN来进⾏别
呢?CNN到底是怎么识别的?⽤CNN有哪些优势呢?我们下⾯就来简单分析⼀下。在讲CNN之前,为避免完全零基础的⼈看不懂后⾯的讲解,我们先简单回顾⼀下传统的神经⽹络的基本知识。
  神经⽹络的预备知识
为什么要⽤神经⽹络?
特征提取的⾼效性。
  ⼤家可能会疑惑,对于同⼀个分类任务,我们可以⽤机器学习的算法来做,为什么要⽤神经⽹络呢?⼤家回顾⼀下,⼀个分类任务,我们在⽤机器学习算法来做时,⾸先要明确feature和label,然后把这个数据"灌"到算法⾥去训练,最后保存模型,再来预测分类的准确性。但是这就有个问题,即我们需要实现确定好特征,每⼀个特征即为⼀个维度,特征数⽬过少,我们可能⽆法精确的分类出来,即我们所说的⽋拟合,如果特征数⽬过多,可能会导致我们在分类过程中过于注重某个特征导致分类错误,即过拟合。
  举个简单的例⼦,现在有⼀堆数据集,让我们分类出西⽠和冬⽠,如果只有两个特征:形状和颜⾊,可能没法分区来;如果特征的维度有:形状、颜⾊、⽠瓤颜⾊、⽠⽪的花纹等等,可能很容易分类出来;如果我们的特征是:形状、颜⾊、⽠瓤颜⾊、⽠⽪花纹、⽠蒂、⽠籽的数量,⽠籽的颜⾊、⽠籽的⼤⼩、⽠籽的分布情况、⽠籽的XXX等等,很有可能会过拟合,譬如有的冬⽠的⽠籽数量和西⽠的类似,模型训练后这类特征的权重较⾼,就很容易分错。这就导致我们在特征⼯程上需要花很多时间和精⼒,才能使模型训练得到⼀个好的效果。然⽽神经⽹络的出现使我们不需要做⼤量的特征⼯程,譬如提前设计好特征的内容或者说特征的数量等等,我们可以直接把数据灌进去,让它⾃⼰训练,⾃我“修正”,即可得到⼀个较好的效果。
数据格式的简易性
  在⼀个传统的机器学习分类问题中,我们“灌”进去的数据是不能直接灌进去的,需要对数据进⾏⼀些处理,譬如量纲的归⼀化,格式的转化等等,不过在神经⽹络⾥我们不需要额外的对数据做过多的处理,具体原因可以看后⾯的详细推导。
参数数⽬的少量性
  在⾯对⼀个分类问题时,如果⽤SVM来做,我们需要调整的参数需要调整核函数,惩罚因⼦,松弛
变量等等,不同的参数组合对于模型的效果也不⼀样,想要迅速⽽⼜准确的调到最适合模型的参数需要对背后理论知识的深⼊了解(当然,如果你说全部都试⼀遍也是可以的,但是花的时间可能会更多),对于⼀个基本的三层神经⽹络来说(输⼊-隐含-输出),我们只需要初始化时给每⼀个神经元上随机的赋予⼀个权重w和偏置项b,在训练过程中,这两个参数会不断的修正,调整到最优质,使模型的误差最⼩。所以从这个⾓度来看,我们对于调参的背后理论知识并不需要过于精通(只不过做多了之后可能会有⼀些经验,在初始值时赋予的值更科学,收敛的更快罢了)
有哪些应⽤?
  应⽤⾮常⼴,不过⼤家注意⼀点,我们现在所说的神经⽹络,并不能称之为深度学习,神经⽹络很早就出现了,只不过现在因为不断的加深了⽹络层,复杂化了⽹络结构,才成为深度学习,并在图像识别、图像检测、语⾳识别等等⽅⾯取得了不错的效果。
基本⽹络结构
  ⼀个神经⽹络最简单的结构包括输⼊层、隐含层和输出层,每⼀层⽹络有多个神经元,上⼀层的神经元通过激活函数映射到下⼀层神经元,每个神经元之间有相对应的权值,输出即为我们的分类类别。
八点听书
 详细数学推导
  去年中旬我参考吴恩达的UFLDL和mattmazur的博客写了篇⽂章详细讲解了⼀个最简单的神经⽹络从前向传播到反向传播的直观推导,⼤家可以先看看这篇⽂章--。
 优缺点
  前⾯说了很多优点,这⾥就不多说了,简单说说缺点吧。我们试想⼀下如果加深我们的⽹络层,每⼀个⽹络层增加神经元的数量,那么参数的个数将是M*N(m为⽹络层数,N为每层神经元个数),所需的参数会⾮常多,参数⼀多,模型就复杂了,越是复杂的模型就越不好调参,也越容易过拟合。此外我们从神经⽹络的反向传播的过程来看,梯度在反向传播时,不断的迭代会导致梯度越来越⼩,即梯度消失的情况,梯度⼀旦趋于0,那么权值就⽆法更新,这个神经元相当于是不起作⽤了,也就很难导致收敛。尤其是在图像领域,⽤最基本的神经⽹络,是不太合适的。后⾯我们会详细讲讲为啥不合适。
  为什么要⽤卷积神经⽹络?
  传统神经⽹络的劣势
术尔泰
  前⾯说到在图像领域,⽤传统的神经⽹络并不合适。我们知道,图像是由⼀个个像素点构成,每个像素点有三个通道,分别代表RGB颜⾊,那么,如果⼀个图像的尺⼨是(28,28,1),即代表这个
图像的是⼀个长宽均为28,channel为1的图像(channel也叫depth,此处1代表灰⾊图像)。如果使⽤全连接的⽹络结构,即,⽹络中的神经与与相邻层上的每个神经元均连接,那就意味着我们的⽹络有28 * 28 =784个神经元,hidden层采⽤了15个神经元,那么简单计算⼀下,我们需要的参数个数(w和b)就有:784*15*10+15+10=117625个,这个参数太多了,随便进⾏⼀次反向传播计算量都是巨⼤的,从计算资源和调参的⾓度都不建议⽤传统的神经⽹络。(评论中有同学对这个参数计算不太理解,我简单说⼀下:图⽚是由像素点组成的,⽤矩阵表⽰的,28*28的矩阵,肯定是没法直接放到神经元⾥的,我们得把它“拍平”,变成⼀个28*28=784 的⼀列向量,这⼀列向量和隐含层的15个神经元连接,就有784*15=11760个权重w,隐含层和最后的输出层的10个神经元连接,就有11760*10=117600个权重w,再加上隐含层的偏置项15个和输出层的偏置项10个,就是:117625个参数了)
                                    图1 三层神经⽹络识别⼿写数字
  卷积神经⽹络是什么?
  三个基本层
卷积层(Convolutional Layer)
  上⽂提到我们⽤传统的三层神经⽹络需要⼤量的参数,原因在于每个神经元都和相邻层的神经元相连接,但是思考⼀下,这种连接⽅式是必须的吗?全连接层的⽅式对于图像数据来说似乎显得不这么友好,因为图像本⾝具有“⼆维空间特征”,通俗点说就是局部特性。譬如我们看⼀张猫的图⽚,可能看到猫的眼镜或者嘴巴就知道这是张猫⽚,⽽不需要说每个部分都看完了才知道,啊,原来这个是猫啊。所以如果我们可以⽤某种⽅式对⼀张图⽚的某个典型特征识别,那么这张图⽚的类别也就知道了。这个时候就产⽣了卷积的概念。举个例⼦,现在有⼀个4*4的图像,我们设计两个卷积核,看看运⽤卷积核后图⽚会变成什么样。
图2 4*4 image与两个2*2的卷积核操作结果
  由上图可以看到,原始图⽚是⼀张灰度图⽚,每个位置表⽰的是像素值,0表⽰⽩⾊,1表⽰⿊⾊,(0,1)区间的数值表⽰灰⾊。对于这个4*4的图像,我们采⽤两个2*2的卷积核来计算。设定步长为1,即每次以2*2的固定窗⼝往右滑动⼀个单位。以第⼀个卷积核filter1为例,计算过程如下:
1 feature_map1(1,1) = 1*1 + 0*(-1) + 1*1 + 1*(-1) = 1
2 feature_map1(1,2) = 0*1 + 1*(-1) + 1*1 + 1*(-1) = -1
3 ```
4 feature_map1(3,3) = 1*1 + 0*(-1) + 1*1 + 0*(-1) = 2
  可以看到这就是最简单的内积公式。feature_map1(1,1)表⽰在通过第⼀个卷积核计算完后得到的feature_map的第⼀⾏第⼀列的值,随着卷积核的窗⼝不断的滑动,我们可以计算出⼀个3*3的feature_map1;同理可以计算通过第⼆个卷积核进⾏卷积运算后的
feature_map2,那么这⼀层卷积操作就完成了。feature_map尺⼨计算公式:[ (原图⽚尺⼨ -卷积核尺⼨)/ 步长 ] + 1。这⼀层我们设定了两个2*2的卷积核,在paddlepaddle⾥是这样定义的:
1 conv_pool_1 = paddleworks.simple_img_conv_pool(
2        input=img,
3        filter_size=3,
4        num_filters=2,
5        num_channel=1,
6        pool_stride=1,
7        act=paddle.activation.Relu())
  这⾥调⽤了networks⾥simple_img_conv_pool函数,激活函数是Relu(修正线性单元),我们来看⼀看源码⾥外层接⼝是如何定义的:
View Code
  我们在⾥可以看到simple_img_conv_pool这个函数的定义:
1 def simple_img_conv_pool(input,
2                          num_filters,
3                          filter_size,
4                          pool_size,
5                          pool_stride,
6                          act,
7                          pool_type='max',
8                          main_program=None,
9                          startup_program=None):
10    conv_out = v2d(
11        input=input,
12        num_filters=num_filters,
13        filter_size=filter_size,
14        act=act,
15        main_program=main_program,
16        startup_program=startup_program)
17
18    pool_out = layers.pool2d(
19        input=conv_out,
20        pool_size=pool_size,
21        pool_type=pool_type,
22        pool_stride=pool_stride,
23        main_program=main_program,
24        startup_program=startup_program)
25    return pool_out
  可以看到这⾥⾯有两个输出,conv_out是卷积输出值,pool_out是池化输出值,最后只返回池化输出的值。conv_out和pool_out分别⼜调⽤了layers.py的conv2d和pool2d,去layers.py⾥我们可以看到conv2d和pool2d是如何实现的:
  conv2d:
View Code
  pool2d:
View Code
同志空间  ⼤家可以看到,具体的实现⽅式还调⽤了:
View Code
  详细的源码细节我们下⼀节会讲这⾥指写⼀下实现的⽅式和调⽤的函数。
  所以这个卷积过程就完成了。从上⽂的计算中我们可以看到,同⼀层的神经元可以共享卷积核,那么对于⾼位数据的处理将会变得⾮常简单。并且使⽤卷积核后图⽚的尺⼨变⼩,⽅便后续计算,并且我们不需要⼿动去选取特征,只⽤设计好卷积核的尺⼨,数量和滑动的步长就可以让它⾃⼰去训练了,省时⼜省⼒啊。
  为什么卷积核有效?
  那么问题来了,虽然我们知道了卷积核是如何计算的,但是为什么使⽤卷积核计算后分类效果要由于普通的神经⽹络呢?我们仔细来看⼀下上⾯计算的结果。通过第⼀个卷积核计算后的feature_map是⼀个三维数据,在第三列的绝对值最⼤,说明原始图⽚上对应的地⽅有⼀条垂直⽅向的特征,即像素数值变化较⼤;⽽通过第⼆个卷积核计算后,第三列的数值为0,第⼆⾏的数值绝对值最⼤,说明原始图⽚上对应的地⽅有⼀条⽔平⽅向的特征。
  仔细思考⼀下,这个时候,我们设计的两个卷积核分别能够提取,或者说检测出原始图⽚的特定的
特征。此时我们其实就可以把卷积核就理解为特征提取器啊!现在就明⽩了,为什么我们只需要把图⽚数据灌进去,设计好卷积核的尺⼨、数量和滑动的步长就可以让⾃动提取出图⽚的某些特征,从⽽达到分类的效果啊!铸造合金钢
道路石油沥青  注:1.此处的卷积运算是两个卷积核⼤⼩的矩阵的内积运算,不是矩阵乘法。即相同位置的数字相乘再相加求和。不要弄混淆了。
社会主义初级阶段的基本矛盾    2.卷积核的公式有很多,这只是最简单的⼀种。我们所说的卷积核在数字信号处理⾥也叫滤波器,那滤波器的种类就多了,均值滤波器,⾼斯滤波器,拉普拉斯滤波器等等,不过,不管是什么滤波器,都只是⼀种数学运算,⽆⾮就是计算更复杂⼀点。
3.每⼀层的卷积核⼤⼩和个数可以⾃⼰定义,不过⼀般情况下,根据实验得到的经验来看,会在越靠近输⼊层的卷积层设定少量的卷积核,越往后,卷积层设定的卷积核数⽬就越多。具体原因⼤家可以先思考⼀下,⼩结⾥会解释原因。
池化层(Pooling Layer)
  通过上⼀层2*2的卷积核操作后,我们将原始图像由4*4的尺⼨变为了3*3的⼀个新的图⽚。池化层的主要⽬的是通过降采样的⽅式,在不影响图像质量的情况下,压缩图⽚,减少参数。简单来说,假设
现在设定池化层采⽤MaxPooling,⼤⼩为2*2,步长为1,取每个窗⼝最⼤的数值重新,那么图⽚的尺⼨就会由3*3变为2*2:(3-2)+1=2。从上例来看,会有如下变换:
      图3 Max Pooling结果
通常来说,池化⽅法⼀般有⼀下两种:
MaxPooling:取滑动窗⼝⾥最⼤的值
AveragePooling:取滑动窗⼝内所有值的平均值
  为什么采⽤Max Pooling?
  从计算⽅式来看,算是最简单的⼀种了,取max即可,但是这也引发⼀个思考,为什么需要Max Pooling,意义在哪⾥?如果我们只取最⼤值,那其他的值被舍弃难道就没有影响吗?不会损失这部分信息吗?如果认为这些信息是可损失的,那么是否意味着我们在进⾏卷积操作后仍然产⽣了⼀些不必要的冗余信息呢?
  其实从上⽂分析卷积核为什么有效的原因来看,每⼀个卷积核可以看做⼀个特征提取器,不同的卷积核负责提取不同的特征,我们例⼦中设计的第⼀个卷积核能够提取出“垂直”⽅向的特征,第⼆个卷积核能够提取出“⽔平”⽅向的特征,那么我们对其进⾏Max Pooling操作后,提取出的是真正能够识别特征的数值,其余被舍弃的数值,对于我提取特定的特征并没有特别⼤的帮助。那么在进⾏后续计算使,减⼩了feature map的尺⼨,从⽽减少参数,达到减⼩计算量,缺不损失效果的情况。
  不过并不是所有情况Max Pooling的效果都很好,有时候有些周边信息也会对某个特定特征的识别产⽣⼀定效果,那么这个时候舍弃这部分“不重要”的信息,就不划算了。所以具体情况得具体分析,如果加了Max Pooling后效果反⽽变差了,不如把卷积后不加Max Pooling的结果与卷积后加了Max Pooling的结果输出对⽐⼀下,看看Max Pooling是否对卷积核提取特征起了反效果。

本文发布于:2024-09-22 09:53:19,感谢您对本站的认可!

本文链接:https://www.17tex.com/xueshu/293360.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:卷积   特征   需要   神经   计算
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议