【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等

阅读之前看这里????:博主是一名正在学习数据类知识的学生,在每个领域我们都应当是学生的心态,也不应该拥有身份标签来限制自己学习的范围,所以博客记录的是在学习过程中一些总结,也希望和大家一起进步,在记录之时,未免存在很多疏漏和不全,如有问题,还请私聊博主指正。
博客地址:天阑之蓝的博客,学习过程中不免有困难和迷茫,希望大家都能在这学习的过程中肯定自己,超越自己,最终创造自己。

问题的提出

在深度学习的过程中,我们可能出现两种问题,一个问题是模型在训练集上表现不好,另一种问题是模型在测试集上表现不好(过拟合)。

针对这些问题,有什么可以优化的方法呢?

一、模型在测试集上表现不好的优化方法

1.**函数的选择

神经网络的**函数其实是将线性转化为非线性的一个函数,在深度学习中常用的**函数有sigmoid function

1.1 什么是Sigmoid function

一提起Sigmoid function可能大家的第一反应就是Logistic Regression。我们把一个sample扔进 s i g m o i d sigmoid sigmoid中,就可以输出一个probability,也就是是这个sample属于第一类或第二类的概率。 还有像神经网络也有用到 s i g m o i d sigmoid sigmoid,不过在那里叫activation function。Sigmoid function长下面这个样子:
σ ( z ) = 1 1 + e − z \sigma(z)=\frac{1}{1+e^{-z}} σ(z)=1+ez1
其实这个function我们只知道怎么用它,但是不知道它是怎么来的,以及底层的含义是什么。

首先假设我们有两个class:C1C2,并且给出一个sample x x x,我们的目标是求 x x x属于C1的概率是多少。这个概率我们可以通过Naive Bayes很轻松的得出,也就是(公式1):

【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等
其中等号右面的分布这项(公式2):

【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等
x x x出现的概率等于C1出现的概率乘以C1中出现 x x x的概率加上C2出现的概率乘以 C2 中出现 x x x的概率。 那么就可以把公式2带入公式1的分母中(公式3):

【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等
下面我们将等式两边同时除以分子就变成了(公式4):

【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等
【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等
也就是Sigmoid function

思考:
上面已经知道 sigmoid函数是从什么东西推导过来的了,那么有个问题就是,既然上面式子中只有 P ( x ∣ C 1 ) P(x|C_1) P(xC1) P ( x ∣ C 2 ) P(x|C_2) P(xC2)我们不知道,那我们干脆用Bayes不就能直接计算出 P ( x ∣ C 1 ) P(x|C_1) P(xC1)了嘛? ( x x x是某个sample,其中有多个feature,也就是说x是一个vector)

【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等
但是Bayes有一个限制条件就是所有的feature都必须是independent的,假如我们训练的sample中各个feature都是independent的话,那么Bayes会给我们一个很好的结果。但实际情况下这是不太可能的,各个feature之间不可能是independent的,那么bias就会非常大,搞出的model就很烂。

1.2 这个 z z z应该长什么样子

我们将 z z z变换一下可以变换成下面的样子:

【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等
【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等
【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等
【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等
【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等

1.3 Sigmoid函数的好处

sigmoid函数也叫Logistic函数,用于隐层神经元输出,取值范围为(0,1),它可以将一个实数映射到(0,1)的区间,可以用来做二分类。在特征相差比较复杂或是相差不是特别大时效果比较好。主要优点是平滑、易于求导。
【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等
sigmoid函数的导数是可以直接由自己来表示的,这在神经网络的反向传播的求导中起了大用途:
【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等

1.4 Sigmod函数的缺点(梯度消失和梯度爆炸的问题)

缺点:**函数计算量大,反向传播求误差梯度时,求导涉及除法;反向传播时,很容易就会出现梯度消失的情况,从而无法完成深层网络的训练。
对于梯度消失的问题:李宏毅老师视频中有这样两张PPT:
【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等
简单解释一下这上面的意思:
因为Sigmod函数的特性,在输入很大的情况,输出却变得很小,就算是增大输入,通过sigmoid函数得梯度也会变得很小,所以会造成学习速率很慢,也就是第一张图中的learn very slow。但是在靠近输出的地方,却学习很快。会造成一个现象就是:
当输入为random的时候,输出的地方已经根据这个random找到了一个局部最优值。

举个例子,对于一个含有三层隐藏层的简单神经网络来说,当梯度消失发生时,接近于输出层的隐藏层由于其梯度相对正常,所以权值更新时也就相对正常,但是当越靠近输入层时,由于梯度消失现象,会导致靠近输入层的隐藏层权值更新缓慢或者更新停滞。这就导致在训练时,只等价于后面几层的浅层网络的学习。

