【机器学习】卷积神经网络(CNN)架构解析

来源:互联网 发布:matlab 三维矩阵 画图 编辑:程序博客网 时间:2024/05/22 08:17

卷积神经网络是一种在图像识别与分类领域被证明特别有效的神经网络。卷积网络已经成功地识别人脸、物体、交通标志,应用在机器人和无人车等载具。接下来将通过对一个一个概念的讲解,帮助大家更好地理解卷积神经网络。


卷积

首先希望大家对整个CNN网络有一个总体的把握,假设我们输入一个图像,经过特征提取层,池化层,全连接层(不一定是固定的顺序)之后,我们希望得到的是这个图像对于每一个类别的概率值。要理解CNN,首先要明白,什么是卷积?CNN中的卷积就是将输入信号通过滑动窗口(或称过滤器卷积核)平滑处理,将信号的特征值提取出来,并且一般会使用多个不同的窗口进行卷积,输出多个通道(一个窗口对应一个通道)的处理结果。可以理解成卷积就是把轮廓表现出来CNN网络中,利用卷积,可以将原来图像中的特征映射出来,下图是一张图像使用不同的卷积核提取出不同特征后得到的结果。


池化(下采样)

通过卷积操作获得了图像的特征之后,若直接用该特征去做分类则面临计算量的挑战。而Pooling的结果可以使得特征减少,参数减少,同时改善结果(不易于出现过拟合)。它的本质其实是采样。Pooling 对于输入的 Feature Map,选择某种方式对其进行压缩。池化一般有两种方法,mean-poolingmax-poolingmean-pooling对领域内特征点求平均值,对背景保留更好,max-pooling对领域内特征点求最大值,对纹理提取更好。

 

 

例如:对于一个 96X96 像素的图像,假设我们已经学习得到了400个定义在8X8输入上的特征,每一个特征和图像卷积都会得到一个 (96 − 8 + 1) * (96 − 8 + 1) = 7921 维的卷积特征,由于有 400 个特征,所以每个样本都会得到一个 892 * 400 = 3,168,400 维的卷积特征向量。学习一个拥有超过 3 百万特征输入的分类器十分不便,并且容易出现过拟合 (over-fitting)。

池化层除了对Feature Map降维,有效减少后续层所需参数之外,还有一个作用,即平移不变性。对于输入,当其中像素在邻域发生微小位移时,Pooling Layer 的输出是不变的。这就使网络的鲁棒性增强了,有一定抗扰动的作用。

池化有更多的不止俩种方式,还有重叠池化重叠池化的相邻池化窗口之间会有重叠区域),空间金字塔池化空间金字塔池化拓展了卷积神经网络的实用性,使它能够以任意尺寸的图片作为输入。)感兴趣的可以查阅相关文献进行了解。

 


激活函数

如果缺少了激活函数,我们的神经网络会变成什么样子呢?我们的输出信号将仅仅只是一个简单的线性函数,表达力不够,并且大多数情况下执行得并不好。没有激活函数(其实相当于激活函数为y=x),我们的神经网络将无法学习和模拟其他复杂类型的数据,例如图像、视频、音频、语音等。使用非线性函数作为激励函数,这样神经网络就不再是输入的线性组合,可以逼近任意函数,这就是为什么我们要使用人工神经网络技术,来理解一些复杂的事情,一些相互之间具有很多隐藏层的非线性问题,而这也可以帮助我们了解复杂的数据。

关于激活函数,一开始使用的是sigmoid函数(将值映射到0~1之间)或者tanh函数(将值映射-1~1之间)。  



但是sigmoid函数在使用过程中会有以下问题:

①   由于涉及到指数运算,在反向传播求误差梯度时涉及除法,计算量大。

②   对于深层网络,很容易出现梯度消失现象。(即上图中比较平缓的区域,导数趋于0变换太缓慢,导致无法完成深层网络的训练)

于是引入了ReLu函数,它的形式很简单,即y=max(0,x)。在解决了梯度消失问题,计算速度方面问题的同时,带来了另外一个好处:它会使一部分神经元的输出为0,使得网络变得稀疏并减少参数之间的相互依存关系,缓解了过拟合的发生。

然而ReLU也有需要特别的问题:Dead ReLU Problem,指的是某些神经元可能永远不会被激活,导致相应的参数永远不能被更新。由于ReLU在x<0时梯度为0,这样就导致负的梯度在这个ReLU被置零,而且这个神经元有可能再也不会被任何数据激活。尽管存在问题,但ReLU目前仍是最常用的激活函数。

