-
2020-06-15 17:46:19更多相关内容
-
深度学习基础3——过拟合欠拟合、梯度消失与梯度爆炸、常见循环神经网络
2021-01-20 11:53:54解决过拟合欠拟合的方法(1)权重缩减(2)丢弃法二、梯度消失与梯度爆炸1.消失与爆炸2.随机初始化3.影响模型效果的其他因素三、循环神经网络进阶1.门控循环神经网络/门控循环单元(GRU)2.LSTM:长短期记忆3.深度循环... -
梯度消失与爆炸
2021-01-20 11:34:11梯度消失问题的解决方法 梯度消失问题 Sigmoid函数 梯度范围可能变得越来越小 在反向传播超过5层后,梯度可能会消失 激活函数 ReLU函数(rectified linear unit) 导数: ReLU可被近似为softplut函数 x增加时... -
过拟合、欠拟合、梯度消失及梯度爆炸的理解
2021-01-20 11:42:143, 梯度消失和爆炸的定义 4,梯度消失和爆炸的解决方法 1,过拟合和欠拟合的定义 无论在机器学习还是深度学习建模当中都可能会遇到两种最常见结果,一种叫过拟合(over-fitting )另外一种叫欠拟合(under-... -
深度学习(三)————过拟合、欠拟合及其解决方案;梯度消失、梯度爆炸;循环神经网络进阶
2021-01-20 11:49:19梯度消失及梯度爆炸 循环神经网络进阶 GRU LSTM 深度神经网络 过拟合、欠拟合及其解决方案 训练误差和泛化误差 在解释上述现象之前,我们需要区分训练误差(training error)和泛化误差(generalization error)。... -
L8梯度消失、梯度爆炸.ipynb
2020-02-14 15:52:062020 年参加伯禹教育pytorch培训资料-L8梯度消失、梯度爆炸 jupyter notebook源文件 介绍梯度消失和梯度爆炸的基本概念 介绍影响模型效果的其他因素影响:协变量偏移,标签偏移,概念偏移 介绍Kaggle房价预测的... -
《动手学深度学习PyTorch版》打卡_Task3,过拟合,欠拟合,梯度消失,梯度爆炸
2021-01-20 11:53:17最近参加了伯禹平台和Datawhale等举办的《动手学深度学习PyTorch版》课程,对过拟合,欠拟合,梯度消失,梯度爆炸做下笔记。 过拟合和欠拟合 模型无法得到较低的训练误差,我们将这一现象称作欠拟合(underfitting)... -
梯度消失,梯度爆炸.md
2020-02-13 18:44:48梯度消失、梯度爆炸以及Kaggle房价预测 梯度消失和梯度爆炸 考虑到环境因素的其他问题 Kaggle房价预测 -
过拟合欠拟合及其解决方案、梯度消失梯度爆炸、循环神经网络进阶
2021-01-06 20:03:47一、过拟合欠拟合及其解决方案 ...二、梯度消失梯度爆炸 深度模型有关数值稳定性的典型问题是消失(vanishing)和爆炸(explosion)。 当神经网络的层数较多时,模型的数值稳定性容易变差。 假设一个层数为的多层感知 -
pytorch_task3过拟合欠拟合;梯度消失爆炸;循环神经网络
2021-01-07 02:35:27Task3过拟合、欠拟合及其解决方案训练误差、泛化误差模型选择验证数据集K折交叉验证过拟合欠拟合概念模型复杂度解决过拟合权重衰减(加上L2范数惩罚项)丢弃法梯度消失、梯度爆炸初始化模型参数Xavier随机初始化协... -
梯度消失与梯度爆炸
2021-01-06 18:05:03什么是梯度消失与梯度爆炸 层数比较多的神经网络模型在使用梯度下降法对误差进行反向传播时会出现梯度消失和梯度爆炸问题。梯度消失问题和梯度爆炸问题一般会随着网络层数的增加变得越来越明显。 例如,对于图所示... -
过拟合,欠拟合,梯度消失,梯度爆炸
2021-01-06 20:17:52过拟合和欠拟合 我们将探究模型训练中经常出现的两类典型问题: 一类是模型无法得到较低的训练误差,我们将这一现象称作欠拟合(underfitting); 另一类是模型的训练误差远小于它在测试数据集上的误差,我们称该... -
Task03:过拟合、欠拟合及梯度爆炸与梯度消失
2021-01-06 14:43:52K折交叉验证 由于验证数据集不参与模型训练,当训练数据不够用时,预留大量的验证数据显得太奢侈。一种改善的方法是K折交叉验证(K-fold cross-validation)。在K折交叉验证中,我们把原始训练数据集分割成K个不重合... -
梯度消失、梯度爆炸笔记
2021-01-20 11:23:25梯度消失和梯度爆炸 深度模型有关数值稳定性的典型问题是消失(vanishing)和爆炸(explosion)。 当神经网络的层数较多时,模型的数值稳定性容易变差。 假设一个层数为L的多层感知机的第层的权重参数为,输出层的... -
梯度消失和梯度爆炸_梯度消失、爆炸的原因及解决办法
2020-12-17 23:08:55一、引入:梯度更新规则目前优化神经网络的方法都是基于反向传播的思想,即根据损失函数计算的误差通过梯度反向传播的方式,更新优化深度网络的权值。这样做是有一定原因的,首先,...二、梯度消失、爆炸的原因下图...一、引入:梯度更新规则
目前优化神经网络的方法都是基于反向传播的思想,即根据损失函数计算的误差通过梯度反向传播的方式,更新优化深度网络的权值。这样做是有一定原因的,首先,深层网络由许多非线性层堆叠而来,每一层非线性层都可以视为是一个非线性函数 f(x),因此整个深度网络可以视为是一个复合的非线性多元函数:
我们最终的目的是希望这个多元函数可以很好的完成输入到输出之间的映射。
二、梯度消失、爆炸的原因
下图以三个隐层的单神经元网络为例:
假设每一层网络激活后的输出为,其中 i 为第 i 层,x 代表第 i 层的输入,也就是第 i−1 层的输出,f 是激活函数,那么,可得出
,暂时忽略常数 b,简记为
。BP算法基于梯度下降策略如下:
由上图可知,上式主要由两部分构成:多个激活函数偏导数的连乘,和多个权重参数的连乘。如果激活函数求导后与权重相乘的积大于1,那么随着层数增多,求出的梯度更新信息将以指数形式增加,即发生梯度爆炸;如果此部分小于1,那么随着层数增多,求出的梯度更新信息将会以指数形式衰减,即发生梯度消失。
【注意】具体激活函数的导数情况可自行验证,比如sigmoid,tanh,Relu,leaky-Relu等。
三、解决方法
在讨论解决方法之前,我们探讨一下其解决思想,其实就是抑制上述式子连乘后结果远远大于1或小于1,主要取决于激活函数偏导数和权值大小。
3.1 预训练加微调
此方法来自Hinton在2006年发表的一篇论文,其基本思想是每次训练一层隐节点,训练时将上一层隐节点的输出作为输入,而本层隐节点的输出作为下一层隐节点的输入,此过程就是逐层“预训练”(pre-training),得到暂时的最优权重值;在预训练完成后,再利用BP算法对整个网络进行训练,对整个网络进行“微调”(fine-tunning)。此思想相当于是先寻找局部最优,然后整合起来寻找全局最优,此方法有一定的好处,但是目前应用不是很多。
3.2 梯度剪切、正则
梯度剪切主要是针对梯度爆炸提出的,其思想是设置一个梯度剪切阈值,更新梯度时,如果梯度超过这个阈值,那么就将其强制限制在这个范围之内,防止梯度爆炸。另一种解决梯度爆炸的手段是权重正则化(weithts regularization),常见的是
正则,和
正则。
3.3 合理的激活函数+权值初始化
Relu激活函数:思想是,如果激活函数的导数为1,那么就消除了激活函数偏导数的影响,只需考虑权值即可。
3.4 Batch Normalization
Batch norm已被广泛应用到各大网络中,具有加速网络收敛速度,提升训练稳定性的效果,Batchnorm本质上是解决反向传播过程中的梯度问题,它是将输出信号 x 规范化,以保证网络的稳定性。
As the data flows through a deep network, the weights and parameters adjust those values, sometimes making the data too big or too small again - a problem the authors refer to as "internal covariate shift". By normalizing the data in each mini-batch, this problem is largely avoided.”Internal Covariate Shift:此术语是google小组在论文 Batch Normalization 中提出来的,其主要描述的是:训练深度网络的时候经常发生训练困难的问题,如上图所示,每一次参数迭代更新后,上一层网络的输出数据经过这一层网络计算后,数据的分布会发生变化,为下一层网络的学习带来困难,此现象称之为Internal Covariate Shift。
为了解决这个问题,Batch Norm就派上用场了,它应用于每层激活函数之前,就是做均值和方差归一化,对于每一批次数据并且还做放大缩小,平移,为了梯度下降的收敛速度更快,相当于把数据都拉到中间的位置了,有这个就不需要Dropout,Relu等等。BN使得每层输出信号满足均值为0,方差为1的分布,而最后的“scale and shift”操作则是为了让因训练所需而“刻意”加入的BN能够有可能还原最初的输入,从而保证整个网络的稳定性。简而言之,BN包括两点:归一化+缩放平移,具体伪代码如下:
为了说明BN如何防止梯度消失,梯度爆炸,进而加快训练速度,举例如下:
1、带有BN的前向传播过程如下所示(其中
为列向量,
为
):
2、则其反向传播有:
3、相应的,连续多层的梯度反向传播过程为:
可以看出,与不使用BN相比,每层的反向传播过程的,增加了一个基于标准差的矩阵
对权重
进行缩放,这样的缩放能够产生什么效果?如果权重
较小,那必然
较小,从而使得其标准差
较小,相对的
较大,所以
相对于原本的
就放大了,避免了梯度的衰减;同样的,如果权重
较大,可以很容易得到
相对于原本的
缩小了,避免了梯度的膨胀。于是,加入了BN的反向传播过程中,就不易出现梯度消失或梯度爆炸,梯度将始终保持在一个合理的范围内。而这样带来的好处就是,基于梯度的训练过程可以更加有效的进行,即加快收敛速度,减轻梯度消失或爆炸导致的无法训练的问题。
最后直观感受一下有无BN的训练过程:
3.5 残差网络结构
3.5.1 残差块
残差网络是由一系列残差块组成的。一个残差块可以用表示为:
残差块分成两部分:直接映射部分和残差部分。
是直接映射,即下图左边灰色部分;
是残差部分,一般由两个或者三个卷积操作构成,即下图右侧包含卷积的部分。
残差块 - Weight:在卷积网络中指卷积操作,
- addition:单位加操作
3.5.2 残差网络的背后原理
残差块一个更通用的表示方式是
是直接映射,
是激活函数,一般使用ReLU。我们首先给出两个假设:
- 假设1:
是直接映射;
- 假设2:
是直接映射。
这时候残差块表示为:
对于一个更深的层
,其与
层的关系可以表示为
【ResNet 解决问题1:网络随着深度的增加,而出现的“degradation problem”】
随着网络层数的增加,网络发生了退化(degradation)的现象:随着网络层数的增多,训练集loss逐渐下降,然后趋于饱和,当再增加网络深度,训练集loss反而会增大。注意这并不是过拟合,因为在过拟合中训练loss是一直减小的。
公式(5)反应了残差网络的两个属性:
-
层 = 任意一个比它浅的
层 + 他们之间的残差部分之和;
- 保证
层不少于浅层
层的特征信息:在前向传输的过程中,随着层数的加深,Feature Map包含的图像信息会逐层减少,而ResNet直接映射的加入,保证了
层网络信息一定不少于
层的图像信息。
【ResNet 解决问题2:梯度消失的问题】
根据BP中使用的导数的链式法则,损失函数
关于
的梯度可以表示为
公式(7)反映了残差网络的两个属性:
- 训练过程中,
不可能一直为
,故解决了梯度消失的问题。
-
表示
层的梯度可以直接传递到任何一个比它浅的
层,不经过中间层的权重矩阵。
通过分析残差网络的正向和反向两个过程,我们发现,当残差块满足上面两个假设时,信息可以非常畅通的在高层和低层之间相互传导。
【参考】
[1]
如何解决梯度消失和梯度爆炸?_黄飞的博客专栏-CSDN博客_梯度消失blog.csdn.net[2]
详解机器学习中的梯度消失、爆炸原因及其解决方法_Double_V的博客-CSDN博客_梯度爆炸的解决方法blog.csdn.net[3]
基础 | batchnorm原理及代码详解blog.csdn.net[4]
深度学习中 Batch Normalization为什么效果好?www.zhihu.com[5]
深入浅出--搞懂卷积神经网络的过拟合、梯度弥散、batchsize的影响的问题(二)_深度学习思考者-CSDN博客_卷积网络batchsizeblog.csdn.net[6]
https://www.quora.com/Why-does-batch-normalization-helpwww.quora.com[7]
基础 | batchnorm原理及代码详解blog.csdn.net[8]
小小将:你必须要知道CNN模型:ResNetzhuanlan.zhihu.com[9]
大师兄:详解残差网络zhuanlan.zhihu.com[10]
https://openaccess.thecvf.com/content_cvpr_2016/papers/He_Deep_Residual_Learning_CVPR_2016_paper.pdfopenaccess.thecvf.com -
RNN的梯度消失和梯度爆炸
2021-01-08 18:55:07文章目录RNN 梯度消失&梯度爆炸1. 深层网络角度解释梯度消失和梯度爆炸2. 激活函数角度解释梯度消失和梯度爆炸3. RNN中的梯度消失和CNN的梯度消失有区别4. 梯度消失、爆炸的解决方案4.1 梯度爆炸的解决方案4.2 ...文章目录
RNN 梯度消失&梯度爆炸
参考:https://zhuanlan.zhihu.com/p/33006526?from_voters_page=true
梯度消失和梯度爆炸本质是同一种情况。梯度消失经常出现的原因:一是使用深层网络;二是采用不合适的损失函数,如Sigmoid。梯度爆炸一般出现的场景:一是深层网络;二是权值初始化太大。
1. 深层网络角度解释梯度消失和梯度爆炸
深层网络由许多非线性层堆叠而来,每一层网络激活后的输出为 f i ( x ) f_{i}(x) fi(x),其中 i i i为第 i i i层, x x x是第 i i i层的输入,即第 i − 1 i-1 i−1层的输出, f f f是激活函数,整个深层网络可视为一个复合的非线性多元函数:
f i + 1 = f ( f i ∗ w i + b ) F ( x ) = f n ( . . . f 3 ( f 2 ( f 1 ( x ) ∗ w 1 + b ) ∗ w 2 + b ) . . . ) f_{i+1} = f(f_{i}*w_{i}+b) \\ F(x)=f_n(...f_3(f_2(f_1(x)*w_{1}+b)*w_{2}+b)...) fi+1=f(fi∗wi+b)F(x)=fn(...f3(f2(f1(x)∗w1+b)∗w2+b)...)
目的是多元函数 F ( x ) F(x) F(x)完成输入到输出的映射,假设不同的输入,输出的最优解是g(x),则优化深层网络就是为了找到合适的权值,满足 L o s s = L ( g ( x ) , F ( x ) ) Loss=L(g(x),F(x)) Loss=L(g(x),F(x))取得极小值。BP 算法基于梯度下降策略,以负梯度方向对参数进行调整,参数更新:
w ← w + Δ w Δ w = − α ∂ L o s s ∂ w Δ w 1 = ∂ L o s s ∂ w 2 = ∂ L o s s ∂ f n ∂ f n ∂ f n − 1 ∂ f n − 1 ∂ f n − 2 . . . ∂ f 3 ∂ f 2 ∂ f 2 ∂ w 2 ∂ f 2 ∂ w 2 = f 1 w\leftarrow w+\Delta{w} \\ \Delta{w} = -\alpha\frac{\partial{Loss}}{\partial{w}} \\ \Delta{w_1} = \frac{\partial Loss}{\partial w_2} = \frac{\partial Loss}{\partial f_n}\frac{\partial f_n}{\partial f_{n-1}}\frac{\partial f_{n-1}}{\partial f_{n-2}}... \frac{\partial f_{3}}{\partial f_{2}} \frac{\partial f_{2}}{\partial w_{2}} \\ \frac{\partial f_{2}}{\partial w_{2}}=f_1 w←w+ΔwΔw=−α∂w∂LossΔw1=∂w2∂Loss=∂fn∂Loss∂fn−1∂fn∂fn−2∂fn−1...∂f2∂f3∂w2∂f2∂w2∂f2=f1
∂ f n ∂ f n − 1 \frac{\partial f_n}{\partial f_{n-1}} ∂fn−1∂fn即对激活函数求导,如果此部分大于1,随着层数增加,梯度更新将以指数形式增加,即发生梯度爆炸;如果此部分小于1,随着层数增加,梯度更新将以指数形式衰减,即发生梯度消失。梯度消失、爆炸,其根本原因在于反向传播训练法则,链式求导次数太多。
2. 激活函数角度解释梯度消失和梯度爆炸
计算权值更新信息,需要计算前层偏导信息,因此激活函数选择不合适,比如Sigmoid,梯度消失会更明显。
S i g m o i d ( x ) = 1 1 + e − x S i g m o i d ′ ( x ) = e − x ( 1 + e − x ) 2 = S i g m o i d ( x ) ( 1 − S i g m o i d ( x ) ) Sigmoid(x) = \frac{1}{1+e^{-x}}\\ Sigmoid'(x) = \frac{e^{-x}}{(1+e^{-x})^2} =Sigmoid(x)(1-Sigmoid(x)) Sigmoid(x)=1+e−x1Sigmoid′(x)=(1+e−x)2e−x=Sigmoid(x)(1−Sigmoid(x))
如果使用sigmoid作为损失函数,其梯度是不可能超过0.25的,这样经过链式求导之后,很容易发生梯度消失。tanh作为损失函数,它的导数图如下,可以看出,tanh比sigmoid要好一些,但是它的导数仍然是小于1的。
t a n h ( x ) = s i n h ( x ) c o s h ( x ) = e x − e − x e x + e − x t a n h ′ ( x ) = 1 − ( e x − e − x ) 2 ( e x + e − x ) 2 = 1 − t a n h 2 ( x ) tanh(x) = \frac{sinh(x)}{cosh(x)}=\frac{e^{x}-e^{-x}}{e^{x}+e^{-x}}\\ tanh'(x) = 1-\frac{(e^{x}-e^{-x})^2}{(e^{x}+e^{-x})^2} = 1-tanh^2(x) tanh(x)=cosh(x)sinh(x)=ex+e−xex−e−xtanh′(x)=1−(ex+e−x)2(ex−e−x)2=1−tanh2(x)
由于sigmoid和tanh存在上述的缺点,因此relu激活函数成为了大多数神经网络的默认选择。relu函数的导数在正数部分是恒等于1,因此在深层网络中就不存在梯度消失/爆炸的问题,每层网络都可以得到相同的更新速度。另外计算方便,计算速度快,加速网络的训练。
但是relu也存在缺点:即在 x x x小于0时,导数为0,导致一些神经元无法激活。输出不是以0为中心的。因此引申出下面的leaky relu函数,但是实际上leaky relu使用的并不多。
R E L U ( x ) = m a x ( 0 , x ) L e a k y R E L U ( x ) = m a x ( 0.01 x , x ) RELU(x)=max(0,x)\\ Leaky RELU(x) =max(0.01x,x) RELU(x)=max(0,x)LeakyRELU(x)=max(0.01x,x)
3. RNN中的梯度消失和CNN的梯度消失有区别
RNN中的梯度消失/爆炸和MLP/CNN中的梯度消失/爆炸含义不同:MLP/CNN中不同的层有不同的参数,各是各的梯度;而 RNN 中同样的权重在各个时间步共享,最终的梯度 g 等于各个时间步的梯度 g t g_t gt 的和。
-
RNN中的总的梯度不会消失。即便梯度越传越弱,那也只是远距离的梯度消失,由于近距离的梯度不会消失,所有梯度之和并不会消失。RNN 所谓梯度消失的真正含义是,梯度被近距离梯度主导,导致模型难以学到远距离的依赖关系。
RNN前向传导过程:
t = 1 s 1 = g ( U x 1 + W s 0 ) o 1 = f ( V g ( U x 1 + W s 0 ) ) t = 2 s 2 = g ( U x 2 + W s 1 ) o 2 = f ( V g ( U x 2 + W s 1 ) ) = f ( V g ( U x 2 + W g ( U x 1 + W s 0 ) ) ) t = 3 s 3 = g ( U x 3 + W s 2 ) o 3 = f ( V g ( U x 3 + W s 2 ) ) = f ( V g ( U x 3 + W g ( U x 2 + W ( U x 1 + W s 0 ) ) ) ) . . . t = m . . . L o s s = L ( o m , y ) ∂ L ∂ U = ∂ L ∂ o m ∂ o m ∂ s m ∂ s m ∂ U + ∂ L ∂ o m ∂ o m ∂ s m ∂ s m ∂ s m − 1 ∂ s m − 1 ∂ U + . . . + ∂ L ∂ o m ∂ o m ∂ s m ∂ s m ∂ s m − 1 . . . ∂ s 2 ∂ s 1 ∂ s 1 ∂ U = ∑ t = 1 m ∂ L ∂ o m ∂ o m ∂ s m ( ∏ j = t + 1 m ∂ s j ∂ s j − 1 ) ∂ s t ∂ U \begin{aligned} t &= 1 \\ s_1 &= g(Ux_1 + Ws_{0})\\ o_1 &= f(Vg(Ux_1 + Ws_{0}))\\ t &= 2 \\ s_2 &= g(Ux_2 + Ws_{1})\\ o_2 &= f(Vg(Ux_2 + Ws_{1})) =f(Vg(Ux_2 + Wg(Ux_1 + Ws_{0})))\\ t &= 3 \\ s_3 &= g(Ux_3 + Ws_{2})\\ o_3 &= f(Vg(Ux_3 + Ws_{2})) = f(Vg(Ux_3 + Wg(Ux_2 + W(Ux_1 + Ws_{0}))))\\ ...\\ t &= m \\ ...\\ Loss &= L(o_m,y)\\ \frac{\partial L}{\partial U} &= \frac{\partial L}{\partial o_m}\frac{\partial o_m}{\partial s_m}\frac{\partial s_m}{\partial U} + \frac{\partial L}{\partial o_m}\frac{\partial o_m}{\partial s_m}\frac{\partial s_m}{\partial s_{m-1}}\frac{\partial s_{m-1}}{\partial U}+...+ \frac{\partial L}{\partial o_m}\frac{\partial o_m}{\partial s_m}\frac{\partial s_m}{\partial s_{m-1}}...\frac{\partial s_{2}}{\partial s_{1}}\frac{\partial s_{1}}{\partial U}\\ &= \sum_{t=1}^{m}\frac{\partial L}{\partial o_m}\frac{\partial o_m}{\partial s_m}\left(\prod_{j=t+1}^{m}\frac{\partial s_{j}}{\partial s_{j-1}}\right)\frac{\partial s_t}{\partial U} \end{aligned} ts1o1ts2o2ts3o3...t...Loss∂U∂L=1=g(Ux1+Ws0)=f(Vg(Ux1+Ws0))=2=g(Ux2+Ws1)=f(Vg(Ux2+Ws1))=f(Vg(Ux2+Wg(Ux1+Ws0)))=3=g(Ux3+Ws2)=f(Vg(Ux3+Ws2))=f(Vg(Ux3+Wg(Ux2+W(Ux1+Ws0))))=m=L(om,y)=∂om∂L∂sm∂om∂U∂sm+∂om∂L∂sm∂om∂sm−1∂sm∂U∂sm−1+...+∂om∂L∂sm∂om∂sm−1∂sm...∂s1∂s2∂U∂s1=t=1∑m∂om∂L∂sm∂om(j=t+1∏m∂sj−1∂sj)∂U∂st当激活函数为tanh, s t = t a n h ( U x t + W s t − 1 ) s_t = tanh(Ux_t + Ws_{t-1}) st=tanh(Uxt+Wst−1),
权值梯度:
L o s s = ∑ t = 1 m ∂ L ∂ o m ∂ o m ∂ s m ( ∏ j = t + 1 m ∂ s j ∂ s j − 1 ) ∂ s t ∂ U = ∑ t = 1 m ∂ L ∂ o m ∂ o m ∂ s m ( ∏ j = t + 1 m t a n h ′ W ) ∂ s t ∂ U \begin{aligned} Loss &= \sum_{t=1}^{m}\frac{\partial L}{\partial o_m}\frac{\partial o_m}{\partial s_m}\left(\prod_{j=t+1}^{m}\frac{\partial s_{j}}{\partial s_{j-1}}\right)\frac{\partial s_t}{\partial U}\\ &= \sum_{t=1}^{m}\frac{\partial L}{\partial o_m}\frac{\partial o_m}{\partial s_m}\left(\prod_{j=t+1}^{m}tanh'W \right)\frac{\partial s_t}{\partial U} \end{aligned} Loss=t=1∑m∂om∂L∂sm∂om(j=t+1∏m∂sj−1∂sj)∂U∂st=t=1∑m∂om∂L∂sm∂om(j=t+1∏mtanh′W)∂U∂st -
MLP/CNN 的梯度消失:主要是随着网络加深,浅层网络的梯度越来越小,导致参数无法更新迭代。
4. 梯度消失、爆炸的解决方案
在深度神经网络中,往往是梯度消失出现的更多一些。
4.1 梯度爆炸的解决方案
-
梯度裁剪:主要思想是设置一个梯度剪切阈值,然后更新梯度的时候,如果梯度超过这个阈值,那么就将其强制限制在这个范围之内。这可以防止梯度爆炸。
-
权值正则化(weithts regularization):正则化是通过对网络权重做正则限制过拟合,如下正则项在损失函数中的形式:
L o s s = ( y − W T x ) 2 + α ∣ ∣ W ∣ ∣ 2 Loss = (y-W^Tx)^2+\alpha||W||^2 Loss=(y−WTx)2+α∣∣W∣∣2
常见的是L1正则和L2正则,在各个深度框架中都有相应的API可以使用正则化。其中, α \alpha α是指正则项系数,因此,如果发生梯度爆炸,权值的范数就会变的非常大,通过正则化项,可以部分限制梯度爆炸的发生。
4.2 梯度消失的解决方案
4.2.1 选择relu、leakrelu、elu等激活函数
-
relu函数的导数在正数部分是恒等于1的,因此在深层网络中不会导致梯度消失和爆炸的问题。relu优点:解决了梯度消失、爆炸的问题,计算速度快,加速网络训练。relu缺点:导数的负数部分恒为0,会导致一些神经元无法激活(可通过设置小学习率部分解决),输出不是以0为中心的。
-
leakrelu就是为了解决relu的0区间带来的影响。数学表达: l e a k r e l u = m a x ( x ∗ k , x ) leakrelu=max(x*k,x) leakrelu=max(x∗k,x)
其中k是leak系数,一般选择0.1或者0.2,或者通过学习而来。leakrelu解决了0区间带来的影响,而且包含了relu的所有优点。
-
elu也是为了解决relu的0区间带来的影响,其数学表达为:
e l u ( x ) = { x , if x > 0 α ( e x − 1 ) , otherwise elu(x) = \begin{cases} x, & \text{if }x>0\\ \alpha(e^x-1), & \text{otherwise} \end{cases} elu(x)={x,α(ex−1),if x>0otherwise
但是elu相对于leakrelu来说,计算要更耗时间一些。
4.2.2 使用Batchnorm(batch normalization,简称BN):
目前已经被广泛的应用到了各大网络中,具有加速网络收敛速度,提升训练稳定性的效果,Batchnorm本质上是解决反向传播过程中的梯度问题。通过规范化操作将输出信号x规范化到均值为0,方差为1保证网络的稳定性。 具体来说就是反向传播中,经过每一层的梯度会乘以该层的权重,举个简单例子: 正向传播中 f 3 = f 2 ( w T x + b ) f_3=f_2(w^Tx+b) f3=f2(wTx+b) ,那么反向传播中, ∂ f 2 ∂ x = ∂ f 2 ∂ f 1 w \frac{\partial f_2}{\partial x}=\frac{\partial f_2}{\partial f_1}w ∂x∂f2=∂f1∂f2w, 反向传播式子中有 w w w 的存在,所以 w w w 的大小影响了梯度的消失和爆炸,batchnorm就是通过对每一层的输出做scale和shift的方法,通过一定的规范化手段,把每层神经网络任意神经元这个输入值的分布强行拉回到接近均值为0方差为1的标准正太分布,即严重偏离的分布强制拉回比较标准的分布,这样使得激活输入值落在非线性函数对输入比较敏感的区域,这样输入的小变化就会导致损失函数较大的变化,使得让梯度变大,避免梯度消失问题产生,而且梯度变大意味着学习收敛速度快,能大大加快训练速度。
4.2.3 残差结构:
残差单元里的shortcut(捷径)部分可以保证在反向传播中梯度不会消失。
∂ L o s s ∂ x l = ∂ L o s s ∂ x L ∂ x L ∂ x l = ∂ L o s s ∂ x L ( 1 + ∂ ∂ x L ∑ i = l L − 1 F ( x i , W i ) ) \frac{\partial Loss}{\partial x_l}=\frac{\partial Loss}{\partial x_L}\frac{\partial x_L}{\partial x_l}=\frac{\partial Loss}{\partial x_L}\left(1+\frac{\partial }{\partial x_L}\sum_{i=l}^{L-1}F(x_i,W_i)\right) ∂xl∂Loss=∂xL∂Loss∂xl∂xL=∂xL∂Loss(1+∂xL∂i=l∑L−1F(xi,Wi))
式子的第一个因子 ∂ L o s s ∂ x L \frac{\partial Loss}{\partial x_L} ∂xL∂Loss表示的损失函数到达 L 层的梯度,小括号中的1表明短路机制可以无损地传播梯度,而另外一项残差梯度则需要经过带有weights的层,梯度不是直接传递过来的。残差梯度不会那么巧全为-1,而且就算其比较小,有1的存在也不会导致梯度消失。所以残差学习会更容易。4.2.4 LSTM:
使用LSTM(long-short term memory networks,长短期记忆网络),就不那么容易发生梯度消失,主要原因在于LSTM内部复杂的“门”(gates),如下图,LSTM通过它内部的“门”可以在更新的时候“记住”前几次训练的“残留记忆”,因此,经常用于生成文本中。
5. 参考
RNN
- https://zybuluo.com/hanbingtao/note/541458
- https://colab.research.google.com/drive/1Zfvt9Vfs3PrJwSDF8jMvomz7CzU36RXk
LSTM
- http://colah.github.io/posts/2015-08-Understanding-LSTMs/
- https://www.youtube.com/watch?v=9zhrxE5PQgY&feature=youtu.be
- https://towardsdatascience.com/illustrated-guide-to-lstms-and-gru-s-a-stepby-step-explanation-44e9eb85bf21
- https://medium.com/datadriveninvestor/how-do-lstm-networks-solve-theproblem-of-vanishing-gradients-a6784971a577
欢迎各位关注我的个人公众号:HsuDan,我将分享更多自己的学习心得、避坑总结、面试经验、AI最新技术资讯。
-
-
AI03过拟合欠拟合;梯度消失、梯度爆炸;卷积神经网络基础
2021-01-06 14:03:04过拟合欠拟合及其解决方案 训练误差和泛化误差 训练误差:模型在训练数据集上表现出的误差 泛化误差:模型在任意一个测试数据样本上表现出的误差的期望,并常常通过测试数据集上的误差来近似。 ... -
TensorFlow2 手把手教你避开梯度消失和梯度爆炸
2021-06-11 10:25:34TensorFlow2 手把手教你避开梯度消失和梯度爆炸.TensorFlow2 手把手教你避开梯度消失和梯度爆炸
梯度消失 & 梯度爆炸
输出结果:vanish: 0.025517964452291125 explode: 37.78343433288728
梯度消失
梯度消失问题 (Vanishing gradient problem). 如果导数小于 1, 随着网络层数的增加梯度跟新会朝着指数衰减的方向前进, 这就是梯度消失.
当导数小于 1 的时候, 层数越多, 梯度就越小, 即梯度消失.梯度爆炸
梯度爆炸问题 (Exploding gradient problem). 如果导数大于 1, 随着网络层数的增加梯度跟新会朝着指数增加的方向前进, 这就是梯度爆炸.
当导数大于 1 的时候, 层数越多, 梯度就越大, 即梯度爆炸.张量限幅
通过张量限幅, 我们可以有效解决梯度爆炸问题.
tf.clip_by_value
我们可以通过
tf.clip_by_value
函数来实现张量限幅.格式:
tf.clip_by_value( t, clip_value_min, clip_value_max, name=None )
参数:
- t: 传入的张量
- clip_value_min: 下限
- clip_value_max: 上限
- name: 数据名称
例子:
# clip_by_value a = tf.range(10) print(a) b = tf.maximum(a, 2) print(b) c = tf.minimum(a, 8) print(c) d = tf.clip_by_value(a, 2, 8) print(d)
输出结果:
tf.Tensor([0 1 2 3 4 5 6 7 8 9], shape=(10,), dtype=int32) tf.Tensor([2 2 2 3 4 5 6 7 8 9], shape=(10,), dtype=int32) tf.Tensor([0 1 2 3 4 5 6 7 8 8], shape=(10,), dtype=int32) tf.Tensor([2 2 2 3 4 5 6 7 8 8], shape=(10,), dtype=int32)
tf.clip_by_norm
tf.clip_by_norm
可以对梯度进行裁剪, 防止梯度爆炸.格式:
tf.clip_by_norm( t, clip_norm, axes=None, name=None )
参数:
- t: 传入的张量
- clip_norm: 定义最大限幅
- axes: 计算尺寸
- name: 数据名称
例子:
# clip_by_normal a = tf.random.normal([2, 2], mean=10) print(a) print(tf.norm(a)) # 范数 b = tf.clip_by_norm(a, 15) print(b) print(tf.norm(b)) # 范数
输出结果:
tf.Tensor( [[ 9.33037 10.703022] [ 9.788097 9.713704]], shape=(2, 2), dtype=float32) tf.Tensor(19.793266, shape=(), dtype=float32) tf.Tensor( [[7.070867 8.111109 ] [7.417748 7.3613706]], shape=(2, 2), dtype=float32) tf.Tensor(15.0, shape=(), dtype=float32)
mnist 展示梯度爆炸
为了实现梯度爆炸, 我们把学习率设为 0.1.
完整代码
# 读取训练集的特征值和目标值 (x, y), _ = tf.keras.datasets.mnist.load_data() # 转换为0~1的形式 x = tf.convert_to_tensor(x, dtype=tf.float32) / 255 # 转换成one_hot编码 y = tf.one_hot(y, depth=10) # 批次分割 train_db = tf.data.Dataset.from_tensor_slices((x, y)).batch(256).repeat(30) def main(): # 生成w1形状为[784, 512]的截断正态分布, 中心为0, 标差为0.1 w1 = tf.Variable(tf.random.truncated_normal([784, 512], stddev=0.1)) # 生成b1形状为[512]初始化为0 b1 = tf.Variable(tf.zeros([512])) # 生成w2形状为[512, 256]的截断正态分布, 中心为0, 标差为0.1 w2 = tf.Variable(tf.random.truncated_normal([512, 256], stddev=0.1)) # 生成b2形状为[256]初始化为0 b2 = tf.Variable(tf.zeros([256])) # 生成w3形状为[256, 10]的截断正态分布, 中心为0, 标差为0.1 w3 = tf.Variable(tf.random.truncated_normal([256, 10], stddev=0.1)) # 生成b3形状为[10]初始化为0 b3 = tf.Variable(tf.zeros([10])) # 优化器 optimizer = tf.keras.optimizers.SGD(learning_rate=0.1) # 梯度下降 for step, (x, y) in enumerate(train_db): # 把x平铺 [256, 28, 28] => [256, 784] x = tf.reshape(x, [-1, 784]) with tf.GradientTape() as tape: # 第一个隐层 h1 = x @ w1 + b1 h1 = tf.nn.relu(h1) # 激活 # 第二个隐层 h2 = h1 @ w2 + b2 h2 = tf.nn.relu(h2) # 激活 # 输出层 out = h2 @ w3 + b3 # 计算损失函数 loss = tf.square(y - out) loss = tf.reduce_mean(loss) # 计算梯度 grads = tape.gradient(loss, [w1, b1, w2, b2, w3, b3]) # 调试输出剪切前的范数 print("================before===============") for g in grads: print(tf.norm(g)) grads, _ = tf.clip_by_global_norm(grads, 15) # 调试输出剪切后的范数 print("================after===============") for g in grads: print(tf.norm(g)) optimizer.apply_gradients(zip(grads, [w1, b1, w2, b2, w3, b3])) # 跟新权重 if __name__ == '__main__': main()
输出结果
================before=============== tf.Tensor(5.5961547, shape=(), dtype=float32) tf.Tensor(0.87258744, shape=(), dtype=float32) tf.Tensor(7.397964, shape=(), dtype=float32) tf.Tensor(0.69156337, shape=(), dtype=float32) tf.Tensor(9.840232, shape=(), dtype=float32) tf.Tensor(0.8157242, shape=(), dtype=float32) ================after=============== tf.Tensor(5.5961547, shape=(), dtype=float32) tf.Tensor(0.87258744, shape=(), dtype=float32) tf.Tensor(7.397964, shape=(), dtype=float32) tf.Tensor(0.69156337, shape=(), dtype=float32) tf.Tensor(9.840232, shape=(), dtype=float32) tf.Tensor(0.8157242, shape=(), dtype=float32) ================before=============== tf.Tensor(18.01539, shape=(), dtype=float32) tf.Tensor(2.9375393, shape=(), dtype=float32) tf.Tensor(21.330334, shape=(), dtype=float32) tf.Tensor(2.1504176, shape=(), dtype=float32) tf.Tensor(21.820374, shape=(), dtype=float32) tf.Tensor(2.0918982, shape=(), dtype=float32) ================after=============== tf.Tensor(7.5730414, shape=(), dtype=float32) tf.Tensor(1.2348388, shape=(), dtype=float32) tf.Tensor(8.966527, shape=(), dtype=float32) tf.Tensor(0.90396047, shape=(), dtype=float32) tf.Tensor(9.172523, shape=(), dtype=float32) tf.Tensor(0.8793609, shape=(), dtype=float32) ================before=============== tf.Tensor(0.5821787, shape=(), dtype=float32) tf.Tensor(0.0859229, shape=(), dtype=float32) tf.Tensor(0.7110027, shape=(), dtype=float32) tf.Tensor(0.082481824, shape=(), dtype=float32) tf.Tensor(0.51846975, shape=(), dtype=float32) tf.Tensor(0.1655324, shape=(), dtype=float32) ================after=============== tf.Tensor(0.5821787, shape=(), dtype=float32) tf.Tensor(0.0859229, shape=(), dtype=float32) tf.Tensor(0.7110027, shape=(), dtype=float32) tf.Tensor(0.082481824, shape=(), dtype=float32) tf.Tensor(0.51846975, shape=(), dtype=float32) tf.Tensor(0.1655324, shape=(), dtype=float32) ... ...
-
梯度消失 & 梯度爆炸
2019-07-01 23:46:51神经网络(DNN)其实就是人工神经网络(ANN)的多层实现,一个ANN有2个或者2个以上的隐藏层,则被称为深度神经网络(DNN),下面的内容我们会针对神经网络反向微分过程中产生的梯度爆炸和梯度消失,以及当前有效的缓和方法做... -
Dive into deep learning task 03- 过拟合、欠拟合及其解决方案;梯度消失、梯度爆炸;循环神经网络进阶
2021-01-07 00:44:231. 过拟合 欠拟合 特征复杂,但是训练 样本数不足时,会产生过拟合,即训练误差小,但是在测试集上的测试误差比较大,即泛化能力强 解决的办法是增加样本数量 或用L2范数进行征罚。 增加样本数量的方法比较简单,... -
Deep Learning_Task3_过拟合、欠拟合/梯度消失、梯度爆炸/循环神经网络进阶
2021-01-06 15:56:07一、过拟合、欠拟合及其解决方案 ·模型选择、过拟合和欠拟合 训练误差(training error):模型在训练数据集上表现出来的误差 泛化误差(generalization error):模型在任意一个测试样本上表现出的误差的期望,并常常... -
动手学深度学习:梯度消失、梯度爆炸
2021-01-06 21:33:51动手学深度学习:梯度消失、梯度爆炸 内容摘自伯禹人工智能AI公益课程 目录: 梯度消失和梯度爆炸的基本概念 考虑到环境因素的其他问题 Kaggle房价预测# 梯度消失、梯度爆炸以及Kaggle房价预测 1、梯度消失和梯度... -
LSTM解决梯度消失问题
2022-03-22 16:27:22“LSTM 能解决梯度消失/梯度爆炸”是对 LSTM 的经典误解。 1、首先需要明确的是,RNN 中的梯度消失/梯度爆炸和普通的 MLP 或者深层 CNN 中梯度消失/梯度爆炸的含义不一样。MLP/CNN 中不同的层有不同的参数,各是各的... -
【机器学习】梯度消失和梯度爆炸的原因分析、表现及解决方案
2021-06-15 21:23:20当存在过多的层时,就会出现梯度不稳定场景,比如梯度消失和梯度爆炸。所以梯度消失和梯度爆炸属于梯度不稳定的范畴。 (2)梯度消失和梯度爆炸 BP算法基于梯度下降策略,以目标的负梯度方向对参数进行调整,计 -
残差神经网络为什么可以缓解梯度消失?
2022-01-03 17:58:57随着网络层数的加深,目标函数越来越容易陷入局部最优解,同时,随着层数增加,梯度消失问题更加严重,特别是激活函数为sigmoid/softmax/tanh等,使得原理输出层的网络参数得不到有效的学习。因此为了改善这个问题,... -
梯度消失和梯度爆炸
2020-12-30 12:12:41梯度消失和梯度爆炸,简单来说,就是因为激活函数sigmoid导致的,输入值过大或过小导致sigmoid函数趋于0和1,对应的求导趋近于0,而且sigmoid的导数在(0,1/4)之间,这就导致如果初始化W为0-1之间的比较小的值,... -
为什么LSTM可以缓解梯度消失?
2021-03-10 23:20:55早些时候写了一篇关于RNN/LSTM的博客,介绍了RNN、LSTM的基本原理,其中提到了RNN梯度消失的问题,借机引出了LSTM。当时的文章中只写到了LSTM可以缓解梯度消失,但没有写明原因,原因是当时太想当然了,没有仔细... -
梯度消失与梯度爆炸产生原因及解决方法
2020-08-30 19:16:301 、什么是梯度消失和梯度爆炸 在反向传播过程中需要对激活函数进行求导,如果导数大于1,那么随着网络层数的增加梯度更新将会朝着指数爆炸的方式增加这就是梯度爆炸。同样如果导数小于1,那么随着网络层数的增加...