爆炸梯度是一种问题,在该问题中,大的误差梯度累积,导致在训练期间神经网络模型权重的更新非常大。
这会使您的模型不稳定,无法从您的训练数据中学习。
在本文中,您将了解深度人工神经网络中的爆炸梯度问题。
完成这篇文章后,您将了解:
- 爆炸梯度是什么以及它们在训练过程中引起的问题。
- 如何知道您的网络模型是否存在爆炸梯度。
- 如何解决您网络中的爆炸梯度问题。
立即开始您的项目,阅读我的新书 《Python长短期记忆网络》,其中包含分步教程和所有示例的Python源代码文件。
让我们开始吧。
- 更新于2018年10月:已删除对ReLU作为解决方案的提及。

递归神经网络中爆炸梯度入门指南
照片由 Taro Taylor 拍摄,保留部分权利。
什么是爆炸梯度?
误差梯度是神经网络训练过程中计算出的方向和大小,用于以正确的方向和正确的量更新网络权重。
在深度网络或递归神经网络中,误差梯度会在更新过程中累积,导致非常大的梯度。这些反过来会导致网络权重产生大的更新,从而导致网络不稳定。在极端情况下,权重的值可能会变得非常大,以至于溢出并导致NaN值。
爆炸通过具有大于1.0的值的网络层重复乘以梯度的指数增长而发生。
爆炸梯度有什么问题?
在深度多层感知机网络中,爆炸梯度可能导致网络不稳定,该网络最多只能从训练数据中学习,最坏的情况是导致NaN权重值,这些值无法再更新。
…爆炸梯度可能导致学习不稳定。
— 第282页,《深度学习》,2016年。
在递归神经网络中,爆炸梯度可能导致网络不稳定,无法从训练数据中学习,最多也只能使网络无法学习长序列数据。
…爆炸梯度问题是指在训练过程中梯度的范数急剧增加。此类事件是由于长期成分的爆炸造成的
— 《训练递归神经网络的困难》,2013年。
如何知道您是否存在爆炸梯度?
在训练您的网络时,可能存在一些细微迹象表明您遭受了爆炸梯度,例如
- 模型无法在您的训练数据上获得牵引力(例如,损失差)。
- 模型不稳定,导致损失从一次更新到下一次更新发生大的变化。
- 模型损失在训练过程中变为NaN。
如果您遇到这类问题,您可以深入研究以查看是否存在爆炸梯度问题。
有一些不太微妙的迹象可以用来确认您是否存在爆炸梯度。
- 模型权重在训练过程中很快变得非常大。
- 模型权重在训练过程中变为NaN值。
- 在训练过程中,每个节点和层的误差梯度值始终大于1.0。
如何解决爆炸梯度?
有许多解决爆炸梯度的方法;本节列出了一些您可以使用的最佳实践方法。
1. 重新设计网络模型
在深度神经网络中,可以通过重新设计网络以减少层数来解决爆炸梯度问题。
在训练网络时使用较小的批量大小也可能有一些好处。
在递归神经网络中,在训练过程中更新的先前时间步长更少,称为截断反向传播,可能会减少爆炸梯度问题。
2. 使用长短期记忆网络
在递归神经网络中,由于该类型网络训练的固有不稳定性,可能会发生梯度爆炸,例如通过反向传播(本质上将递归网络转换为深度多层感知机神经网络)。
通过使用长短期记忆(LSTM)记忆单元和可能的相关的门控类型神经元结构,可以减少爆炸梯度。
采用LSTM记忆单元是用于序列预测的递归神经网络的新最佳实践。
3. 使用梯度裁剪
对于具有大批量大小的非常深的感知机网络和具有非常长输入序列长度的LSTM,仍然可能发生爆炸梯度。
如果爆炸梯度仍然发生,您可以在训练网络时检查并限制梯度的大小。
这称为梯度裁剪。
处理爆炸梯度有一个简单但非常有效的解决方案:如果梯度的范数超过给定的阈值,则裁剪梯度。
— 第5.2.4节,“神经网络在自然语言处理中的方法”,2017年。
具体来说,会检查误差梯度的值是否超过阈值,如果误差梯度超过阈值,则将其裁剪或设置为该阈值。
在某种程度上,可以通过梯度裁剪(在执行梯度下降步骤之前对梯度值进行阈值处理)来缓解爆炸梯度问题。
— 第294页,《深度学习》,2016年。
在Keras深度学习库中,您可以在训练之前通过在优化器上设置clipnorm或clipvalue参数来使用梯度裁剪。
好的默认值是clipnorm=1.0和clipvalue=0.5。
4. 使用权重正则化
另一种方法是,如果爆炸梯度仍然发生,可以检查网络权值的大小,并对网络的损失函数中的大权值应用惩罚。
这称为权重正则化,通常可以使用L1(绝对值权重)或L2(平方权重)惩罚。
对递归权重使用L1或L2惩罚有助于解决爆炸梯度问题
— 《训练递归神经网络的困难》,2013年。
在Keras深度学习库中,您可以通过在层上设置kernel_regularizer参数并使用L1或L2正则化器来使用权重正则化。
进一步阅读
如果您想深入了解,本节提供了更多关于该主题的资源。
文章
书籍
- 深度学习, 2016.
- 自然语言处理中的神经网络方法, 2017.
论文
- 关于训练递归神经网络的困难, 2013.
- 使用梯度下降学习长期依赖关系很困难, 1994.
- 理解爆炸梯度问题, 2012.
文章
Keras API
总结
在本文中,您了解了训练深度神经网络模型时爆炸梯度的问题。
具体来说,你学到了:
- 爆炸梯度是什么以及它们在训练过程中引起的问题。
- 如何知道您的网络模型是否存在爆炸梯度。
- 如何解决您网络中的爆炸梯度问题。
你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。
我曾在优化问题中使用复杂的梯度,这有助于解决这个问题。这种做法是否存在于神经网络中?
我以前没见过,对您来说效果好吗?
感谢您提供研究论文和其他文献的链接。
您认为对深度学习前沿方法感兴趣的人该如何跟进最新的研究?
arXiv上有很多论文,很难决定读哪些或跳过哪些。
我建议关注一两年前有效的技术。最前沿的噪音太大,其中大部分是明年将不再有用的噪音。
谢谢你的文章。非常有帮助。这些解决爆炸梯度的修复方法也可以添加到列表中
1. 谨慎初始化权重,例如“Xavier”初始化或“He”初始化。
2. 执行梯度检查:有时错误发生在代码中的某个实现错误时;除非您使用的是Tensorflow反向传播等预打包库。如果您从头开始实现了网络,则进行GD检查
Amir,很棒的建议!谢谢。
谢谢 Jason 的文章。但我对 Sigmoid 或 Tanh 函数是否是爆炸梯度的原因感到疑惑。由于它们的导数对于大值和小的激活值趋向于零,它们确实会导致梯度消失。那么它们如何导致梯度爆炸呢?
在“如何解决爆炸梯度”部分的方法中
1 sigmoid->relu
sigmoid 的梯度是 f(1-f),它在 (0,1) 之间;而 ReLU 的梯度是 {0,1}。这种替换如何解决爆炸梯度?
2 lstm
LSTM 通过替换乘法与加法来修复梯度消失,将长期依赖信息传递到最后一步;而且,我认为这种方法无法解决梯度爆炸问题。
希望得到回复,谢谢
实际上,sigmoid 的梯度在 0 和 0.25 之间。希望能得到对这两个问题的解释。
在哪里可以找到可在 Chromebook 上使用的机器学习程序?Chromebook 不允许下载任何使用程序。
不确定,抱歉。
也许是可以用在机器学习或深度学习上的 JavaScript 库?
例如
http://cs.stanford.edu/people/karpathy/convnetjs/
可在任何平台上通过浏览器使用的“机器学习程序”
- 免费的 Google GPU-Cloud
https://colab.research.google.com/notebooks/welcome.ipynb
每12小时重置数据,但对于学习神经网络来说已经足够了。
好建议。
不过,NLP 和视觉的许多运行会持续数天。
EC2 可能更好
https://machinelearning.org.cn/develop-evaluate-large-deep-learning-models-keras-amazon-web-services/
精彩的阅读,谢谢!
谢谢。
我推荐这篇相对较新的论文
https://arxiv.org/abs/1712.05577
谢谢推荐,你读过它吗?
是的,我正在测试预激活标准差和预激活符号多样性的指标,在 ReLU、PReLU 和我们创新性的可学习 ISRLU (https://arxiv.org/abs/1710.09967) 上表现如何。
期待听到您的进展!
我认为 ReLU 用于处理梯度消失,而不是爆炸梯度。我说得对吗?
我认为两者都是。
ReLU 如何减小爆炸梯度问题?ReLU 函数对于局部正场是无界的。这意味着 ReLU 不会限制其对局部场>0 的输出。由于 ReLU 的输出将是另一个 ReLU 的输入,输出将由于累积乘法而爆炸。不是因为这个,ReLU 是导致爆炸梯度问题的原因之一吗?
确实,ReLU 解决了梯度消失问题。
已修复。
不知何故,当我从 ReLU 切换到 Sigmoid 时,我从未遇到过爆炸梯度问题……
这种情况并非总是发生,但网络越深,或者输入越大,就越有可能爆炸(或消失)。
您认为我应该为此使用 Sigmoid(在 LSTM 中)吗?还是它已经过时了?
我相信 LSTM 使用 Sigmoid 和 Tanh 来实现不同的门。
在 LSTM 中使用 ReLU 也可以很有效。
嗨,Jason,
感谢您的帖子。
长短期记忆网络如何直接影响梯度爆炸?
我没有看到任何联系。此外,我认为这可能不是一种普遍适用的方法,因为许多应用都不是 LSTM 友好的,也就是说,其他架构可能是更好的选择。
谢谢
LSTM 降低了反向传播过程中梯度爆炸的可能性。也许可以比较一下 LSTM 和 SimpleRNN 在同一个问题上的表现?
看到文章的“您将学到什么”和“结论”比实际内容还长,真是令人沮丧。
感谢您的反馈 Lukas。
嗨,Jason,
我以前没有遇到过这种情况,但读了您的帖子让我对此感到好奇。您认为在一个小的前馈神经网络(例如一个隐藏层)中是否可能观察到爆炸梯度问题?如果可能,为什么会发生这种情况?
非常感谢
也许使用非常大的(未缩放的)输入。
嗨,
Swish 激活应该在隐藏层中使用。或者我可以在输入层使用它吗?
Swish 激活可以用来替换 LSTM 架构中的 Sigmoid 激活。可能吗?
什么是“Swish 激活”?
这里还有一些未提及的方法。
1 – 对激活层进行归一化,如 Batch Normalization、Layer Normalization 等。
2 – 对权重进行归一化,如谱归一化。
3 – 使用带有跳跃连接的模块,如残差块。
感谢分享。
我可以对输入值进行分数化,也可以使用 LOG10。
感谢您的反馈 Vitor!
我有一点不明白,如果我们用大的权重进行初始化,然后对我们的损失函数关于我们的参数求导,我们会得到大的梯度,然后在更新参数时,我们从旧参数中减去大的梯度,这会减小我们参数的大小。
我不明白这里有什么问题
你好 Abolfazi…以下资源希望能帮助你更清楚地理解
https://neptune.ai/blog/vanishing-and-exploding-gradients-debugging-monitoring-fixing