原因:当我们对Sigmoid函数求导时,得到其结果如下:

【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等
由此可以得到它Sigmoid函数图像,呈现一个驼峰状(很像高斯函数),从求导结果可以看出,Sigmoid导数的取值范围在0~0.25之间,而我们初始化的网络权值 ∣ w ∣ |w| w通常都小于1,因此,当层数增多时,小于0的值不断相乘,最后就导致梯度消失的情况出现。同理,梯度爆炸的问题也就很明显了,就是当权值过大时,导致 ,最后大于1的值不断相乘,就会产生梯度爆炸
【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等

从深层网络角度来讲,不同的层学习的速度差异很大,表现为网络中靠近输出的层学习的情况很好,靠近输入的层学习的很慢,有时甚至训练了很久,前几层的权值和刚开始随机初始化的值差不多。因此,梯度消失、爆炸,其根本原因在于反向传播训练法则,属于先天不足。如下图所示,对于四个隐层的网络来说,第四隐藏层比第一隐藏层的更新速度慢了两个数量级:

【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等

其它更多详细的内容可以看博客:https://blog.****.net/qq_30815237/article/details/89453315

2.解决梯度消失和爆炸的方法

2.1 Relu函数

梯度爆炸的发生可能是因为**函数,如之前很流行的 Sigmoid 和 Tanh 函数。使用 ReLU **函数可以减少梯度爆炸。采用 ReLU **函数是最适合隐藏层的,是目前使用最多的**函数。
【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等
relu函数的导数在正数部分是恒等于1的,因此在深层网络中使用relu**函数就不会导致梯度消失和爆炸的问题。

relu的主要贡献在于:

  • 解决了梯度消失、爆炸的问题
  • 计算方便,计算速度快, 加速了网络的训练

同时也存在一些缺点:

  • 由于负数部分恒为0,会导致一些神经元无法**(可通过设置小学习率部分解决)
  • 输出不是以0为中心的

2.2 relu函数为分段线性函数,为什么会增加非线性元素

我们知道**函数的作用就是为了为神经网络增加非线性因素,使其可以拟合任意的函数。那么relu在大于的时候就是线性函数,如果我们的输出值一直是在大于0的状态下,怎么可以拟合非线性函数呢?

relu是非线性**函数
疑问在于,为什么relu这种“看似线性”(分段线性)的**函数所形成的网络,居然能够增加非线性的表达能力。
1、首先什么是线性的网络,如果把线性网络看成一个大的矩阵M。那么输入样本A和B,则会经过同样的线性变换MA,MB(这里A和B经历的线性变换矩阵M是一样的)。
2、的确对于单一的样本A,经过由relu**函数所构成神经网络,其过程确实可以等价是经过了一个线性变换M1,但是对于样本B,在经过同样的网络时,由于每个神经元是否**(0或者Wx+b)与样本A经过时情形不同了(不同样本),因此B所经历的线性变换M2并不等于M1。因此,relu构成的神经网络虽然对每个样本都是线性变换,但是不同样本之间经历的线性变换M并不一样,所以整个样本空间在经过relu构成的网络时其实是经历了非线性变换的。
3、还有一种解释就是,不同样本的同一个feature,在通过relu构成的神经网络时,流经的路径不一样(relu**值为0,则堵塞;**值为本身,则通过),因此最终的输出空间其实是输入空间的非线性变换得来的。
4、更极端的,不管是tanh还是sigmoid,你都可以把它们近似看成是分段线性的函数(很多段),但依然能够有非线性表达能力;relu虽然只有两段,但同样也是非线性**函数,道理与之是一样的。
5、relu的优势在于运算简单,网络学习速度快

二、模型在测试集上表现不好的优化方法

1.Adagrad

【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等
通过上式 ,我们可以看到学习率在不断变小, 且受每次计算出来的梯度影响 ,对于梯度比较大的参数,它的学习率就会变得相对更小,里面的根号特别重要,没有这个根号算法表现非常差,自适应学习率的缺点就是在某些情况下一直递减的学习率并不好这样会造成学习过早停止。

2. 动量方法(Momentum)

