本教程是深度学习简明教程系列的第一部分,旨在提取最精炼且必备的深度学习知识点,供读者快速学习及本人查阅复习所用,大多内容是本人结合个人理解补充细节整合而成,参考链接放在文章最后。

目录

第一章  模型评估

1.1  基础概念

1.2  P-R曲线

1.3  ROC曲线和AUC

1.4  目标检测评价

1.5  语义分割评价

1.6  相关面试题

第二章  深度学习入门

2.1  机器学习到深度学习

2.2  前馈神经网络(MLP)

2.3  卷积神经网络(CNN)

2.4  循环神经网络(RNN)

2.5  相关面试题

第三章  激活函数

3.1  常用激活函数

3.2  相关面试题

第四章  损失函数

4.1  概览

4.2  分类任务损失函数

4.3  回归任务损失函数

4.4  相关面试题

第五章  优化算法

5.1  概述

5.2  存在的挑战

5.3  梯度下降优化方法

5.4  梯度优化额外的策略

 5.5  相关面试题

第六章  反向传播算法(BP算法)

6.1  神经网络

6.2  正向传播

6.3  反向传播

6.4  总结

6.5  相关面试题

第七章  梯度消失和梯度爆炸

7.1  产生原因

7.2  解决方案

7.3  相关面试题

第八章  范数正则化

8.1  正则化概述

8.2  L0范数与L1范数

8.3  L2范数

8.4  正则化参数的选择

8.5  相关面试题

第九章  Batch Normalization

9.1  使用BN的原因

9.2  什么是BN

9.3  BN具体是怎么做的

9.4  其他Normalization方法

9.5  相关面试题

第十章  Dropout

10.1  Dropout简介

10.2  模型变化

10.3  相关面试题

第十一章  注意力机制

11.1  注意力机制分类

11.2  注意力模块

11.3  相关面试题


 

第一章  模型评估

1.1  基础概念

假设有个样本,其中有个样本分类正确,则有:

  • 准确率(Accuracy):

  • 错误率(Error):

这两个指标虽然常用,但无法满足所有任务需求,我们还会用查准率(Precision)、召回率(Recall)、误检率(Noise Factor)、漏检率(Prob of Miss)来衡量分类效果。在二分类问题中,可以根据样本真实类别和预测类别的组合划分为:

  • 真阳(TP):预测为真,实际为真;

  • 假阳(FP):预测为真,实际为假;

  • 真阴(TN):预测为假,实际为假;

  • 假阴(FN):预测为假,实际为真。

因此有:

  • 查准率(Precision):,意即预测的正例有几个是对的;

  • 召回率(Recall):,意即真正的正例预测了几个;

  • 误检率(Noise Factor):,意即预测的正例有几个是错的;

  • 漏检率(Prob of Miss):,意即漏掉几个正例没检测出来。

1.2  P-R曲线

查准率和召回率是一对矛盾的度量指标,一般呈现负相关,在很多情况下,我们可以通过绘制出学习器的P-R曲线(Precision - Recall Curve)来比较学习器的好坏。P-R图以查准率为纵轴,召回率为横轴,大致如下图所示:

P-R曲线

如果一个学习器的P-R曲线被另一个学习器的P-R曲线完全包住,则可断言外层的学习器性能优于内层,例如上面的A和B优于学习器C。但是A和B的性能无法直接判断,我们可以根据曲线下方的面积大小来进行比较,但更常用的是平衡点或者是F1值:

  • 平衡点(BEP)是 P = R 时的取值,如果这个值较大,则说明学习器的性能较好。
  • F1 = 2 * P * R /( P + R ),同样,F1值越大,我们可以认为该学习器的性能较好。

注意:一条P-R曲线要对应一个阈值。通过选择合适的阈值,比如50%,对样本进行划分,概率大于50%的就认为是正例,小于50%的就是负例,从而计算相应的精准率和召回率。

1.3  ROC曲线和AUC

1.3.1  ROC曲线

接受者操作特性曲线(Receiver Operating Characteristic Curve),简称ROC曲线,纵轴是击中率(TPR),横轴是虚警率(FPR)。

击中率,也即真正类率(True Postive Rate):TPR = TP/(TP+FN),代表分类器预测的正类中实际正例占所有正例的比例。

虚警率,也即负正类率(False Postive Rate):FPR = FP/(FP+TN),代表分类器预测的正类中实际负例占所有负例的比例。

下图为ROC曲线示意图,因现实任务中通常利用有限个测试样例来绘制ROC图,因此应为无法产生光滑曲线,如右图所示。

ROC曲线

绘图过程:给定m个正例子,n个反例子,根据学习器预测结果进行排序,先把分类阈值设为最大,使得所有例子均预测为反例,此时TPR和FPR均为0,在(0,0)处标记一个点,再将分类阈值依次设为每个样例的预测值,即依次将每个例子划分为正例。设前一个坐标为(x,y),若当前为真正例,对应标记点为(x,y+1/m),若当前为假正例,则标记点为(x+1/n,y),然后依次连接各点。

注意:

  • ROC曲线也需要相应的阈值才可以进行绘制,原理同上的P-R曲线。
  • ROC曲线越左上凸越好,P-R曲线越右上凸越好。

1.3.2  AUC

AUC (Area under Curve):ROC曲线下的面积,介于0.1和1之间,作为数值可以直观的评价分类器的好坏,值越大越好。

  • AUC = 1,是完美分类器,采用这个预测模型时,存在至少一个阈值能得出完美预测。绝大多数预测的场合,不存在完美分类器;
  • 0.5 < AUC < 1,优于随机猜测。这个分类器(模型)妥善设定阈值的话,能有预测价值;
  • AUC = 0.5,跟随机猜测一样(例:丢硬币),模型没有预测价值。

1.4  目标检测评价

1.4.1  mAP

mAP(mean Average Precision)即各类别AP的平均值。由此我们可以知道,要计算mAP必须先绘出各类别P-R曲线,计算出AP。

1)VOC2010之前

只需要选取当Recall >= 0, 0.1, 0.2, ..., 1共11个点时的Precision最大值,然后AP就是这11个Precision的平均值。具体来说,计算precision时采用一种插值方法,即对于某个recall值r,precision值取所有recall>=r中的最大值(这样保证了p-r曲线是单调递减的,避免曲线出现抖动)。

11-point interpolation

2)VOC2010及其之后

需要针对每一个不同的Recall值r(包括0和1),Precision值取所有recall >= r+1中的最大值,然后计算PR曲线下面积作为AP值。

Interpolating all points

 

AP衡量的是对一个类检测好坏,mAP就是对多个类的检测好坏。就是简单粗暴的把所有类的AP值取平均就好了。

1.5  语义分割评价

评价指标一般包含如下三个方面:

  • 执行时间(execution time)
  • 内存占用(memory footprint)
  • 准确度(accuracy)

1.5.1  准确度

 

1.6  相关面试题

Q:

A:

 

第二章  深度学习入门

2.1  机器学习到深度学习

机器学习从发展角度来讲可以被分为频率派(统计机器学习)和贝叶斯派(概率图模型)。

  • 统计机器学习中主要应用到的四个思想分别是:正则化(L1、L2)、核化(Kernel SVM)、集成化(AdaBoost、RF)和层次化(Neural Network);其中,本文的主角——神经网络主要包括:多层感知机(MLP)、自编码器(AutoEncoder)、卷积神经网络(CNN)和循环神经网络(RNN),随着网络层次的加深,我们统称它们为深度神经网络(DNN)。
  • 概率图模型中主要包括三种模型分别是:有向图模型(Beyesian Network)、无向图模型(Markov Network)和混合模型(Mixed Network);其中,加入深度后它们又各自发展成了深度有向网络(Deep Directed Network)、深度玻尔兹曼机(Deep Boltzman Machine)、深度信念网络(Deep Belief Network),我们统称它们为深度生成模型(Deep Generative Model)。

狭义上的深度学习主要指的就是深度神经网络,广义上的深度学习就包括了深度生成模型,思维导图如下:

 

2.2  前馈神经网络(MLP)

2.2.1  MLP简介

前馈神经网络由输入层、若干个隐层和输出层组成,每层有若干个神经元,前层每个神经元和后层所有神经元均有连接(Fully Connected),连接的边上带有权重,神经元的输出就是输入和权重之积经过激活函数映射之后得到的值。

多层感知器能够学习任意非线性函数,其中非线性是通过引入激活函数来实现的,我们训练神经网络其实就是不断更新权值,使得网络输出结果能够以较小的误差正确拟合我们的数据。

2.2.2  MLP面临的挑战

在利用MLP解决图像分类问题时,首先要将二维图像转换成一维向量,然后再对模型进行训练。这样做有两个缺点:

1)随着图像尺寸的增大,可训练参数的数量会急剧增加;

2)MLP会丢失图像的空间特征。

2.3  卷积神经网络(CNN)

2.3.1  理解卷积

通俗来讲,图像处理中的卷积就是通过一个模板矩阵,在图像上进行滑窗,把对应位置上的元素相乘后加起来,得到最终的结果,可以形象理解为把原图像一块区域“卷”起来融合成新图像的一个像素点,这个模板矩阵即为卷积核。

假设原图像的大小为  ,卷积核大小为  ,往图像两边填充  个像素,滑窗步长为  ,则经过卷积后特征图的大小为:

