BatchNormalization 关于正则化、梯度弥散..

博客介绍了Batch normalization(BN),它通过mini - batch进行归一化,解决数据分布多元化不利于DNN训练的问题,在训练和推理阶段有不同处理方式,能加速收敛、正则化、减轻梯度弥散。还提到Learning rate因BN后数据状态更好可适当增大。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Batch normalization

要知道,数据分布太多元化并不利于DNN的训练。

BN的提出就是为了狙击这个问题。

出于whitening的代价太大了,BN采用了mini-batch进行normalization的方案。

用一个 N × C × H × W N\times C \times H \times W N×C×H×W的数据举栗:

在大小为 M ( M &lt; N ) M(M&lt;N) MM<N的batch之中,基于信道 C C C求均值、方差。

μ B ← 1 m ∑ i = 1 m x i \mu_B \leftarrow \frac{1}{m}\sum_{i=1}^mx_i μBm1i=1mxi

σ B 2 ← 1 m ∑ i = 1 m ( x i − μ B ) 2 \sigma_B^2 \leftarrow \frac{1}{m}\sum_{i=1}^m(x_i-\mu_B)^2 σB2m1i=1m(xiμB)2

x ^ i ← x i − μ B σ B 2 + ϵ \hat x_i \leftarrow \frac{x_i-\mu_B}{\sqrt{\sigma_B^2+\epsilon}} x^iσB2+ϵ xiμB

y i ← γ x ^ i + β y_i \leftarrow \gamma\hat x_i +\beta yiγx^i+β

x ^ i \hat x_i x^i就是减去均值,除去方差根的数据。

然后通过 γ , β \gamma,\beta γ,β 再学习得到新的数据 y i y_i yi

(没有 γ , β \gamma,\beta γ,β的话,所有数据都是一个分布,这样每层传递出的信息就被切断了。 γ , β \gamma,\beta γ,β的加入就是为了在「弥补信息损失」和「加速收敛」之间找到一个平衡点)

不过这是在training阶段,在inference阶段,是用training时候得到的均值和方差(经过小小处理)来对test-data进行归一化的(单纯线性变换一下了,很快):

x ^ = x − E [ x ] V a r [ x ] + ϵ \hat x = \frac{x-E[x]}{\sqrt{Var[x]+\epsilon}} x^=Var[x]+ϵ xE[x]

V a r [ x ] = m m − 1 E B [ σ B 2 ] , E [ x ] = E [ μ B ] Var[x]=\frac{m}{m-1}E_B[ \sigma_B^2],E[x]=E[\mu_B] Var[x]=m1mEB[σB2],E[x]=E[μB]

⬆️ V a r [ x ] , E [ x ] Var[x],E[x] Var[x],E[x]是整合了training期间各个 μ B , σ B 2 \mu_B,\sigma_B^2 μB,σB2得到的Ծ ̮ Ծ。

在BN的论文中,用了 s i g m o i d sigmoid sigmoid的激活函数,此举将数据大致固定在 s i g m o i d sigmoid sigmoid的线形区域,起到了加速收敛,正则化的作用。(why?)

个人理解:

​ 在 s i g m o i d sigmoid sigmoid的饱和区,bp的时候, s i g m o i d ′ ( ) sigmoid&#x27;() sigmoid()是非常小的(今天定个小目标,先给更新一丢丢),在线形区收敛速度自然会快。

​ 至于正则化,也是因为线性区的缘故:线性变换+线性变换+线性变换=线性变换(✧(σ๑˃̶̀ꇴ˂̶́)σ ),这样子出来的曲线就会不会东扭西扭,扭成麻花导致过拟合啦。

DNN在反向传播过程中有可能会出现梯度弥散,BN对这个则有奇效。

首先梯度弥散是如何造成的呢?

