文章目录

  • 1. 梯度爆炸和裁剪
  • 2. TensorFlow.Keras 实现
    • 2.1 梯度范数缩放(Gradient Norm Scaling)
    • 2.2 梯度值裁剪(Gradient Value Clipping)
  • 3. 实例
    • 3.1 梯度爆炸 MLP
    • 3.2 梯度范数缩放 MLP
    • 3.3 梯度值裁剪 MLP

给定误差函数,学习率,甚至目标变量的大小,训练神经网络可能变得不稳定。训练期间权重的较大更新会导致数值上溢或下溢,通常称为梯度爆炸(gradients exploding)

梯度爆炸在递归神经网络中更为常见,例如LSTM,因为梯度的累积在数百个输入时间步长上展开。

梯度爆炸的一种常见且相对容易的解决方案是:在通过网络向后传播误差并使用其更新权重之前,更改误差的导数。两种方法包括:给定选定的向量范数( vector norm)来重新缩放梯度;以及裁剪超出预设范围的梯度值。这些方法一起被称为梯度裁剪(gradient clipping)


1. 梯度爆炸和裁剪

使用随机梯度下降优化算法训练神经网络。这首先需要在一个或多个训练样本上估算损失,然后计算损失的导数,该导数通过网络反向传播,以更新权重。使用学习率控制的反向传播误差的一小部分来更新权重。

权重的更新可能会很大,以至于权重的数值精度超出或低于该数值精度。权重在上溢或下溢时可以取“NaN”或“Inf”值,但网络将毫无用处,因为信号流过无效权重时永远预测NaN值。权重的上溢或下溢是指网络训练过程的不稳定性,并且由于不稳定的训练过程导致网络无法进行训练,从而导致模型实质上是无用的,因此被称为梯度爆炸。

在给定的神经网络(例如卷积神经网络或多层感知器)中,可能由于配置选择不当而发生梯度爆炸:

  • 学习率选择不当会导致较大的权重更新。
  • 准备的数据有很多噪声,导致目标变量差异很大。
  • 损失函数选择不当,导致计算出较大的误差值。

在递归神经网络(例如长短期记忆网络)中容易出现梯度爆炸。通常,可以通过精心配置网络模型来避免爆炸梯度,例如,选择较小的学习速率,按比例缩放目标变量和标准损失函数。尽管如此,对于具有大量输入时间步长的递归网络,梯度爆炸仍然是一个需要着重考虑的问题。

梯度爆炸的一种常见解决方法是先更改误差导数,然后通过网络反向传播误差导数,然后使用它来更新权重。通过重新缩放误差导数,权重的更新也将被重新缩放,从而大大降低了上溢或下溢的可能性。更新误差导数的主要方法有两种:

  • 梯度缩放(Gradient Scaling)
  • 梯度裁剪(Gradient Clipping)

梯度缩放涉及对误差梯度向量进行归一化,以使向量范数大小等于定义的值,例如1.0。只要它们超过阈值,就重新缩放它们。如果渐变超出了预期范围,则渐变裁剪会强制将渐变值(逐个元素)强制为特定的最小值或最大值。这些方法通常简称为梯度裁剪。

当传统的梯度下降算法建议进行一个非常大的步长时,梯度裁剪将步长减小到足够小,以至于它不太可能走到梯度最陡峭的下降方向的区域之外。

它是一种仅解决训练深度神经网络模型的数值稳定性,而不能改进网络性能的方法。

梯度向量范数或预设范围的值可以通过反复试验来配置,可以使用文献中使用的常用值,也可以先通过实验观察通用向量范数或范围,然后选择一个合理的值。

对于网络中的所有层,通常都使用相同的梯度裁剪配置。不过,在某些示例中,与隐藏层相比,输出层中允许更大范围的误差梯度。


2. TensorFlow.Keras 实现

2.1 梯度范数缩放(Gradient Norm Scaling)

梯度范数缩放:在梯度向量的L2向量范数(平方和)超过阈值时,将损失函数的导数更改为具有给定的向量范数

例如,可以将范数指定为1.0,这意味着,如果梯度的向量范数超过1.0,则向量中的值将重新缩放,以使向量范数等于1.0。在Keras中通过在优化器上指定 clipnorm 参数实现:

....
opt = SGD(lr=0.01, momentum=0.9, clipnorm=1.0)

2.2 梯度值裁剪(Gradient Value Clipping)

如果梯度值小于负阈值或大于正阈值,则梯度值剪切将损失函数的导数剪切为给定值。例如,可以将范数指定为0.5,这意味着如果梯度值小于-0.5,则将其设置为-0.5,如果梯度值大于0.5,则将其设置为0.5。通过在优化器上指定 clipvalue 参数实现:

...
opt = SGD(lr=0.01, momentum=0.9, clipvalue=0.5)