假设原图像通道数为C1,卷积后通道数为C2,需要训练的参数量为:

浮点数相乘计算的次数为:

2.3.2  CNN简介

卷积神经网络(CNN)目前在深度学习领域非常热门,在图像和视频处理项目中尤其普遍。CNN的核心就在于卷积层,卷积层会使用若干个卷积核,在图像上进行滑窗卷积操作,通过卷积对图像特征进行抽象和提取,这么做有两个特点:

  1. 稀疏连接:CNN中后层神经元只于前层局部区域有连接;
  2. 权重共享:同一个卷积核的参数在滑窗计算过程中都是一样的。

卷积核的参数全部都是需要通过学习得到的,和ANN学习权重参数一样,而以上两个特性可以大幅降低训练参数数量,所以非常适合用于处理图像问题。

  • 卷积核的厚度 = 被卷积的图像的通道数
  • 卷积核的个数 = 卷积操作后输出的通道数

除了卷积层外,CNN中可能还包括池化层、激活层以及全连接层:

1)池化层(Pooling)通常位于卷积操作之后,其作用在于特征融合和降维,其实也是一种类似卷积的操作,只是池化层的所有参数都是超参数(Average Pooling / Max Pooling),都是不用学习得到的,池化操作的降维改变的是图像的宽高,而不改变通道数

2)激活层的主要作用在于增加非线性,值得注意的是卷积层中的激活过程针对的是每一个像素值,比如某卷积层输出中某个通道的 i 行 j 列像素值为x,只要这个数x>0,则x=x;x<0,则x=0。

3)全连接层:负责逻辑推断,所有的参数都需要学习得到。CNN中的全连接层用于链接卷积层的输出,并去除空间信息(通道数),是一种将三维矩阵变成向量的过程(一种全卷积操作),其操作如下:

输入特征图是W×H×C,那么卷积核的尺寸为W×H×C,这样的话整个输入特征图就变成了一个数,一共有k个数(第一层全连接层的神经元个数),就有K个W×H×C的卷积核,所以全连接层(尤其是第一层)的参数量是非常可怕的。

2.3.3  理解感受野

感受野用来表示神经网络内部的不同位置的神经元对原图像的感受范围的大小。神经元之所以无法对原始图像的全部信息进行感知,是因为在这些网络结构中普遍使用卷积层和pooling层,在层与层之间均为局部相连(通过sliding filter)。神经元感受野的值越大表示其能接触到的原始图像范围就越大,也意味着他可能蕴含更为全局、语义层次更高的特征;而值越小则表示其所包含的特征越趋向于局部和细节。因此感受野的值可以大致用来判断每一层的抽象层次。

由于图像是二维的,具有空间信息,因此感受野的实质其实也是一个二维区域。但业界通常将感受野定义为一个正方形区域,因此也就使用边长来描述其大小了。感受野的抽象公式如下:

其中, 为第n个卷积层的感受野, 和  分别表示第n个卷积层的kernel_size和stride。

2.3.4  特殊卷积结构

1、分组卷积(Group convolution)

分组卷积最早出现在AlexNet中,由于当时的硬件资源有限,训练AlexNet时卷积操作不能全部放在同一个GPU处理,因此作者把feature maps分给多个GPU分别进行处理,最过程中把多个GPU的结果进行通道concat。通过使用分组卷积可以大大减少参数量。

2、Inception结构

传统的层叠式网络,基本上都是一个个卷积层的堆叠,每层只用一个尺寸的卷积核,例如VGG结构中使用了大量的3×3卷积层。事实上,同一层feature map可以分别使用多个不同尺寸的卷积核,以获得不同尺度的特征,再把这些特征结合起来(concat),得到的特征往往比使用单一卷积核的要好,谷歌的GoogleNet,或者说Inception系列的网络,就使用了多个卷积核的结构。

3、Bottleneck结构

发明GoogleNet的团队发现,如果仅仅引入多个尺寸的卷积核,会带来大量的额外的参数,受到Network In Network中1×1卷积核的启发,为了解决这个问题,他们往Inception结构中加入了一些1×1的卷积核,如下图所示:

1×1卷积核也被认为是影响深远的操作,它主要用来改变通道数,降低参数量,往后大型的网络为了降低参数量都会应用上1×1卷积核。我们来做个对比计算,假设输入feature map的维度为256维,要求输出维度也是256维。有以下两种操作:

  • 256维的输入直接经过一个3×3×256的卷积层,输出一个256维的feature map,那么参数量为:256×3×3×256 = 589824
  • 256维的输入先经过一个1×1×64的卷积层,再经过一个3×3×64的卷积层,最后经过一个1×1×256的卷积层,输出256维,参数量为:256×1×1×64 + 64×3×3×64 + 64×1×1×256 = 69632,足足把第一种操作的参数量降低到九分之一。

4、深度可分离卷积(DepthWise Convolution)

标准的卷积过程如下图所示,一个2×2的卷积核在卷积时,对应图像区域中的所有通道均被同时考虑,问题在于,为什么一定要同时考虑图像区域和通道?我们为什么不能把通道和空间区域分开考虑?

标准卷积

Xception网络就是基于以上的问题发明而来。我们首先对每一个通道进行各自的卷积操作,有多少个通道就有多少个过滤器。得到新的通道feature maps之后,这时再对这批新的通道feature maps进行标准的1×1跨通道卷积操作。这种操作被称为 “DepthWise Convolution” ,缩写“DW”,它的直接作用就在于可以大幅降低参数量。

深度可分离卷积
  • 直接接一个3×3×256的卷积核,参数量为:3×3×3×256 = 6912
  • DW操作,分两步完成,参数量为:3×3×3 + 3×1×1×256 = 795,又把参数量降低到九分之一。

5、通道洗牌

在AlexNet的Group Convolution当中,特征的通道被平均分到不同组里面,最后再通过两个全连接层来融合特征,这样一来,就只能在最后时刻才融合不同组之间的特征,对模型的泛化性是相当不利的。为了解决这个问题,ShuffleNet在每一次层叠这种Group conv层前,都进行一次channel shuffle,shuffle过的通道被分配到不同组当中。进行完一次group conv之后,再一次channel shuffle,然后分到下一层组卷积当中,以此循环。

经过channel shuffle之后,Group conv输出的特征能考虑到更多通道,输出的特征自然代表性就更高。另外,AlexNet的分组卷积,实际上是标准卷积操作,而在ShuffleNet里面的分组卷积操作是depthwise卷积,因此结合了通道洗牌和分组depthwise卷积的ShuffleNet,能得到超少量的参数以及超越mobilenet、媲美AlexNet的准确率。

6、通道加权

无论是在Inception、DenseNet或者ShuffleNet里面,我们对所有通道产生的特征都是不分权重直接结合的,那为什么要认为所有通道的特征对模型的作用就是相等的呢? 这是一个好问题,于是,ImageNet 2017冠军SENet就出来了。

从上图可以看到,一组特征在上一层被输出,这时候分两条路线,第一条直接通过,第二条进行如下操作:

  1. 首先进行Squeeze操作(Global Average Pooling),把每个通道二维的特征图压缩成一个一维向量,从而得到一个特征通道向量(每个数字代表对应通道的特征);
  2. 然后进行Excitation操作,把这一列特征通道向量输入两个全连接层和sigmoid,建模出特征通道间的相关性,得到的输出其实就是每个通道对应的权重;
  3. 最后,把这些权重通过Scale乘法通道加权到原来的特征上(第一条路),这样就完成了特征通道的权重分配。

7、空洞卷积(Dilated Convolution)

标准的3×3卷积核只能看到对应区域3×3的大小,但是为了能让卷积核看到更大的范围,dilated conv使其成为了可能。dilated conv原论文中的结构如图所示:

上图b可以理解为卷积核大小依然是3×3,但是每个卷积点之间有1个空洞(dilated rate = 1),也就是在绿色7×7区域里面,只有9个红色点位置作了卷积处理,其余点权重为0。这样即使卷积核大小不变,但它看到的区域变得更大了。

8、可变形卷积(Deformable Convolution)

传统的卷积核一般都是长方形或正方形,但MSRA提出了一个相当反直觉的见解,认为卷积核的形状可以是变化的,变形的卷积核能让它只看感兴趣的图像区域 ,这样识别出来的特征更佳。

要做到这个操作,可以直接在原来的卷积核的基础上再加一层卷积核,这层卷积核学习的是下一层卷积核的位置偏移量(offset),实际增加的计算量是相当少的,但能实现可变形卷积核,识别特征的效果更好。