一个原因是激活函数可能陷入饱和区导致grad太小啦(上面说到的 s i g m o i d ′ ( ) sigmoid&#x27;() sigmoid()就是栗子)。

还有一个就是 W 1 W 2 W 3 … W1W2W3… W1W2W3,如果 W 1 &lt; 1 , W 2 &lt; 1 , W 3 &lt; 1 … W1&lt;1,W2&lt;1,W3&lt;1… W1<1,W2<1,W3<1,相乘直接就vanish咯。

BN应对第一个原因就是弯的给他掰直!(斜眼笑)

至于应对第二个原因, ∂ y ∂ x ^ = γ \frac{\partial y}{\partial\hat x}=\gamma x^y=γ ,不过我认为 γ \gamma γ没有这么猛吧(小声BB,待我跑个程序验证一下)。

应该是如Physcal所说的:

直观上来说,对于一个网络层:
I、 X X X大点, W W W肯定要小点。
​II、 X X X小点, W W W肯定要大点。
违反这两条,会让激活值处于函数边界,从而被自然选择淘汰掉(有点遗传算法的味道)。
​这是经典的大拇指规则(Rule of Thumb),由无数前辈的实验得到,似乎已经成了共识。
​normalize之后,各层的XX遭到了压制,并且向高斯分布中心进行数值收缩。
​进而,由 X X X影响到了 W W W W W W也向高斯分布中心进行数值收缩。
​这样, W 1 W 2 W 3 … … . W n W1W2W3…….Wn W1W2W3.Wn的衰减将会得到可观的减缓。
​这大概是Batch Normalization可以减轻使用ReLU的Gradient Vanish的直接原因。

这一点也可以拿来解释Dropout的正则化作用,Dropout会暂时屏蔽一些单元,然后对保留单元做一个放大(比如说,屏蔽了1/3的单元,就将保留单元放大3/2), X X X的变大会引起 W ( a l i v e ) W(alive) Walive的减小,从而压制了 W W W

不过梯度衰减这点,inception V3那篇论文说可能人们把它misplace了。。Ծ‸Ծ

Learning rate

Learning rate 是可以更大了,但也不是超级大,不然还是会摆过头的。

learning rate可以更大的原因个人认为是:因为BN后数据处于一个更为健康的状态(身体好,孩子吃饭又快又香),可以用更大的学习率,更少的梯度更新次数。这点知乎网友纳米酱说的比较nice。

Reference:

Ioffe S, Szegedy C. Batch normalization: Accelerating deep network training by reducing internal covariate shift[J]. arXiv preprint arXiv:1502.03167, 2015.

http://www.cnblogs.com/neopenx/p/5211969.html

https://www.zhihu.com/question/38102762/answer/84238772

<think>首先,用户的问题是:“我想了解深度学习中梯度爆炸的表现及可能的解决方案请问深度学习梯度爆炸表现如何解决”。这是一个关于深度学习的问题,具体关注梯度爆炸的表现和解决方案。我需要参考提供的引用。引用[1]、[2]、[3]、[4]都涉及梯度消失和梯度爆炸。用户的问题只提到梯度爆炸,所以我会专注于那个部分,但可能简要提及梯度消失作为对比,因为两者经常一起讨论。引用内容总结:-引用[1]:讨论梯度爆炸的解决方案,包括原理解释、方法汇总、代码实践等。-引用[2]:解释梯度消失和梯度爆炸的底层真相及解决方案,如BN和残差网络。-引用[3]:在Python中实践解决梯度消失和梯度爆炸。-引用[4]:定义梯度弥散梯度消失)和梯度爆炸,强调激活函数的饱和导致梯度消失。用户的问题关键点:-梯度爆炸的表现(症状)。-如何解决梯度爆炸。我的回答需要:-使用中文。-结构清晰,逐步解决问题。-保证真实可靠。-在回答中引用段落末尾添加引用标识。-使用$...$forinlinemath,$$...$$forblockmath.-生成相关问题。回答结构:1.**介绍梯度爆炸**:简要解释什么是梯度爆炸。2.**表现(症状)**:描述梯度爆炸的典型症状。3.**原因**:简要解释为什么会发生梯度爆炸。4.**解决方案**:列出并详细说明可能的解决方案。5.**代码示例**:如果适用,提供代码片段(使用PyTorch,如引用[1]中提到)。6.**总结**:给出实战建议。7.**生成相关问题**:在末尾添加相关问题。确保LaTeX语法正确:-Inlinemath:如$gradient$,$W$forweights.-Blockmath:如用于反向传播公式。引用标识:-在引用段落末尾添加[^数字],匹配提供的引用。例如,如果引用引用[1],添加[^1]。现在,构建回答:-**开头**:直接回答用户问题。-**表现**:从引用[1]和[^4],梯度爆炸的典型症状包括:损失值剧烈波动、权重更新过大、NaN值出现。-**原因**:梯度爆炸通常由于深度网络中的链式法则,导致梯度指数级增长。-**解决方案**:从引用[1]、[^2]、[^3]、[^4],解决方案包括:梯度裁剪、权重初始化、使用适当的激活函数、批量归一化(BatchNormalization)、残差网络(ResNet)、学习率调整等。-**代码示例**:提供PyTorch代码,如梯度裁剪的实现。-**结尾**:总结并生成相关问题。生成相关问题:-基于主题,如梯度爆炸的其他方面、相关概念、实践建议。最终回答框架:1.引言:解释梯度爆炸。2.表现:列出症状。3.解决方案:详细说明方法。4.代码实践:PyTorch示例。5.总结。6.相关问题。</think>### 深度学习中的梯度爆炸:表现与解决方案 在深度学习中,梯度爆炸(Gradient Explosion)是指在反向传播过程中,梯度值急剧增大到异常高的水平,导致模型训练不稳定甚至失败的现象。它与梯度消失(Gradient Vanishing)同为深度神经网络中的常见问题,但表现和应对策略有所不同。下面我将从表现、原因、解决方案及代码实践等方面,逐步为您解答。回答基于深度学习理论和实践经验,确保真实可靠。 --- #### 1. **梯度爆炸的表现(症状)** 梯度爆炸在训练过程中会表现出明显的异常现象,主要包括: - **损失值剧烈波动**:损失函数(如交叉熵或均方误差)在训练过程中出现突然的跳跃或发散,例如损失值从正常范围(如0.5)猛增至数千或NaN(Not a Number)[^1]。 - **权重更新过大**:模型权重在更新时幅度异常大,导致参数值溢出(如变为无穷大或NaN)。数学上,如果梯度范数 $\|\nabla L\|$ 超过阈值(如1000),即可视为爆炸[^1][^4]。 - **训练不稳定**:模型收敛困难,训练曲线出现锯齿状波动,或提前终止(例如因数值错误而崩溃)[^2]。 - **输出异常**:预测结果出现无效值(如NaN),或在测试阶段表现急剧下降[^3]。 梯度爆炸的根源在于深度网络中的链式求导:反向传播时,梯度通过多层网络逐层相乘。如果权重矩阵 $W$ 的特征值大于1,梯度会指数级增长($\nabla L \propto \prod_{i=1}^n W_i$),最终失控[^2][^4]。这与梯度消失(梯度趋近0)形成对比,后者通常由激活函数饱和引起。 --- #### 2. **梯度爆炸的解决方案** 解决梯度爆炸需要综合策略,以下从易到难列出常见方法(共8大类),并附PyTorch代码示例。这些方法在实践中已被证明有效[^1][^2][^3]。 ##### **2.1 梯度裁剪(Gradient Clipping)** 最简单且高效的方案,通过限制梯度范数防止更新幅度过大。PyTorch中可轻松实现: ```python import torch import torch.nn as nn # 定义模型和优化器 model = nn.Linear(10, 1) optimizer = torch.optim.SGD(model.parameters(), lr=0.01) # 训练循环中应用梯度裁剪 for inputs, targets in dataloader: outputs = model(inputs) loss = nn.MSELoss()(outputs, targets) loss.backward() # 梯度裁剪:限制最大范数为1.0 torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0) optimizer.step() optimizer.zero_grad() ``` - **原理**:强制 $\|\nabla L\| \leq \text{max\_norm}$,避免权重爆炸[^1]。 - **优点**:实现简单,计算开销小,适用于大多数场景。 ##### **2.2 权重初始化(Weight Initialization)** 合理的初始化可控制梯度传播。推荐使用: - **Xavier初始化**:适用于Sigmoid/Tanh激活函数,初始化权重 $W \sim \mathcal{U}(-\frac{\sqrt{6}}{\sqrt{n_{\text{in}} + n_{\text{out}}}}, \frac{\sqrt{6}}{\sqrt{n_{\text{in}} + n_{\text{out}}}})$,其中 $n_{\text{in}}$ 和 $n_{\text{out}}$ 为输入输出维度[^3]。 - **He初始化**:适用于ReLU激活函数,$W \sim \mathcal{N}(0, \sqrt{\frac{2}{n_{\text{in}}}})$。 在PyTorch中自动应用: ```python nn.Linear(10, 1, bias=True) # 默认使用Kaiming(He)初始化 ``` ##### **2.3 激活函数选择** 避免饱和激活函数(如Sigmoid),改用: - **ReLU及其变体**:如Leaky ReLU($f(x) = \max(0.01x, x)$)或ELU,减少梯度累积风险[^2][^4]。 - **数学优势**:ReLU的导数在正区间恒为1,防止梯度指数增长。 ##### **2.4 批量归一化(Batch Normalization, BN)** 在每层输入前添加BN层,稳定梯度分布: ```python class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.fc1 = nn.Linear(10, 20) self.bn1 = nn.BatchNorm1d(20) # 添加BN层 self.fc2 = nn.Linear(20, 1) def forward(self, x): x = torch.relu(self.bn1(self.fc1(x))) x = self.fc2(x) return x ``` - **原理**:BN通过归一化输入($\hat{x} = \frac{x - \mu}{\sigma}$)减少内部协变量偏移,使梯度更平滑[^2][^3]。 ##### **2.5 残差网络(ResNet)** 引入跳跃连接(Skip Connections),缓解深度网络的梯度问题: ```python class ResidualBlock(nn.Module): def __init__(self, in_features): super(ResidualBlock, self).__init__() self.fc = nn.Linear(in_features, in_features) def forward(self, x): residual = x x = torch.relu(self.fc(x)) x += residual # 跳跃连接 return x ``` - **数学形式**:$y = f(x) + x$,确保梯度有直接路径回传,避免累积[^2]。 ##### **2.6 学习率调整** 降低学习率(Learning Rate)或使用自适应优化器: - **Adam优化器**:自动调整学习率,减少爆炸风险。 - **学习率预热(Warmup)**:训练初期逐步增加学习率。 ##### **2.7 正则化技术** 添加L2正则化(权重衰减)约束权重幅度: ```python optimizer = torch.optim.Adam(model.parameters(), lr=0.001, weight_decay=1e-5) # weight_decay即L2系数 ``` ##### **2.8 网络架构优化** - **减少网络深度**:在浅层网络中问题较轻。 - **使用门控机制**:如LSTM/GRU,在RNN中控制梯度流动[^3]。 --- #### 3. **调试与实战建议** - **检测梯度爆炸**:在训练中监控梯度范数: ```python total_norm = torch.norm(torch.stack([torch.norm(p.grad) for p in model.parameters() if p.grad is not None])) print(f"Gradient Norm: {total_norm.item()}") ``` 若范数持续 >100,可能发生爆炸[^1]。 - **综合策略**:优先梯度裁剪+BN+合理初始化,覆盖90%场景。残差网络适用于极深模型(如ResNet-50)[^2]。 - **注意事项**:梯度爆炸常与不当超参(如过高学习率)相关,需结合交叉验证调优。 --- #### 总结 梯度爆炸表现为损失波动、权重溢出等,主要由链式求导中的指数增长引起。通过梯度裁剪、权重初始化、BN等方法可有效控制。在实践中,梯度裁剪是首选快速方案,而BN和ResNet提供深度鲁棒性。稳定训练后,模型能更好地收敛和泛化[^1][^2][^3]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值