3. 实例

通过一个简单的MLP回归问题来说明梯度裁剪的作用。

3.1 梯度爆炸 MLP

from sklearn.datasets import make_regression
from keras.layers import Dense
from keras.models import Sequential
from keras.optimizers import SGD
import matplotlib.pyplot as plt
plt.rcParams['figure.dpi'] = 150# 构造回归问题数据集
X, y = make_regression(n_samples=1000, n_features=20, noise=0.1, random_state=1)# 划分训练集和验证集
n_train = 500
trainX, testX = X[:n_train, :], X[n_train:, :]
trainy, testy = y[:n_train], y[n_train:]# 定义模型
model = Sequential()
model.add(Dense(25, input_dim=20, activation='relu', kernel_initializer='he_uniform'))
model.add(Dense(1, activation='linear'))# 编译模型
model.compile(loss='mean_squared_error', optimizer=SGD(lr=0.01, momentum=0.9))# 训练模型
history = model.fit(trainX, trainy, validation_data=(testX, testy), epochs=100, verbose=0)# 评估模型
train_mse = model.evaluate(trainX, trainy, verbose=0)
test_mse = model.evaluate(testX, testy, verbose=0)
print('Train: %.3f, Test: %.3f' % (train_mse, test_mse))# 绘制损失曲线
plt.title('Mean Squared Error')
plt.plot(history.history['loss'], label='train')
plt.plot(history.history['val_loss'], label='test')
plt.legend()
plt.show()

在这种情况下,该模型无法学习,从而导致对NaN值的预测。给定非常大的误差,然后在训练中针对权重更新计算出的误差梯度,模型权重会爆炸。传统的解决方案是使用标准化或归一化来重新调整目标变量。不过,本文使用替代方法–梯度修剪。


3.2 梯度范数缩放 MLP

from sklearn.datasets import make_regression
from keras.layers import Dense
from keras.models import Sequential
from keras.optimizers import SGD
import matplotlib.pyplot as plt
plt.rcParams['figure.dpi'] = 150# 构造回归问题数据集
X, y = make_regression(n_samples=1000, n_features=20, noise=0.1, random_state=1)# 划分训练集和验证集
n_train = 500
trainX, testX = X[:n_train, :], X[n_train:, :]
trainy, testy = y[:n_train], y[n_train:]# 定义模型
model = Sequential()
model.add(Dense(25, input_dim=20, activation='relu', kernel_initializer='he_uniform'))
model.add(Dense(1, activation='linear'))# 编译模型
opt = SGD(lr=0.01, momentum=0.9, clipnorm=1.0)
model.compile(loss='mean_squared_error', optimizer=opt)# 训练模型
history = model.fit(trainX, trainy, validation_data=(testX, testy), epochs=100, verbose=0)# 评估模型
train_mse = model.evaluate(trainX, trainy, verbose=0)
test_mse = model.evaluate(testX, testy, verbose=0)
print('Train: %.3f, Test: %.3f' % (train_mse, test_mse))# 绘制损失曲线
plt.title('Mean Squared Error')
plt.plot(history.history['loss'], label='train')
plt.plot(history.history['val_loss'], label='test')
plt.legend()
plt.show()


该图显示了损失在20个epoch内从20000以上的大数值迅速下降到100以下的小数值。


3.3 梯度值裁剪 MLP

from sklearn.datasets import make_regression
from keras.layers import Dense
from keras.models import Sequential
from keras.optimizers import SGD
import matplotlib.pyplot as plt
plt.rcParams['figure.dpi'] = 150# 构造回归问题数据集
X, y = make_regression(n_samples=1000, n_features=20, noise=0.1, random_state=1)# 划分训练集和验证集
n_train = 500
trainX, testX = X[:n_train, :], X[n_train:, :]
trainy, testy = y[:n_train], y[n_train:]# 定义模型
model = Sequential()
model.add(Dense(25, input_dim=20, activation='relu', kernel_initializer='he_uniform'))
model.add(Dense(1, activation='linear'))# 编译模型
opt = SGD(lr=0.01, momentum=0.9, clipvalue=5.0)
model.compile(loss='mean_squared_error', optimizer=opt)# 训练模型
history = model.fit(trainX, trainy, validation_data=(testX, testy), epochs=100, verbose=0)# 评估模型
train_mse = model.evaluate(trainX, trainy, verbose=0)
test_mse = model.evaluate(testX, testy, verbose=0)
print('Train: %.3f, Test: %.3f' % (train_mse, test_mse))# 绘制损失曲线
plt.title('Mean Squared Error')
plt.plot(history.history['loss'], label='train')
plt.plot(history.history['val_loss'], label='test')
plt.legend()
plt.show()


该图表明,该模型可以快速学习问题,仅在几个训练周期内就损失了不到100的MSE。