在实际操作时,并不是真正地把卷积核进行扩展,而是对卷积前图片的像素重新整合,变相地实现卷积核的扩张,具体来说可变性卷积的流程为:

  1. 原始图片大小为b*h*w*c,记为U,经过一个普通卷积,卷积填充为same,对应的输出结果为(b*h*w*2*k*k),记为V,输出的结果是指原图片batch中卷积核在每个像素上的偏移量(k*k的卷积核具有x偏移与y偏移,因此通道数为2*k*k);
  2. 将U中图片的像素索引值与V相加,得到偏移后的position(即在原始图片U中的坐标值),需要将position值限定为图片大小以内。但position只是一个坐标值,而且还是float类型的,我们需要这些float类型的坐标值获取像素。
  3. 例如取一个坐标值(a,b),将其转换为四个整数,floor(a), ceil(a), floor(b), ceil(b),将这四个整数进行整合,得到四对坐标(floor(a),floor(b)), ((floor(a),ceil(b)), ((ceil(a),floor(b)), ((ceil(a),ceil(b))。这四对坐标每个坐标都对应U中的一个像素值,而我们需要得到(a,b)的像素值,这里采用双线性差值的方式计算(一方面得到的像素准确,另一方面可以进行反向传播)。
  4. 在得到position的所有像素后,即得到了一个新图片M,将这个新图片M作为输入数据输入到别的层中,如普通卷积。

9、上采样、上池化和转置卷积

1)上采样(UnSampling)

UnSampling阶段没有使用MaxPooling时的位置信息,而是直接将内容以插值方式来扩充Feature Map,属于人工特征工程,没有要学习的参数。常用上采样方法有:最近邻插值(Nearest neighbor interpolation)、双线性插值(Bi-Linear interpolation)、双立方插值(Bi-Cubic interpolation)

 

上采样

2)上池化(UnPooling)

在Maxpooling的时候保留最大值的位置信息,之后在UnPooling阶段使用该信息扩充Feature Map,除最大值位置以外,其余补0。

 

上池化

3)转置卷积(Deconvolution)

反卷积是一种特殊的正向卷积,先按照一定的比例通过补0来扩大输入图像的尺寸,接着旋转卷积核(参数与之前正向卷积过程中使用到的卷积核参数一致),再进行卷积。具体步骤如下:

  1. 设卷积核大小为k*k,输入为方形矩阵;
  2. 对输入进行四边补零,单边补零的数量为k-1;
  3. 将卷积核旋转180°,在新的输入上进行直接卷积。

 

 

 

下图展示一个反卷积的工作过程,乍看一下好像反卷积和卷积的工作过程差不多,主要的区别在于反卷积输出图片的尺寸会大于输入图片的尺寸,通过增加padding来实现这一操作。

下图中的反卷积的stride为2,通过间隔插入padding来实现的。同样,可以根据反卷积的o、s、k、p参数来计算反卷积的输出i,也就是卷积的输入。公式如下:i=(o−1)s+k−2p,其实就是根据上式推导出来的。

2.3.5  卷积的可视化

1、可视化方案

总体思路就是将某一层的feature maps 经过相反的结构。如经过max pooling层那么就在对称位置记住所取位置后,unpooling到相应位置,如经过relu那么在对称位置在经过一次relu,如经过conv那么在对称位置使用相同的Filter的转置进行deconv。

  1. 反池化:我们知道,池化是不可逆的过程,然而我们可以通过记录池化过程中,最大激活值得坐标位置。然后在反池化的时候,只把池化过程中最大激活值所在的位置坐标的值激活,其它的值置为0,当然这个过程只是一种近似,因为我们在池化的过程中,除了最大值所在的位置,其它的值也是不为0的。
  2. 反激活:反激活过程和激活过程没有什么差别,都是直接采用relu函数。
  3. 反卷积:对于反卷积过程,采用卷积过程转置后的卷积核(参数一样,只不过把参数矩阵水平和垂直方向翻转了一下),反卷积实际上应该叫卷积转置。

最后可视化网络如下图所示:

网络的整个过程,从右边开始:输入图片-->卷积-->Relu-->最大池化-->得到结果特征图-->反池化-->Relu-->反卷积。

举个例子:假如你想要查看Alexnet 的conv5提取到了什么东西,我们就用conv5的特征图后面接一个反卷积网络,然后通过:反池化、反激活、反卷积,这样的一个过程,把本来一张13*13大小的特征图(conv5大小为13*13),放大回去,最后得到一张与原始输入图片一样大小的图片(227*227)。

2、理解可视化

从上图可看出:

  • layer 1、layer 2学习到的特征基本上是颜色、边缘等低层特征
  • layer 3则开始稍微变得复杂,学习到的是纹理特征,比如上面的一些网格纹理;
  • layer 4学习到的则是比较有区别性的特征,比如狗头等物体的局部;
  • layer 5学习到的则是物体整体的信息,具有辨别性关键特征

总的来说,通过CNN学习后,我们学习到的特征,是具有辨别性的特征,比如要我们区分人脸和狗头,那么通过CNN学习后,背景部位的激活度基本很少,我们通过可视化就可以看到我们提取到的特征忽视了背景,而是把关键的信息给提取出来了。

3、特征学习过程

在网络训练过程中,每一层学习到的特征是怎么变化的,上面每一张图片是网络的某一层特征图,然后每一行有8个小图片,分别表示网络epochs次数为:1、2、5、10、20、30、40、64的特征图,可以看出前几层(lower)收敛较快,后几层收敛较慢。

上图是对应着图像平移、缩放、旋转给featuremap带来的变化,可以看出第一层中对于图像变化非常敏感,第7层就接近于线性变化,最后的输变化就相对较小了。

2.3.6  总结

总的来说,卷积核的发展有如下几个方面和特点:

卷积核方面:

  1. 大卷积核用多个小卷积核代替;
  2. 单一尺寸卷积核用多尺寸卷积核代替;
  3. 固定形状卷积核趋于使用可变形卷积核;
  4. 使用1×1卷积核(bottleneck结构)。

卷积层通道方面:

  1. 标准卷积用depthwise卷积代替;
  2. 使用分组卷积;
  3. 分组卷积前使用通道洗牌;
  4. 通道加权计算。

卷积层连接方面:

  1. 使用skip connection,让模型更深;
  2. Densely connection,使每一层都融合上其它层的特征输出(DenseNet)

2.4  循环神经网络(RNN)

2.4.1  基础RNN结构

普通神经网络由于结构问题,对于时序任务,会独立的去处理每个数据项,难以有效学习各个数据项之间的上下文依赖关系。

RNN的提出主要就是用来解决序列问题,强调的是先后顺序,借助RNN的hidden state记忆单元,使得一个序列位置的输出在数学上和之前的所有序列的输入都是有关系的,常见RNN网络结构如下:

左边是RNN网络,右边是RNN网络按时序展开的形式,其实就是同一个神经网络单元(同样的权重在各个时间步共享),t 时刻的hidden status是当前的时间步的数据和上一时间步的hidden status(记忆)拼接成大的矩阵后经过一个tanh函数激活的结果,同时需要把结果  作为记忆信息输入到下一时刻(  初始化为0)。

内部具体结构如下图所示:

RNN的几种结构:

1)RNN(N vs N)网络结构

2)RNN(N vs 1)网络结构

输出经过一个softmax后即可得到分类结果

3)RNN(1 vs N)网络结构

4)RNN(N vs M)网络结构

RNN存在的问题:

  1. 原始的RNN中,由于隐状态信息中的长期信息计算时会反复连乘权重矩阵,如果权重矩阵W小于1,就会导致长期信息对后面数据项的影响近乎为0,从而无法学习长期依赖关系;
  2. RNN存在梯度消失问题:RNN梯度消失是因为在反向传播求损失函数偏导时,需要连乘tanh函数的导数,而tanh的导数值域在0到1之间,链式法则中的连乘效应将导致求得的偏导越来越小,从而导致梯度消失(RNN 中同样的权重在各个时间步共享,最终的梯度 g = 各个时间步的梯度 gt 的和,因此RNN中总的梯度是不会消失的,RNN 所谓梯度消失的真正含义是,梯度被近距离梯度主导,导致模型难以学到远距离的依赖关系);
  3. RNN存在梯度消失问题:当Wh参数初始化为足够大,使得tanh函数的导数乘以W大于1,则连乘效应将导致偏导极大,从而导致梯度爆炸。

2.4.2  LSTM结构

为了解决RNN存在的几个问题,提出了LSTM神经网络,它可以通过门控机制解决无法学习长期依赖的问题(将梯度乘性问题转变成加性问题),有挑选的将信息放入到细胞状态线里,从某种角度类似时间线上的attention机制。LSTM结构图如下所示:

1、细胞状态和隐状态

LSTM相比RNN的hidden status还引入了细胞状态来记录信息,细胞状态通过门结构gate来添加新的记忆和删除旧的记忆信息。

添加和删除信息的原理:输入矩阵通过sigmoid激活函数后就会得到0~1取值范围的矩阵,再和上一时刻的cell state矩阵进行点乘,就可以实现过滤部分信息的效果。

2、门控结构

LSTM通过遗忘门来决定从上个隐状态记忆中忘记哪些信息,通过输入门来决定输入哪部分信息,通过输出门来决定输出哪部分信息,以此解决长时依赖问题。下面我们详细介绍一下LSTM中的各种门:

1)遗忘门

通过遗忘门可以通过过滤矩阵选择性忘记cell state中的部分记忆信息。

2)输入门

这一步进行了两个操作:一个是经过输入门产生了一个过滤矩阵来决定那些信息来加入到本时刻的cell state中;另一步是通过上一时刻的hidden state和新的输入来计算这步的待输入信息;然后,待输入信息和输入门产生的过滤矩阵点乘,产生最终需添加到cell state的新信息。

3)输出门

将新的cell state信息经过tanh激活后,再和输出门产生的过滤矩阵点乘,得到此刻的隐状态 

