TensorFlow教程——梯度爆炸与梯度裁剪

在较深的网络,如多层CNN或者非常长的RNN,由于求导的链式法则,有可能会出现梯度消失(Gradient Vanishing)或梯度爆炸(Gradient Exploding )的问题。(这部分知识后面补充)

原理

问题:为什么梯度爆炸会造成训练时不稳定而且不收敛?
梯度爆炸,其实就是偏导数很大的意思。回想我们使用梯度下降方法更新参数:

w1w2=w1αJ(w)w1=w2αJ(w)w2(1) (1) w 1 = w 1 − α ∂ J ( w ) ∂ w 1 w 2 = w 2 − α ∂ J ( w ) ∂ w 2

损失函数的值沿着梯度的方向呈下降趋势,然而,如果梯度(偏导数)很大话,就会出现函数值跳来跳去,收敛不到最值的情况,如图:

这里写图片描述

当然出现这种情况,其中一种解决方法是,将学习率 α α 设小一点,如0.0001。

这里介绍梯度裁剪(Gradient Clipping)的方法,对梯度进行裁剪,论文提出对梯度的L2范数进行裁剪,也就是所有参数偏导数的平方和再开方。

g1=J(w)w1 g 1 = ∂ J ( w ) ∂ w 1 g2=J(w)w2 g 2 = ∂ J ( w ) ∂ w 2 ,设定裁剪阈值为 c c g2=g12+g22

g2 ∥ g ∥ 2 大于 c c 时:

g=cg2g

g2 ∥ g ∥ 2 小于等于 c c 时:g不变。

其中, cg2 c ∥ g ∥ 2 是一个标量,大家有没有觉得这个跟学习率 α α 很类似?

TensorFlow代码

方法一:

optimizer = tf.train.AdamOptimizer(learning_rate=0.001, beta1=0.5)
grads = optimizer.compute_gradients(loss)
for i, (g, v) in enumerate(grads):
    if g is not None:
        grads[i] = (tf.clip_by_norm(g, 5), v)  # 阈值这里设为5
train_op = optimizer.apply_gradients(grads)

其中
optimizer.compute_gradients()返回的是正常计算的梯度,是一个包含(gradient, variable)的列表。

tf.clip_by_norm(t, clip_norm)返回裁剪过的梯度,维度跟t一样。

不过这里需要注意的是,这里范数的计算不是根据全局的梯度,而是一部分的。

方法二:

optimizer = tf.train.AdamOptimizer(learning_rate=0.001, beta1=0.5)
grads, variables = zip(*optimizer.compute_gradients(loss))
grads, global_norm = tf.clip_by_global_norm(grads, 5)
train_op = optimizer.apply_gradients(zip(grads, variables))

这里是计算全局范数,这才是标准的。不过缺点就是会慢一点,因为需要全部梯度计算完之后才能进行裁剪。

总结

当你训练模型出现Loss值出现跳动,一直不收敛时,除了设小学习率之外,梯度裁剪也是一个好方法。

然而这也说明,如果你的模型稳定而且会收敛,但是效果不佳时,那这就跟学习率和梯度爆炸没啥关系了。因此,学习率的设定和梯度裁剪的阈值并不能提高模型的准确率。

### 深度学习中梯度爆炸梯度消失的概念及解决方案 #### 一、梯度消失的原因及解决方案 在深度学习中,梯度消失是一个常见问题,特别是在处理深层神经网络时。当使用某些激活函数(如 sigmoid),由于其导数的最大值仅为 0.25,在反向传播过程中,随着层数增加,梯度会逐渐变小甚至接近于零[^5]。这使得权重更新变得极其缓慢,从而阻碍了模型的学习能力。 为了应对这一挑战,可以采取以下几种策略: 1. **更换激活函数** 使用 ReLU 或其他非饱和型激活函数替代传统的 sigmoid 和 tanh 函数。ReLU 的导数要么为 0 要么为 1,能够有效缓解梯度消失的问题[^3]。 2. **初始化技术改进** 应用合适的权重初始化方法,例如 Xavier 初始化或 He 初始化,有助于保持信号在整个网络传播过程中的稳定性,减少梯度消失的可能性。 3. **残差连接 (Residual Connections)** 利用跳跃连接结构(skip connections),允许梯度绕过一些层直接传递到更前面的层,显著改善了深网中的梯度流动情况。 ```python import tensorflow as tf from tensorflow.keras.layers import Dense, Activation model = tf.keras.Sequential([ Dense(64), Activation('relu') # 替代sigmoid以减轻梯度消失 ]) ``` --- #### 二、梯度爆炸的原因及解决方案 相对于梯度消失而言,梯度爆炸指的是在网络训练期间,参数的梯度过大而导致数值不稳定的现象。这种情况通常发生在循环神经网络(RNNs)或者非常深的前馈网络中,因为较长的时间跨度内的累积误差可能会被放大许多倍。 以下是几个有效的解决办法: 1. **梯度裁剪 (Gradient Clipping)** 设置一个最大范数值作为界限,一旦检测到当前批次下的梯度超过了这个范围,则按比例缩放整个梯度向量使其满足约束条件[^4]。这种方法简单高效,广泛应用于序列建模领域。 2. **权重正则化 (Weights Regularization)** 添加 L1/L2 正则项至目标函数里,通过对较大的权重施加惩罚来抑制极端值的增长趋势,间接达到控制梯度的目的。 3. **门控机制引入** 对于 RNN 类架构来说,采用 LSTM 或 GRU 这样的单元设计能很好地管理长期依赖关系并遏制潜在的梯度失控风险。 ```python optimizer = tf.keras.optimizers.SGD( clipvalue=0.5 # 实现梯度裁剪功能 ) lstm_model = tf.keras.models.Sequential() lstm_model.add(tf.keras.layers.LSTM(units=128)) # 引入LSTM单元规避梯度爆炸 ``` --- ### 总结 无论是梯度消失还是梯度爆炸,都属于优化难题范畴,严重影响模型性能提升效率。通过合理调整算法组件配置——包括但不限于选用恰当激活函数、实施科学合理的初始化手段以及运用先进的规范化措施等途径,均能在不同程度上克服上述障碍,推动深度学习项目顺利开展[^1][^2].
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

手撕机

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值