为了解决ReLU的神经元坏死问题,提出了Leaky ReLU函数,即y=max(0.01x,x),它不会有神经元坏死问题,也有ReLU的优点。同时提出来的还有ELU(ExponentialLinear Units)激活函数,它不会有神经元坏死问题,并且输出的均值接近0,但是计算量稍大。


这两者虽然理论上好于ReLU,但是在实际操作中并没有完全证明它们总是表现得更好。因此建议使用ReLU函数,但是要注意初始化和learning rate的设置;如果我们的模型在训练过程中遇到死亡神经元可以尝试使用Leaky ReLU或ELU函数;不建议使用tanh,尤其是sigmoid函数。

 

反向传播

假设我们输入X矩阵,经过W1矩阵,W2矩阵,W3矩阵……(也就是各种各样的层,实质上就是权重),最终可以得到一个损失函数的值,代表跟实际情况的差距,那么我们怎么利用这个使得W1W2W3(假设只有这三层)怎么得到更新呢?也就是说怎么样调节W1W2W3loss值下降?在神经网络中,我们利用反向传播来实现。我们要看的是,每一组权重,对我们的最终结果做了多大贡献。我们知道对一个目标函数进行优化都是通过求偏导来实现,这里也是一样,也就是说我们要求得最终结果对W3的偏导,对W2的偏导,对W1的偏导,但是对W2求偏导,中间要经过W3,怎么办呢?相信学过高数的大家已经猜到了,这里要用的是求导中的链式法则。也就是说。这样我们可以把求导的偏导一个一个往前传,最终更新到W1。这一过程称为反向传播。反向传播的过程也就是更新权重,使得整个神经网络朝着更好的方向优化的过程。


Softmax分类器

定义:

我们的网络最终要得到的是概率值,即属于某一个类别的概率值,然而一般训练得到的是一个得分值,因此需要做一个转换,比如我得到一张图片属于猫的得分为3.2,属于汽车的得分为5.1,属于青蛙的得分为-1.7,由于差距比较小,我们可以将这个差距放大之后再求概率,那就是某个分类的概率就是取e的x次幂再除以它们取e的x次幂之后的总和,那对应的softmax值就是[0.13,0.87,0.00]。

在神经网络中,我们需要计算神经网络正向传播计算的分数S1,和按照正确标签计算的分数S2之间的差距,计算出损失值,才能应用于反向传播,这里的loss定义如下


将上面求出来的softmax值取负对数,就得到了它的损失值,概率越大,这个样本的loss也就越小,符合我们的要求。

在反向传播中,我们需要求loss对每个权重矩阵的偏导,而使用softmax函数的话,最后结果的形式非常的简单,只要将算出来的概率的向量对应的真正结果的那一维减1,就可以了,假设我最终正确的分类是汽车,那么求出来的偏导就是[0.13,0.87-1,0.00]。

 

Dropout

因为神经网络实在是太强了,经常引入过多不必要的特征,导致模型泛化能力(Generalization)下降,很容易就过拟合,因此人们想尽各种办法来解决过拟合问题,而正则化方法就是为了防止过拟合,提高泛化能力而存在的。除了L2 regularization(权重衰减),L1 regularization这两种对代价函数动手脚的方法,还有一种叫做Dropout的方法,它不修改代价函数,而是直接调整神经网络的结构,更加彻底。这种方法非常简单,在实际运用中也有很好的效果。DNN网络将Dropout率设置为 p,它以以概率 p 来丢弃神经元,并且让别的神经元以概率 q = 1 -p进行保留。当一个神经元被丢弃时,无论输入或者相关的参数是什么,它的输出值就会被设置为0。因为这个原因,运用了dropout每一次训练,都像是在训练一个新的网络。每一个网络,都可以给出一个分类结果,这些结果有的是正确的,有的是错误的。随着训练的进行,大部分半数网络都可以给出正确的分类结果,那么少数的错误分类结果就不会对最终结果造成大的影响。

 

我们的图像处理流水线有一系列步骤:卷积,最大池化,全连接网络

而在解决实际问题的时候,这些步骤可以组合起来并堆叠多次。你可以加两个,三个甚至十个卷积层,也可以在任何时候插入一个最大池化层。总之基本思路就是把一张大图,逐步分解为小图,直至我们能够获得结果。卷积层越多,网络就能学习识别越复杂的特征。

比如说,第一个卷积层可能学会了辨认锐利边缘,第二个卷积层可能根据锐边的知识学会了识别鸟喙,第三个卷积层又基于鸟喙识别出了整只鸟。以下是更贴近实践的深度卷积网络结构(学术论文里常见):


更多关于CNN可以看看下面两篇文章,写的都挺不错的。

https://jizhi.im/blog/post/zen_bra

https://jizhi.im/blog/post/ml_is_fun_03