LSTM中梯度的传播有很多条路径,细胞记忆上多是逐元素的相乘和相加,梯度流稳定,因此能够解决RNN无法学习长期依赖和梯度消失的问题;但是,LSTM 仍然有可能发生梯度爆炸,不过,由于 LSTM 的其他路径非常崎岖,和普通 RNN 相比多经过了很多次激活函数(导数都小于 1),因此 LSTM 发生梯度爆炸的频率要低得多。

2.4.3  GRU结构

GRU的结构如下,主要包含重置门和更新门,把GRU看着LSTM的变体,相当于取消了LSTM中的cell state,只使用了hidden state,并且使用update gate更新门来替换LSTM中的输入门和遗忘门,取消了LSTM中的输出门,新增了reset gate重置门。这样做的好处是在达到LSTM相近的效果下,GRU参数更少,训练的计算开销更小,训练速度更快。

重置门:多大程度上擦除以前的隐状态

更新门:忘记传递下来的  中的某些维度信息,并加入当前时刻输入的某些维度信息。

2.5  相关面试题

Q:用Pytorch搭建一个神经网络的大概流程是什么样的?

A:

  1. 首先,定义一个类,也就是我们的神经网络模型,继承自nn.Module;
  2. 这个类有两个方法,第一个函数是__init__(self),可以在里面自己初始化或者是载入网络结构;第二函数是forward(self, input),接收样本数据,并在我们定义的网络上正向传播,返回计算结果;
  3. 完成网络模型类的定义后,我们会在全局变量中定义一些超参数,譬如batch_size、学习率、权重衰减、动量等等;
  4. 在训练时,我们先声明一个网络模型,然后根据需求定义优化器和损失函数;
  5. 之后,我们还可以再载入预训练的模型参数,并DataLoader加载我们的样本集;
  6. 最后,开始若干轮训练,每一次都将样本在网络上传播,计算loss,然后结合优化器,将损失反向传播。
  7. 训练完后,就可以获得最终模型,把权重存下来即可。

Q:Pytorch和Tensorflow的区别

A:

  1. Tensorflow是一种静态框架,在使用时需要先构造一个计算图,构造完之后这个计算图就不能改变了。然后我们再开启会话,输入数据进行计算。而Pytorch是一种动态框架,计算图是在运行时构建的,可以直接输入数据进行计算,不需要采用会话;
  2. Tensorflow是静态计算图,数据参数在CPU与GPU之间迁移麻烦,调试也麻烦;Pytorch是动态计算图,数据参数在CPU与GPU之间迁移十分灵活,调试简便;

Q:

A:

第三章  激活函数

定义:在神经网络中,神经元节点的激活函数定义了对神经元输出的映射,即神经元的输出经过激活函数处理后再作为输出。

作用:神经网络中激活函数的主要作用是提供网络的非线性建模能力,如不特别说明,激活函数一般而言是非线性函数。

3.1  常用激活函数

3.1.1  Sigmoid函数

Sigmoid 是使用范围最广的一类激活函数,具有指数函数形状 。定义为:

可见,sigmoid在定义域内处处可导,两侧导数逐渐趋近于0,也称为软饱和激活函数;与软饱和相对的是硬饱和激活函数,即:f'(x)=0,当 |x| > c,其中 c 为常数。

缺点:1)梯度消失;2)输出均值始终大于0,收敛慢。

3.1.2  Tanh函数

可见,tanh(x)=2sigmoid(2x)-1,也具有软饱和性。tanh 网络的收敛速度要比sigmoid快。因为 tanh 的输出均值比 sigmoid 更接近 0,SGD会更接近 natural gradient(一种二次优化技术),从而降低所需的迭代次数。

缺点:1)梯度消失。

3.1.3  ReLU函数

与传统的sigmoid激活函数相比,ReLU能够有效缓解梯度消失问题,从而直接以监督的方式训练深度神经网络,无需依赖无监督的逐层预训练,这也是2012年深度卷积神经网络在ILSVRC竞赛中取得里程碑式突破的重要原因之一。

可见,ReLU 在x<0 时硬饱和;由于 x>0时导数为 1,所以,ReLU 能够在x>0时保持梯度不衰减,从而缓解梯度消失问题。但其仍存在几个问题:

  1. 随着训练的推进,部分输入会落入硬饱和区,导致对应权重无法更新,这种现象被称为“神经元死亡”。
  2. ReLU还经常被“诟病”的一个问题是输出存在偏移现象,即输出均值恒大于零,偏移现象和神经元死亡会共同影响网络的收敛性。

3.1.4  PReLU函数

PReLU是ReLU 和 LReLU的改进版本,具有非饱和性:

与Leaky ReLU相比,PReLU中的负半轴斜率a可学习而非固定,虽然PReLU 引入了额外的参数,但基本不需要担心过拟合。与ReLU相比,PReLU收敛速度更快,因为PReLU的输出更接近0均值。

3.1.5  RReLU函数

数学形式与PReLU类似,但RReLU是一种非确定性激活函数,其参数是随机的。这种随机性类似于一种噪声,能够在一定程度上起到正则效果。

3.1.6  Maxout函数

Maxout是ReLU的推广,其可以看做是在深度学习网络中加入一层激活函数层,包含一个参数n。这一层相比ReLU,sigmoid等,其特殊之处在于增加了n个神经元,然后输出激活值最大的值。

Maxout网络能够近似任意连续函数,且当w2,b2,…,wn,bn为0时,退化为ReLU。Maxout能够缓解梯度消失,同时又规避了ReLU神经元死亡的缺点,但增加了参数和计算量。

3.1.7  ELU函数

ELU融合了sigmoid和ReLU,具有左侧软饱性。其正式定义为:

右侧线性部分使得ELU能够缓解梯度消失,而左侧软饱能够让ELU对输入变化或噪声更鲁棒。ELU的输出均值接近于零,所以收敛速度更快。

3.2  相关面试题

Q:

A:

 

 

第四章  损失函数

4.1  概览

4.2  分类任务损失函数

4.2.1  二分类交叉熵损失(sigmoid_cross_entropy)

其中, 是样本标签(0/1), 是模型预测样本为正例的概率。

4.2.2  二分类平衡交叉熵损失(balanced_sigmoid_cross_entropy)

其中, 是样本标签(0/1), 是模型预测样本为正例的概率, 是一个超参数。

4.2.3  多分类交叉熵损失(softmax_cross_entropy)

其中, 是类别数, 是样本标签的onehot表示, 中每个元素  表示样本属于第  类的概率。

4.2.4  Focal Loss

Focal Loss主要用于解决多分类任务中样本不平衡的现象,可以获得更好的分类效果:

其中,  用于平衡不同类别样本的重要性, 表示给第  类样本分配的权重,数量少的类别分配更大的权重,数量多的减小权重; 用于控制预测结果的loss大小,概率大说明是容易分类的样本,loss就会减小,概率小说明是困难、错分的样本,loss就会增大,通过这一参数可以使模型更关注于困难样本。论文中α=0.25,γ=2效果最好。

4.2.5  Dice Loss

dice系数源于二分类,本质上是衡量两个样本的重叠部分,二分类时使用该loss,本质就是不断学习,使得交比并越来越大。

最终Dice Loss = 1 - DSC

4.2.6  合页损失(hinge loss)

svm中使用的损失函数,由于合页损失优化到满足小于一定gap距离就会停止优化,而交叉熵损失却是一直在优化,所以,通常情况下,交叉熵损失效果优于合页损失。

  • 当  大于等于+1或者小于等于-1时,都是分类器确定的分类结果,此时的损失函数loss为0;
  • 当预测值时,分类器对分类结果不确定,loss不为0。显然,当  时,loss达到最大值。

4.2.7  KL散度

KL散度( Kullback–Leibler divergence),也叫相对熵,是描述两个概率分布P和Q差异的一种方法。

从上述公式中我们可以看出,KL散度 = 交叉熵 - 熵。

4.3  回归任务损失函数

4.3.1  均方误差(Mean Square Error, MSE)

MSE表示了预测值与目标值之间差值的平方和然后求平均。

L2损失表示了预测值与目标值之间差值的平方和然后开更方,L2表示的是欧几里得距离。

MSE和L2的曲线走势都一样。区别在于一个是求的平均,一个是求的开方。

4.3.2  平均绝对误差(Mean Absolute Error, MAE)

MAE表示了预测值与目标值之间差值的绝对值然后求平均。

L1表示了预测值与目标值之间差值的绝对值,L1也叫做曼哈顿距离。

MAE和L1的区别在于一个求了均值,一个没有求,两者的曲线走势也是完全一致的。

总结:MAE/L1 Loss 对于局外点更鲁棒,但它的导数不连续使得寻找最优解的过程低效;MSE/L2 Loss 对于局外点敏感,但在优化过程中更为稳定和准确。

4.3.3  Huber Loss和Smooth L1 Loss

Huber loss具备了MAE和MSE各自的优点,当δ趋向于0时它就退化成了MAE,而当δ趋向于无穷时则退化为了MSE。

Smooth L1 loss具备了L1 loss和L2 loss各自的优点,本质就是L1和L2的组合。

Huber loss和Smooth L1 loss具有相同的曲线走势,当Huber loss中的δ等于1时,Huber loss等价于Smooth L1 loss。