参考:
https://machinelearningmastery.com/how-to-avoid-exploding-gradients-in-neural-networks-with-gradient-clipping/

【调参19】如何使用梯度裁剪(Gradient Clipping)避免梯度爆炸相关推荐

  1. [机器学习] ML重要概念:梯度(Gradient)与梯度下降法(Gradient Descent)

    本文转自:https://blog.csdn.net/walilk/article/details/50978864 引言 机器学习栏目记录我在学习Machine Learning过程的一些心得笔记, ...

  2. 梯度裁剪Grandient Clipping

    神经网络是通过梯度下降来学习的. 梯度爆炸问题一般会随着网络层数的增加而变得越来越明显.如果发生梯度爆炸,那么就是学过了,会直接跳过最优解.因此需要梯度裁剪,避免模型越过最优点. 梯度裁剪有两种方法 ...

  3. 梯度消亡(Gradient Vanishing)和梯度爆炸(Gradient Exploding)

    文章目录 一.梯度消失 1.1 定义 1.2 梯度消亡(Gradient Vanishing)前提 1.3 产生的原因 1.4 解决方案 二.梯度爆炸 2.1 解决方法 一.梯度消失 1.1 定义 神 ...

  4. ML重要概念:梯度(Gradient)与梯度下降法(Gradient Descent)

    引言 机器学习栏目记录我在学习Machine Learning过程的一些心得笔记,涵盖线性回归.逻辑回归.Softmax回归.神经网络和SVM等等,主要学习资料来自网上的免费课程和一些经典书籍,免费课 ...

  5. 新手炼丹师的调参内经——深度学习涨点技巧总结

    新手炼丹师的调参内经--深度学习涨点技巧总结 训练神经网络的过程就像是一个炼丹的过程,各位炼丹师们除了要设计一个好的丹方(Contribution),配置好的炼丹炉(GPU Server),当然这其中 ...

  6. 深度学习这么调参训练_深度学习调参技巧

    训练技巧对深度学习来说是非常重要的,作为一门实验性质很强的科学,同样的网络结构使用不同的训练方法训练,结果可能会有很大的差异.这里我总结了近一年来的炼丹心得,分享给大家,也欢迎大家补充指正. 参数初始 ...

  7. 深度学习这么调参训练_深度学习调参及训练技巧(转)

    深度学习调参及训练技巧(转) 作者:婉儿飞飞 链接:https://www.jianshu.com/p/0b116c43eb16 来源:简书 简书著作权归作者所有,任何形式的转载都请联系作者获得授权并 ...

  8. 不使用梯度裁剪和使用梯度裁剪的对比(tensorflow)

    一:不使用梯度裁剪 #网络搭建和模型训练 import tensorflow as tf from tensorflow.keras import layers,optimizers,datasets ...

  9. 【李宏毅机器学习】04:梯度下降Gradient Descent

    李宏毅机器学习04:梯度下降Gradient Descent 文章目录 李宏毅机器学习04:梯度下降Gradient Descent 一.梯度下降方法 二.梯度下降的改进方法 Tip 1: Tunin ...

最新文章

  1. Flutter实战视频-移动电商-59.购物车_计算商品价格和数量
  2. 读书笔记:锋利的JQuery
  3. 深入分析存储器的位宽及与C的关系
  4. win2008 mysql_mysql5.7.17在win2008R2的64位系统安装与配置实例
  5. Succinctly 中文系列教程(二) 20220109 更新
  6. tomcat构建及session保持
  7. 政法委重点人员联防联控系统开发,社会治安防控平台建设
  8. (第八天)记忆系统训练软件3.0
  9. 对于寨板X99开启AIDA64传感器必须的设置
  10. UltraCompare破解流程
  11. 软件测试面试题:智力题。
  12. python多张子图画在一张画布上,显示图例和标题,并保存。
  13. C/C++中.bss段的解释
  14. 拼团不中返利模式开发(拼团商城返现系统源码设计)
  15. 基于freeradius的无线认证
  16. Max导Unity Humanoid模型
  17. nyist120 校园网络 (Tarjan算法 / 强连通分量)
  18. 计算机组成原理实验课设:复杂指令模型计算机设计与实现
  19. 90后天搜人图鉴:有梦想的人运气都不会太差
  20. 快抖“变长”、爱优腾“变短”

热门文章

  1. hive通过grouping sets多维度组合去重统计避免使用distinct
  2. 关于自然语言处理之one hot模型
  3. avahi-daemon启动失败-解决方法-linux
  4. 实现联系人功能,右侧A~Z滑动
  5. newman工具的运用
  6. 毕业论文避免查重率过高技巧
  7. 第一章 回归模型分析
  8. 在Mac OS X苹果lion系统上制作USB启动盘
  9. Privacy Amplification by Decentralization
  10. 抽象类和接口的区别,必须弄明白的