通常情况我们在训练深度神经网络的时候把数据拆解成一小批一小批地进行训练,这就是我们常用的mini-batch SGD训练算法,然而虽然这种算法能够带来很好的训练速度,但是在到达最优点的时候并不能够总是真正到达最优点,而是在最优点附近徘徊。另一个缺点就是这种算法需要我们挑选一个合适的学习率,当我们采用小的学习率的时候,会导致网络在训练的时候收敛太慢;当我们采用大的学习率的时候,会导致在训练过程中优化的幅度跳过函数的范围,也就是可能跳过最优点。我们所希望的仅仅是网络在优化的时候网络的损失函数有一个很好的收敛速度同时又不至于摆动幅度太大

【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等
动量的引入就是为了加快学习过程,特别是对于高曲率、小但一致的梯度,或者噪声比较大的梯度能够很好的加快学习过程。动量的主要思想是积累了之前梯度指数级衰减的移动平均(前面的指数加权平均),下面用一个图来对比下,SGD和动量的区别:
【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等
区别: SGD每次都会在当前位置上沿着负梯度方向更新(下降,沿着正梯度则为上升),并不考虑之前的方向梯度大小等等。而动量(moment)通过引入一个新的变量 v v v积累之前的梯度(通过指数衰减平均得到),得到加速学习过程的目的。
【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等

最直观的理解就是,若当前的梯度方向与累积的历史梯度方向一致,则当前的梯度会被加强,从而这一步下降的幅度更大。若当前的梯度方向与累积的梯度方向不一致,则会减弱当前下降的梯度幅度。

所以Momentum优化器刚好可以解决我们所面临的问题,它主要是基于梯度的移动指数加权平均。假设在当前的迭代步骤第 t 步中,那么基于Momentum优化算法可以写成下面的公式:
【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等
β \beta β的值越大,则之前的梯度对现在的方向影响越大。 β \beta β一般取值为0.5, 0.9, 0.99。ng推荐取值0.9。

3. RMSProp方法

RMSProp算法的全称叫 Root Mean Square Prop,是Geoffrey E. Hinton在Coursera课程中提出的一种优化算法,在上面的Momentum优化算法中,虽然初步解决了优化中摆动幅度大的问题。所谓的摆动幅度就是在优化中经过更新之后参数的变化范围,如下图所示,蓝色的为Momentum优化算法所走的路线,绿色的为RMSProp优化算法所走的路线。
【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等

为了进一步优化损失函数在更新中存在摆动幅度过大的问题,并且进一步加快函数的收敛速度,RMSProp算法对权重 W 和偏置 b 的梯度使用了微分平方加权平均数。

其中,假设在第 t 轮迭代过程中,各个公式如下所示
【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等
算法的主要思想就用上面的公式表达完毕了。在上面的公式中 s d w s_{dw} sdw s d b s_{db} sdb分别是损失函数在前 t − 1 t−1 t1轮迭代过程中累积的梯度梯度动量,β 是梯度累积的一个指数。所不同的是,RMSProp算法对梯度计算了微分平方加权平均数。这种做法有利于消除了摆动幅度大的方向,用来修正摆动幅度,使得各个维度的摆动幅度都较小。另一方面也使得网络函数收敛更快。(比如当 d W dW dW或者 d b db db中有一个值比较大的时候,那么我们在更新权重或者偏置的时候除以它之前累积的梯度的平方根,这样就可以使得更新幅度变小)。为了防止分母为零,使用了一个很小的数值 ϵ 来进行平滑,一般取值为 1 0 − 8 10^{−8} 108

显然,Momentum 和 RMSprop是存在区别的。前者是在梯度的更新方向上做优化,没有考虑数值大小;后者在数值大小上进行优化,在梯度值较大的方向进行适当的减小步伐,在梯度值较小的方向适当增大步伐,没有考虑方向。个人认为,两者在长期的优化效果上基本上是一致的,即减小了个别方向上的震动幅度,加快了收敛速度。

4.Adam方法

【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等
Adam(Adaptive Moment Estimation)本质上是带有动量项的RMSprop,它利用梯度的一阶矩估计和二阶矩估计动态调整每个参数的学习率。Adam的优点主要在于经过偏置校正后,每一次迭代学习率都有个确定范围,使得参数比较平稳。

4.Early Stopping方法

当我们训练深度学习神经网络的时候通常希望能获得最好的泛化性能(generalization performance,即可以很好地拟合数据)。但是所有的标准深度学习神经网络结构如全连接多层感知机都很容易过拟合:当网络在训练集上表现越来越好,错误率越来越低的时候,实际上在某一刻,它在测试集的表现已经开始变差。
【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等