对于Huber损失来说,δ的选择十分重要,它决定了模型处理局外点的行为。当残差大于δ时使用L1损失,很小时则使用更为合适的L2损失来进行优化。Huber损失函数克服了MAE和MSE的缺点,不仅可以保持损失函数具有连续的导数,同时可以利用MSE梯度随误差减小的特性来得到更精确的最小值,也对局外点具有更好的鲁棒性。但Huber损失函数的良好表现得益于精心训练的超参数δ。

4.3.4  对数双曲余弦(Log Cosh Loss)

 

其优点在于对于很小的误差来说log(cosh(x))与(x2)/2很相近,而对于很大的误差则与abs(x)-log2很相近。这意味着log-cosh损失函数可以在拥有MSE优点的同时也不会受到局外点的太多影响。它拥有Huber的所有优点,并且在每一个点都是二次可导的。

4.4  相关面试题

Q:

A:

 

第五章  优化算法

5.1  概述

机器学习的本质是建立优化模型,通过优化方法,不断迭代参数向量,找到使目标函数最优的参数向量,最终建立模型。通常用到的优化方法:梯度下降方法、牛顿法、拟牛顿法等。这些优化方法的本质就是在更新参数。

5.1.1  梯度下降法

梯度下降是一种最小化目标函数 J(θ) 的方法,其中 是模型参数,而最小化目标函数是通过在其关于 θ 的 梯度 的相反方向更新 θ 来实现的;而学习率(learning rate)则决定了在到达(局部)最小值的过程中每一步走多长。

梯度下降目前主要有三种方式:

  • 批量梯度下降(BGD,每次进行一次参数更新需要在整个训练集上计算梯度);
  • 随机梯度下降(SGD,每次只使用一个随机的样本进行参数更新);
  • 小批量梯度下降(MBGD,每次从训练集中取出 n 个样本作为一个 mini-batch,以此来进行一次参数更新)。根据数据量的大小,我们在参数更新的准确性和执行更新所需时间之间做了一个权衡。

Q:MBGD中batch size的选择

A:

1)为什么 batch size 会影响训练结果

 

2)在合理范围内,增大 Batch_Size 有何好处

  1. 内存利用率提高了,大矩阵乘法的并行化效率提高;

  2. 跑完一个epoch(全数据集)所需的迭代次数减少,对于相同数据量的处理速度进一步加快;

  3. 在一定范围内,一般来说 Batch_Size 越大,其确定的下降方向越准,引起训练震荡越小。

3)盲目增大 Batch_Size 有何坏处

  1. 内存利用率提高了,但是内存容量可能撑不住了;

  2. 跑完一次 epoch(全数据集)所需的迭代次数减少,但所花费的时间大大增加了,从而对参数的修正也就显得更加缓慢;

  3. Batch_Size 增大到一定程度,其确定的下降方向已经基本不再变化。

运行结果如上图所示,其中绝对时间做了标准化处理。运行结果与上文分析相印证:

5.1.2  牛顿法

首先得明确,牛顿法是为了求解函数值为零的时候变量的取值问题的,具体地,当要求解 f(θ)=0 时,如果 f 可导,那么可以通过迭代公式

来迭代求得最小值,可以通过一个动图来说明这个过程。

在机器学习中,我们应用牛顿法求解目标函数的一阶导数为0时的参数,进而求出目标函数最小值时的参数。那么迭代公式变为:

当θ是向量时,牛顿法可以使用下面式子表示:

其中H叫做海森矩阵,其实就是目标函数对参数向量 θ 的二阶导数。下面给出牛顿法的完整算法描述:

  1. 给定参数初值  和精度阈值  ,并令t = 0;
  2. 计算目标函数对于参数向量的一阶导数  和二阶导数 H;
  3. 若 ,则停止迭代,否则确定搜索方向 ;
  4. 计算新的参数;
  5. 令,转至第二步。

通过比较牛顿法和梯度下降法的迭代公式,可以发现两者及其相似,海森矩阵的逆就好比梯度下降法的学习率参数alpha。

牛顿法的优缺点总结:

优点:二阶收敛,收敛速度快;同时,海森矩阵的的逆在迭代中不断减小,起到逐渐缩小步长的效果。

缺点:牛顿法是一种迭代算法,每一步都需要求解目标函数的Hessian矩阵的逆矩阵,计算比较复杂。

5.1.3  拟牛顿法

拟牛顿法的本质思想是改善牛顿法每次需要求解复杂的Hessian矩阵的逆矩阵的缺陷,它使用正定矩阵来近似Hessian矩阵的逆,从而简化了运算的复杂度。

这样的迭代与牛顿法类似,区别就在于用近似矩阵  代替真实的Hesse矩阵。所以拟牛顿法最关键的地方就是每一步迭代中矩阵 的更新。具体来说,求近似矩阵的方法有:

1)DFP算法

2)BFGS算法

3)L-BFGS算法

5.2  存在的挑战

在深度学习中,我们很少去用牛顿法,而是采用梯度下降法,但是标准的 MBGD 并不保证好的收敛,也提出了以下需要被解决的问题:

  1. 选择一个好的学习率是非常困难的。太小的学习率导致收敛非常缓慢,而太大的学习率则会阻碍收敛,导致损失函数在最优点附近震荡甚至发散。
  2. 学习率不能做到自适应数据的特点。学习率的减小规则和阈值也是需要在训练前定义好的,另外,相同的学习率被应用到所有参数更新中。如果我们的数据比较稀疏,特征有非常多不同的频率,那么此时我们可能并不想要以相同的程度更新他们,反而是对更少出现的特征给予更大的更新。
  3. 对于神经网络来说,另一个最小化高度非凸误差函数的关键挑战是避免陷入他们大量的次局部最优点(suboptimal)传统的梯度下降方法难以逃脱鞍点,因为其各个维度上梯度都趋近于0。

5.3  梯度下降优化方法

5.3.1  动量法(Momentum)

SGD 在遇到沟壑时会比较困难(即在一个维度上比另一个维度更陡峭的曲面),这些曲面通常包围着局部最优点。在这些场景中,SGD 震荡且缓慢的沿着沟壑的下坡方向朝着局部最优点前进,如下图所示:

动量(Momentum)是一种在相关方向加速 SGD 的方法,并且能够减少震荡。

原理:它通过在当前更新向量(梯度方向)中加入了先前一步的状态,对于那些当前的梯度方向与上一次梯度方向相同的向量维度进行加强,即这些方向上更快了;对于那些当前的梯度方向与上一次梯度方向不同的向量维度进行削减,即这些方向上减慢了。因此可以获得更快的收敛速度与减少振荡。

其具体计算公式如下

其中,动量项 γ 通常设置为 0.9 或者相似的值。

5.3.2  Nesterov Accelerated Gradient(NAG)

Momentum中,θ 每次都会多走  的量;在NAG中,我们直接让 θ 先走到  之后的地方,然后再根据那里的梯度前进一步,这种预期更新防止我们下降得太快,也带来了更高的响应速度,这在一些任务中非常有效的提升了性能。

  • 动量法首先计算当前梯度(图 4 中的小蓝色向量),然后在更新累积梯度方向上大幅度的跳跃(图 4 中的大蓝色向量);
  • NAG 首先在先前的累积梯度方向上进行大幅度的跳跃(图 4 中的棕色向量),评估这个梯度并做一下修正(图 4 中的红色向量),这就构成一次完整的 NAG 更新(图 4 中的绿色向量)。

NAG算法相对于Momentum多了一个本次梯度相对上次梯度的变化量,这个变化量本质上是对目标函数二阶导的近似。由于利用了二阶导的信息,NAG算法才会比Momentum具有更快的收敛速度。

通过上面的两种方法,可以做到每次学习过程中能够根据损失函数的斜率做到自适应更新来加速SGD的收敛。下一步便需要对每个参数根据参数的重要性进行各自自适应更新。

5.3.3  Adagrad

Adagrad也是一种基于梯度的优化算法,它能够对不同时刻的参数 θ 自适应不同的学习速率,对稀疏特征,得到大的学习更新,对非稀疏特征,得到较小的学习更新,因此该优化算法适合处理稀疏特征数据。其计算公式如下:

其中  是一个对角矩阵,对角元素  是参数  从开始到时间点 t 为止的梯度平方和;ϵ 是一个平滑项,用于防止分母为 0 ,通常为 10−8 左右; 为目标函数关于参数 θ 在 t 时刻的梯度。

Adagrad的优缺点

优势:在于它能够为每个参数自适应不同的学习速率,而一般的人工都是设定为0.01。

缺点:在于需要计算参数梯度序列平方和,并且学习速率趋势是不断衰减最终达到一个非常小的值。

5.3.4  RMSProp

RMSProp是 Adagrad 的扩展,旨在帮助缓解后者学习率单调下降的问题。与 Adagrad 累积过去所有梯度的平方和不同,RMSProp主要有两个方面的改进:

  • Adadelta 限制在过去某个大小为w的窗口内的梯度(相当于滑动平均值);
  • 存储先前 w 个梯度的平方效率不高,Adadelta 的梯度平方和被递归的定义为过去所有梯度平方的滑动平均值。

在 t 时刻的滑动平均值 仅仅取决于先前的平均值和当前的梯度:

先前我们推导过的 Adagrad 的参数更新向量,我们现在用过去梯度平方和的滑动平均 来代替对角矩阵 :

由于分母只是一个梯度的均方根误差(Root Mean Squared,RMS),我们可以用缩写来代替:

这种方法即RMSProp,解决了对历史梯度一直累加而导致学习率一直下降的问题,但仍需要自己选择初始的学习率。

Hinton 建议将 γ 设为 0.9 ,默认学习率 η 设为 0.001 。

5.3.5  Adadelta

为了解决参数更新中单位不匹配的问题,并自适应的选择一个学习率,Adadelta定义了另一个关于参数  的滑动平均:

那么参数的均方根误差即为:

由于  未知,采用上一步  来代替学习率  ,最终得到Adadelta的更新规则:

5.3.6  Adam

Adaptive Moment Estimation是另一种为每个参数计算自适应学习率的方法。除了像 Adadelta 和 RMSprop 一样存储历史梯度平方的滑动平均值  外,Adam 也存储历史梯度的滑动平均值 ,类似于动量:

  与  分别是梯度的带权平均和带权有偏方差,初始为0向量,Adam的作者发现他们倾向于0向量,特别是在衰减因子β1,β2接近于1时。为了改进这个问题,对  与  进行偏差修正:

最终Adam的更新公式为:

作者建议 β1 的默认值为 0.9 , β2 的默认值为 0.999 ,ϵ 的默认值为 10−8 。实践证明 Adam 在训练中非常有效,而且对比其他自适应学习率算法也有优势。

5.4  梯度优化额外的策略

介绍一些可以和前面讨论的算法一起使用的策略,用以进一步提升 SGD 的性能。

1)Shuffling and Curriculum Learning

  • 为了使得学习过程更加无偏,应该在每次迭代中随机打乱训练集中的样本。
  • 另一方面,在很多情况下,我们是逐步解决问题的,而将训练集按照某个有意义的顺序排列会提高模型的性能和SGD的收敛性,如何将训练集建立一个有意义的排列被称为Curriculum Learning。

2)Batch normalization

  • Batch normalization在每次mini-batch反向传播之后重新对参数进行0均值、1方差的标准化过程。这样可以使用更大的学习速率,以及花费更少的精力在参数初始化点上。Batch normalization充当着正则化、减少甚至消除掉Dropout的必要性。

3)Early stopping

  • 在验证集上如果连续的多次迭代过程中损失函数不再显著地降低,那么应该提前结束训练。

4)Gradient noise

 5.5  相关面试题

Q:

A:

 

第六章  反向传播算法(BP算法)

基本思想: BP算法就是目前使用较为广泛的一种参数学习算法。其主要由由信号的正向传播(求损失)与误差的反向传播(误差回传)两个过程组成。

6.1  神经网络

假设我们有一个神经网络,第  层的输入定义为  ,经过激活函数后的输出定义为  ,激活函数定义为  ,本层的权重定义为 ,大致如下图所示:

通常来说,这些参数的形式如下:

                                           

其中, 表示第  层神经元的个数,例如上图中的例子, 就是一个三行两列的矩阵。

6.2  正向传播

正向传播就是将样本输入到神经网络,从而获得输出值的过程,其中涉及到了两个重要的公式:

利用这两个式子,我们只需要通过权重矩阵和偏置值,就可以一路计算得到神经网络每一层的输入  和输出 ,并记录下来。

6.3  反向传播

BP算法是一种更新权重的方法,我们知道每一层都有一个权重  ,在BP算法中,我们通过梯度下降法来更新每层的权重:

其中,L为模型的损失函数,它是关于最后一层输出  的一个函数, 是学习率。

该方法的关键在于如何求出损失函数关于神经网络某一隐层权重权值矩阵的偏导。

在正向传播中我们可以很容易看出,神经网络最后一层的输出  ,其实是关于某个隐层输入  的函数,综上我们可以得到损失函数L是关于某个隐层权重矩阵的函数:

为此,通过链式法则我们可以得到:

此时,我们定义左边这一项为误差项 ,则有:

其中,我们可以看到  是我们在正向传播中记录下来的输出值,所以问题就转化为我们如何求得每一层的误差项  了。

在正向传播 中,我们有两个重要公式,通过他们结合链式法则,我们可以将  进一步拆解:

 

这个公式告诉我们,只要知道了  层的误差项和权重矩阵,我们就可以求得  层的误差项。实际应用到BP算法中,步骤如下:

  1. 先求最后一层的误差项;
  2. 根据该层误差项求得获得损失函数对于该层权重矩阵的偏导;
  3. 利用梯度下降法计算权重矩阵的更新值;
  4. 往前递推前一层的误差项,转至第2步,直至更新完所有层的权重。

假设损失函数为MSE,最后一层的误差项是可以直接根据损失函数 L 计算得到的:

6.4  总结

我们只解决了给一组数据如何更新权重,它叫做标准误差传播算法。它对于每个训练样本都会改变一次所有的权值。但是它的更新非常非常频繁,而且容易受到干扰。我们希望误差累积到一定程度以后再一次性更新,因此需要用累积误差逆传播算法因此,我们每次更新应该是要对n个训练集累积下来的误差求平均,再用来更新权重矩阵。

综上所述,BP算法的整体流程如下:

  1. 初始化权重矩阵和偏置;
  2. 将训练集输入神经网络正向传播,记录下每层的输入输出等中间变量;
  3. 利用损失函数,先求最后一层的误差项;
  4. 根据该层误差项求得获得损失函数对于该层权重矩阵的偏导;
  5. 利用梯度下降法计算权重矩阵的更新值;
  6. 往前递推前一层的误差项,跳至第4步,直至更新完所有层的权重。

具体实际的例子,可以参考:https://www.jianshu/p/708e11654913

6.5  相关面试题

Q:

A:

 

第七章  梯度消失和梯度爆炸

7.1  产生原因

7.1.1  梯度消失

以下图的反向传播为例,

假设每一层只有一个神经元且对于每一层输出:

其中σ为sigmoid函数,xi为输入值,zi为净激活值。我们可以推导出:

而sigmoid的导数σ'(x)如下图

从上图我们可以看到,σ'(x)的最大值为0.25,而且我们初始化的权重绝对值通常都小于1。于是,当神经网络的层数越多,在链式法则中连乘激活函数的导数越多次,求导的结果就越小,因而会出现梯度消失的现象。

7.1.2  梯度爆炸

若我们初始化的权重w很大,大到乘以激活函数的导数都大于1,即|σ'(z)w|>1,那么连乘后,可能会导致求导的结果很大,形成梯度爆炸。

7.2  解决方案

梯度消失和梯度爆炸本质上是一样的,都是因为网络层数太深而引发的梯度反向传播中的连乘效应。

7.2.1  梯度消失解决方案

  1. 换用Relu等其他激活函数;

  2. 采用BN,将输入值的分布落入激活函数中对输入比较敏感的区域(即梯度大的区域),从而避免梯度消失;

  3. 采用ResNet残差结构;

  4. 采用LSTM结构;

7.2.2  梯度爆炸解决方案

  1. 采用好的参数初始化方式,如He初始化;

  2. 预训练(pre-training)和微调(fine tuning):预训练就是把一个已经训练好的模型参数,应用到另一个任务上作为初始参数的过程;微调就是指将预训练过的模型作用于自己的数据集,并使参数适应自己数据集的过程;

  3. 梯度截断:设值一个剪切阈值,如果更新梯度时,梯度超过了这个阈值,那么就将其强制限制在这个范围之内,以此防止梯度爆炸;

  4. 采用权重正则化:正则化主要是通过对网络权重做正则来限制过拟合,但是根据正则项在损失函数中的形式可以看出,如果发生梯度爆炸,那么权值的范数(正则项)就会变的非常大,反过来,通过限制正则化项的大小,也可以在一定程度上限制梯度爆炸的发生。

7.3  相关面试题

Q:

A:

 

第八章  范数正则化

监督机器学习中训练模型时,需要保证模型“简单”的基础上最小化训练误差,这样得到的参数才具有好的泛化性能(也就是测试误差也小),最小化误差是为了让我们的模型拟合训练数据,而模型“简单”就是通过正则化来实现的,可以防止我们的模型过分拟合训练数据。

8.1  正则化概述

正则化的使用可以约束我们的模型的特性,能将人对这个模型的先验知识融入到模型的学习当中,强行地让学习到的模型具有人想要的特性,例如稀疏、低秩、平滑等等。 一般来说,监督学习可以看做最小化下面的目标函数:

正则化函数 Ω(w) 有很多种选择,一般是模型复杂度的单调递增函数,模型越复杂,正则项值就越大。不同的选择对参数 w 的约束不同,取得的效果也不同,我们在论文中常见的都聚集在:零范数、一范数、二范数、迹范数、Frobenius范数和核范数等等。

8.2  L0范数与L1范数

L0范数和L1范数可以实现参数的稀疏化,L1因具有比L0更好的优化求解特性而被广泛应用。

  • L0范数是指向量中非0的元素的个数。如果我们用L0范数来正则化一个参数矩阵W的话,就是希望W的大部分元素都是0,即是让参数矩阵W是稀疏的。
  • L1范数是指向量中各个元素绝对值之和,也叫“稀疏规则算子”(Lasso regularization)。

Q:为什么L1范数会使权值稀疏?

A:假设有如下带L1正则项的损失函数:

我们在使用梯度下降法求解参数最优解时,就是不断在参数空间中寻找最优点,如果我们在原始损失函数  后添加L1正则化项,相当于对  做了一个约束,此时我们的任务变成在L1约束下寻找参数空间中的最优点,也就是说最优点必须在  等值线与L1图形首次相交的地方。而在参数空间中,两者首次相交的地方往往都在权值参数的很多维度等于0的位置。

下面我们举一个例子来直观说明:我们考虑二维的情况,即只有两个权值w1和w2 ,此时L1=∣w1∣+∣w2∣。我们将求解  的过程画出等值线,同时将L1正则化的函数L1也在w1w2二维平面上画出来。如下图:

图中彩色线是  的等值线,黑色方形是L函数的图形,在  等值线与L1图形首次相交的地方就是模型的最优解。我们可以看到,此时参数的值(w1,w2)=(0,w),也就是有一个维度等于0。那么我们推广到高维空间中,可以直观想象,因为L1函数有很多『突出的角』(二维情况下四个,多维情况下更多), 与这些角接触的机率会远大于与L1其它部位接触的机率,而在这些角上,权值参数的很多维度等于0,这就是为什么L1正则化可以产生稀疏模型,进而可以用于特征选择。

Q:为什么要稀疏?让参数稀疏有什么好处呢?

A:

1)特征选择(Feature Selection)

大家对稀疏规则化趋之若鹜的一个关键原因在于它能实现特征的自动选择。一般来说, 的大部分特征和最终的输出  相关性很低,在最小化目标函数的时候考虑  这些额外的特征,虽然可以获得更小的训练误差,但在预测新的样本时,这些没用的信息反而会被考虑,从而干扰了对正确  的预测。稀疏规则化算子的引入就是为了完成特征自动选择的任务,它会通过学习去掉和输出相关性低的特征(特征对应的权重置0),保留相关性高的特征。

2)可解释性(Interpretability)

另一个青睐于稀疏的理由是,由于我们只选择出少量特征,模型就会变得“简单”,因此我们就能更容易的去分析、解释一个模型。例如说患某种病的概率是y,我们收集到了1000中可能影响患病概率的因素,通过学习我们得到的权重矩阵W里只有很少的非零元素,假设只有5个非零的 ,我们就有理由相信这些对应的特征在患病分析上面提供的信息是巨大的,决策性的。也就是说,患不患这种病只和这5个因素有关,那医生就好分析多了。但如果1000个  都非0,医生面对这1000种因素,便难以分析患病的缘由。

8.3  L2范数

L2范数是向量各元素的平方和然后求平方根。

在损失函数中加入L2正则项,训练时会有选择的让某些与模型输出相关性低的特征权值变得很小,趋近于0。

Q:为什么w越小,模型越简单?

A:可以假设一个线性回归方程,如果某个特征的参数很大,这个特征稍微变动一点点,就会对输出造成很大影响;但如果参数足够小,数据偏移得多一点也不会对结果造成什么影响,也就是说模型的『抗扰动能力强』

因此,拟合过程中通常都倾向于让权值尽可能小,最后构造一个所有参数都比较小的模型,一般认为这样参数值小的模型比较简单,能适应不同的数据集,在一定程度上避免了过拟合现象。

8.4  正则化参数的选择

1)L1正则化参数

通常越大的λ可以让代价函数在参数为0时取到最小值。

2)L2正则化参数

λ越大, 衰减得越快。另一个理解可以参考下图,λ越大,L2圆的半径越小,最后求得代价函数最值时各参数也会变得很小。

8.5  相关面试题

Q:

A:

 

第九章  Batch Normalization

9.1  使用BN的原因

首先我们来回顾一下MBGD的过程:假设训练数据集合T包含 N 个样本,而每个Mini-Batch的Batch Size为 b ,于是整个训练数据可被分成 N/b 个Mini-Batch。在模型通过SGD进行训练时,一般跑完一个Mini-Batch的实例,叫做完成训练的一步(step),跑完N/b步则整个训练数据完成一轮训练,则称为完成一个Epoch。完成一个Epoch训练过程后,对训练数据做随机Shuffle打乱训练数据顺序,重复上述步骤,然后开始下一个Epoch的训练,对模型完整充分的训练由多轮Epoch构成。

由上述过程可以看出,对于Mini-Batch SGD训练方法来说,Mini-Batch内的每个实例需要走一遍当前的网络,产生当前参数下神经网络的预测值,并根据预测值计算损失,然后反向传播更新权重参数。这种时候,通常会出现一个叫Covariance Shift的问题:

  • 在输入层上,如果一批样本的分布与另一批样本的分布显著不同:[0,1] vs [10,100],对于一个浅层模型而言,训练第一批样本时,模型可能在描绘函数A,训练第二批样本时,模型发现自己在描绘函数B,完全不同于A。这样就是推翻自己重复劳动,训练低效。
  • 输入层的这种情况,对于其他层而言,也是一样无法逃避。对于中间某个隐层的某些神经元,它们的输出值可能会远大于同层其他神经元,导致这些神经元的分布与其他神经元大幅偏离,就会出现本层的Covariance Shift的问题,这样子训练就会很低效。

总结:对于神经网络某一层的某些神经元,如果它们的激活值分布与同层其他神经元大幅偏离,就会出现Covariance Shift的问题,导致训练效率低下,而解决方案就是统一每一层激活值的分布。

9.2  什么是BN

规范化(Normalization)是一种对数值的特殊函数变换方法,也就是会在原始数值x外套一层起规范化作用的函数,转换后的数值满足一定的分布特性,即:

因为神经网络里主要有两类实体:神经元或者连接神经元的带权边,所以深度学习中的Normalization可以分为两大类:

  • 对神经元激活值/净激活值进行Normalization操作,如BatchNorm/LayerNorm/InstanceNorm/GroupNorm等;
  • 对神经元带权边进行Normalization操作,如Weight Norm等;

不论哪种Normalization方法,其规范化目标都是一样的,就是将其激活值规整为均值为0,方差为1的正态分布。具体到Batch Normalization,它的整个规范化过程可以分为两步:

1)将激活值规范到均值为0,方差为1的正态分布范围内。

其中, 为某个神经元原始激活值, 为规范后的值,μ是神经元集合S中包含的m个神经元激活值的均值,即:

 为根据均值和集合S中神经元各自激活值求出的激活值标准差:

其中, ε是为了增加训练稳定性而加入的小的常量数据。

2)经过第一步的Normalization操作后,会导致新的分布丧失从前层传递过来的信息,且无法有效利用激活函数的非线性功能;因此,第二步中加入了缩放因子 γ 和平移因子 β,每个神经元在训练过程中会自动学习这两个调节因子,以自行决定是否需要对新分布做一定程度的缩放和平移(如果让γ=σ、β=μ,则其可以取消Normalization)。

这一步的核心思想就是让神经网络自己学习找到一个比较好平衡点,既能享受非线性较强的表达能力,又避免激活值的分布出现Covariance Shift,导致网络收敛速度太慢。

BN的效果:

  1. 可以加快模型收敛速度,不用再依赖精细的参数初始化过程,还可以调大学习率等各种方便;
  2. 用多个样本间计算统计量(均值、方差),引入了随机噪声,能够对模型参数起到正则化的作用,有利于增强模型泛化能力。

BN的缺点:

  1. 如果Batch Size太小,就得不到有效得统计量,也就是说噪音太大,那么BN效果会明显下降;
  2. 对于像素级图片生成任务来说,BN效果不佳;
  3. RNN等动态网络使用BN效果不佳且使用起来不方便;
  4. 训练时和推理时统计量不一致:对于BN来说,采用Mini-Batch内实例来计算统计量,在训练时没有问题,但在推理时由于是单实例的,所以就无法获得BN计算所需的均值和方差。一般解决方法是采用训练时刻记录的各个Mini-Batch的统计量的数学期望,以此来推算全局的均值和方差,在线推理时采用这样推导出的统计量。虽说实际使用并没大问题,但是确实存在训练和推理时刻统计量计算方法不一致的问题。

9.3  BN具体是怎么做的

目前各类Normalizaiton方法大同小异,最主要的区别在于神经元集合S的范围怎么定,不同的方法采用了不同的神经元集合定义方法(用于计算均值和方差)。

9.3.1  MLP中的BN

假设在训练时某个batch包含n个样本,对于前向神经网络来说,这n个样本分别通过同一个神经元k的时候会产生n个激活值,使用BN时就是对这n个同一个神经元被不同样本激发的激活值进行规范化。

9.3.2  CNN中的BN

对于CNN中某个卷积层对应输出特征图的第k个通道来说,假设某个Batch包含n个样本,那么每个样本在这个通道k都会产生一个二维激活平面,也就是说Batch中n个样本分别通过同一个卷积核的输出通道k的时候产生了n个激活平面。假设激活平面为 ,那么n个样本总共包含  个激活值,使用BN就是对这  个激活值进行规范化。

 

9.4  其他Normalization方法

BN要求计算统计量的时候必须在同一个Mini-Batch内的实例之间进行统计,因此形成了Batch内实例之间的相互依赖和影响的关系。如何从根本上解决这些问题?一个自然的想法是:把对Batch的依赖去掉,转换统计集合范围。在统计均值方差的时候,不依赖Batch内数据,只用当前处理的单个训练数据来获得均值方差的统计量,这样因为不再依赖Batch内其它训练数据,那么就不存在因为Batch约束导致的问题。在BN后的几乎所有改进模型都是在这个指导思想下进行的。

9.4.1  Layer Normalization

为了能够在只有当前一个训练实例的情形下,也能找到一个合理的统计范围,一个最直接的想法是:MLP的同一隐层自己包含了若干神经元;同理,CNN中同一个卷积层包含k个输出通道,每个通道包含m*n个神经元,整个通道包含了k*m*n个神经元;类似的,RNN的每个时间步的隐层也包含了若干神经元。那么我们完全可以直接用同层隐层神经元的响应值作为集合S的范围来求均值和方差,这就是Layer Normalization的基本思想。下图分示了MLP、CNN和RNN的Layer Normalization的集合S计算范围,因为很直观,所以这里不展开详述。

但Layer Normalization目前看好像也只适合应用在RNN场景下,在CNN等环境下效果是不如BatchNorm或者GroupNorm等模型的。

9.4.2  Instance Normalization

一个样本在经过某个卷积层后得到了  的输出特征图,Instance Normalization就是对其中的每个通道k上  个激活值都单独进行规范化。也正是因此,这种方法只能在CNN中使用。

Instance Normalization对于一些图片生成类的任务比如图片风格转换来说效果是明显优于BN的,但在很多其它图像类任务比如分类等场景效果不如BN。

9.4.3  Group Normalization

从上面的Layer Normalization和Instance Normalization可以看出,这是两种极端情况,Layer Normalization是将同层所有神经元作为统计范围,而Instance Normalization则是CNN中将同一卷积层中每个卷积核对应的输出通道单独作为自己的统计范围。那么,有没有介于两者之间的统计范围呢?

通道分组是CNN常用的模型优化技巧,所以自然而然会想到对CNN中某一层卷积层的输出或者输入通道进行分组,在分组范围内进行统计,这就是Group Normalization的核心思想。

Group Normalization在要求Batch Size比较小的场景下或者物体检测/视频分类等应用场景下效果是优于BN的。

9.5  相关面试题

Q:

A:

 

第十章  Dropout

10.1  Dropout简介

dropout是指在深度学习网络的训练过程中,对于神经网络单元,按照一定的概率将其暂时从网络中丢弃。因此每一次都是在训练一个不同的网络,消除减弱了神经元节点间的联合适应性,增强了泛化能力,所以对过拟合有抑制作用。

10.2  模型变化

为了达到ensemble的特性,有了dropout后,神经网络的训练和预测就会发生一些变化。

10.2.1  训练层面

无可避免的,训练网络的每个单元要添加一道概率流程。

对应的公式变化如下如下:

  • 没有dropout的神经网络

  • 有dropout的神经网络

10.2.2  预测层面

预测的时候,不需要舍弃神经元。

其他Drop技术:

  1. Dropout:完全随机扔

  2. SpatialDropout:按channel随机扔

  3. Stochastic Depth:按res block随机扔

  4. DropBlock:每个feature map上按spatial块(n*n的方块)随机扔

  5. Cutout:在训练时把输入图像按spatial块随机扔

  6. DropConnect:将与神经元相连的输入权值以一定概率置0

10.3  相关面试题

Q:

A:

 

第十一章  注意力机制

概念:注意力机制是用来模拟人类对环境的生理感知机制而提出的,它是一种方法论,没有严格的数学定义。比如,传统的局部图像特征提取、显著性检测、滑动窗口方法等都可以看作一种注意力机制。在神经网络中,注意力机制通常就是一个额外的神经网络模块,能够硬性选择输入的某些部分,或者柔性地给输入的不同部分分配不通的权值。

作用:

  1. 结构化的选取输入的子集,从而降低数据的维度,减少计算负担。
  2. 注意力机制能够帮助模型选择更好的中间特征,从而提高输出的质量。

11.1  注意力机制分类

注意力机制可以分为四类:

  • 基于输入项的柔性注意力(Item-wise Soft Attention)
  • 基于输入项的硬性注意力(Item-wise Hard Attention)
  • 基于位置的柔性注意力(Location-wise Soft Attention)
  • 基于位置的硬性注意力(Location-wise Hard Attention)

11.1.1  基于项的注意力机制

1)输入

对于基于项的注意力和基于位置的注意力,它们的输入形式是不同的。

  • 基于项的注意力的输入需要是包含明确项的序列,或者需要额外的预处理步骤来生成包含明确项的序列(项可以是一个向量、矩阵,甚至一个特征图);
  • 基于位置的注意力则是针对输入为一个单独的特征图设计的,所有的目标可以通过位置指定。

2)输出

基于项的注意力在项的层面操作。原始输入经过神经网络处理后(如RNN或CNN),形成了一个每一项具有一个单独编码的序列。

  • 基于项的柔性注意力为每一项计算一个权重,然后对所有项进行线性加权合并。合并后的编码就是注意力机制操作后的特征,用于做预测;
  • 基于项的硬性注意力的不同在于它会做出硬性的选择,而不是线性加权。具体就是根据注意力的权重随机地选取若干(通常是一个)编码作为最终的特征。

11.1.2  基于位置的注意力机制

基于位置的注意力直接在一个单独的特征图上进行操作。

  • 基于位置的硬性注意力从输入的特征图中离散地选取一个子区域,作为最终的特征,选取的位置是由注意力模块计算出来的;
  • 基于位置的柔性注意力则对整个特征图做一个变换,使得感兴趣的部分能够突出出来(加权)。

11.2  注意力模块

注意力机制通常由一个连接在原神经网络之后的额外的神经网络实现,整个模型仍然是端对端的,因此注意力模块能够和原模型一起同步训练。对于柔性注意力,注意力模块对其输入是可微的,所以整个模型仍可用梯度方法来优化。而硬性注意力机制要做出硬性的决定,离散地选择其输入的一部分,这样整个系统对于输入不再是可微的。所以强化学习中的一些技术被用来优化包含硬性注意力的模型(强化学习的机制是通过收益函数来激励)。

下面我们通过几个例子直观了解注意力模块在神经网络中的应用:

1)Squeeze-and-Excitation Networks

SENet中提出显示的建模特征通道之间的相互依赖关系,这其实就是通道维度的一种注意力机制,体来说,就是通过学习的方式来自动获取到每个特征通道的重要程度,然后依照这个重要程度去提升有用的特征并抑制对当前任务用处不大的特征。

通过上图我们可以看到,SENet就是将某一层特征图作一次Squeeze操作,通过对各个通道进行全局平均池化,将一个channel上整个空间的特征编码为一个全局特征;随后为了抓取各个通道之间的关系,采用两个全连接层进行非线性关系学习,其中,第一个全连接层用来降维,第二个全连接层恢复维度,并采用Sigmoid将输出的Channel Attention Featuremap的值限定在0-1之间,作为各个通道的注意力权重;最后,通过将权重和原始特征图的各个通道进行相乘,获得包含了通道重要性信息的新特征图。

2)CBAM: Convolutional Block Attention Module 

CBAM是一种结合了空间(spatial)和通道(channel)的注意力机制模块,相比于senet只关注通道的注意力机制可以取得更好的效果。其具体模块示意图如下:

其中主要包括两个模块:Channel Attention Module 和 Spatial Attention Module,下面分别来介绍一下。

Channel Attention Module

CAM其实和SENet中的通道注意力模块类似,CBAM将输入的featuremap,分别经过基于特征平面的global max pooling 和global average pooling;然后分别连接MLP,将MLP输出的两个对应特征进行elementwise加和操作,再经过sigmoid激活操作,生成最终的channel attention featuremap;最后,将该channel attention featuremap和input featuremap做elementwise乘法操作,生成Spatial attention模块需要的输入特征图。

Spatial Attention Module

将Channel Attention Module 输出的特征图作为本模块的输入特征图。首先做一个基于通道的global max pooling 和global average pooling,然后将这2个结果基于 channel 做concat操作;随后经过一个卷积操作,降维为单个channel,再经过sigmoid生成激活值在0-1之间的Spatial Attention Feature;最后将该feature和该模块的输入feature做乘法,得到最终生成的特征。

11.3  相关面试题

Q:

A:

 

参考:

  1. https://www.zhihu/question/53405779

  2. https://zhuanlan.zhihu/p/61880018

  3. https://www.jianshu/p/ac46cb7e6f87

  4. https://zhuanlan.zhihu/p/28749411

  5. https://zhuanlan.zhihu/p/28492837

  6. https://zhuanlan.zhihu/p/22142013

  7. https://blog.csdn/u014380165/article/details/76946358

  8. https://blog.csdn/qq_14845119/article/details/80787753?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-2&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-2

  9. https://blog.csdn/u010099080/article/details/78177781

  10. https://wwwblogs/tianqizhi/p/9713951.html

  11. https://zhuanlan.zhihu/p/45190898

  12. https://blog.csdn/zouxy09/article/details/24971995

  13. https://blog.csdn/jinping_shi/article/details/52433975

  14. https://zhuanlan.zhihu/p/43200897

  15. https://blog.csdn/stdcoutzyx/article/details/49022443

  16. https://www.zhihu/question/32673260/answer/71137399

  17. https://www.zhihu/question/61607442/answer/440401209

  18. https://zhuanlan.zhihu/p/56501461

更多推荐

深度学习简明教程系列 —— 基础知识(合集)