解决过拟合问题有两个方向:降低参数空间的维度或者降低每个维度上的有效规模(effective size)。降低参数数量的方法包括greedy constructive learning、剪枝和权重共享等。降低每个参数维度的有效规模的方法主要是正则化,如权重衰变(weight decay)和早停法(early stopping)等。

早停法是一种被广泛使用的方法,在很多案例上都比正则化的方法要好。上图使用早停法出现的一个结果。其基本含义是在训练中计算模型在验证集上的表现,当模型在验证集上的表现开始下降的时候,停止训练,这样就能避免继续训练导致过拟合的问题。其主要步骤如下:

  1. 将原始的训练数据集划分成训练集和验证集
  2. 只在训练集上进行训练,并每个一个周期计算模型在验证集上的误差,例如,每15次epoch(mini batch训练中的一个周期)
  3. 当模型在验证集上的误差比上一次训练结果差的时候停止训练
  4. 使用上一次迭代结果中的参数作为模型的最终参数

Keras现在已经有自带早停法的使用,可以查看官网文档说明。

5. Dropout方法

dropout是指在深度学习网络的训练过程中,对于神经网络单元,按照一定的概率将其暂时从网络中丢弃。注意是暂时,对于随机梯度下降来说,由于是随机丢弃,故而每一个mini-batch都在训练不同的网络。

dropout是CNN中防止过拟合提高效果的一个大杀器,但对于其为何有效,却众说纷纭。

大规模的神经网络有两个缺点:

  • 费时
  • 容易过拟合

这两个缺点真是抱在深度学习大腿上的两个大包袱,一左一右,相得益彰,额不,臭气相投。过拟合是很多机器学习的通病,过拟合了,得到的模型基本就废了。而为了解决过拟合问题,一般会采用ensemble方法,即训练多个模型做组合,此时,费时就成为一个大问题,不仅训练起来费时,测试起来多个模型也很费时。总之,几乎形成了一个死锁。

Dropout的出现很好的可以解决这个问题,每次做完dropout,相当于从原始的网络中找到一个更瘦的网络,如下图所示:
【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等

因而,对于一个有N个节点的神经网络,有了dropout后,就可以看做是 2 n 2^n 2n个模型的集合了,但此时要训练的参数数目却是不变的,这就解脱了费时的问题。

dropout为什么可以防止过拟合?

我们知道“随机森林”是一种不容易发生过拟合的算法,其采用的方法是“bagging”,即通过对多个树的输出结果加权平均,得出最后的结果。而每棵树都是在不同的训练集上、设置不同的参数得到的,因此是一种典型的通过多个不同参数,甚至不同类型的模型来降低方差的一种方法。这种方法对传统的机器学习算法、或者小型的NN模型可行,但是当数据量很大、模型很复杂的时候,我们不能训练多个不同的模型出来做”bagging”,因为深度神经网络的训练是一个很耗时的过程,需要大量的计算资源和时间。

dropout则为这种思想提供了一种“廉价”的解决方案,因为每一次迭代的过程中,我们会随机dropout掉一些神经元(至于在那一层做dropout,需要看不通的情况),如果设置的dropout的值为0.5,则表示每个神经元有50%的概率被留下来,50%的概率被”抹去“。这就相当于我们从原来的神经网络中随机采样了50%的节点,组成了一个新的神经网络,这个是原来的神经网络的一个子网络,但是规模要比原来的神经网络小很多,并且训练代价也比较小, 这个新的子网络就相当于是”随即森林“中的一个子树(sub-tree)了。我们多次迭代优化,每次迭代优化都会做这样的”随机采样“,从原来的网络中构造一个子网络(sub-network),而每次构造的网络也都不尽相同,这就使得学习到的sub-network在结果上差异性,最后再对这些每个迭代学习到的不同的sub-network做一个”bagging“来得到最终的输出结果。
【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等

6. 正则化方法

见博主另一篇博客:【机器学习】总结之-----主要的常见面试题整理(一)

参考:
1.深度学习优化算法解析(Momentum, RMSProp, Adam)
2.深度学习—深度学习笔记(四):优化方法总结(BGD,SGD,Momentum,AdaGrad,RMSProp,Adam)
3.https://www.zhihu.com/question/268251096/answer/337817494
4.https://blog.****.net/u012328159/article/details/80311892
5.李宏毅《机器学习》视频和PPT
6.https://blog.****.net/u012762419/article/details/79534085

—————————————————————————————————————————————————
博主码字不易,大家关注点个赞转发再走呗 ,您的三连是激发我创作的源动力^ - ^
【深度学习】—模型优化的各种方法(Relu、RMSProp、Dropout)等