共计 1806 个字符,预计需要花费 5 分钟才能阅读完成。
数学原理
反向传播算法的核心在于通过链式法则计算损失函数对网络权重的梯度。假设我们有一个简单的全连接层,其输出可以表示为:

$$ z = Wx + b $$
其中,$W$ 是权重矩阵,$x$ 是输入,$b$ 是偏置项。损失函数 $L$ 对权重 $W$ 的梯度可以通过链式法则计算:
$$ \frac{\partial L}{\partial W} = \frac{\partial L}{\partial z} \cdot \frac{\partial z}{\partial W} $$
具体来说,$\frac{\partial L}{\partial z}$ 是上游梯度,而 $\frac{\partial z}{\partial W}$ 则是当前层的局部梯度。对于全连接层,局部梯度就是输入 $x$ 的转置:
$$ \frac{\partial z}{\partial W} = x^T $$
因此,权重的梯度更新公式为:
$$ \Delta W = -\eta \cdot \frac{\partial L}{\partial W} $$
其中,$\eta$ 是学习率。
优化器对比
- SGD(随机梯度下降):最基本的优化器,直接使用梯度乘以学习率更新权重。缺点是容易陷入局部最优,收敛速度慢。
$$ W_{t+1} = W_t – \eta \cdot \nabla L(W_t) $$
- Momentum:引入动量项,加速收敛并减少振荡。
$$ v_{t+1} = \gamma v_t + \eta \cdot \nabla L(W_t) $$
$$ W_{t+1} = W_t – v_{t+1} $$
- Adam:结合了动量和自适应学习率的优点,适合处理稀疏梯度。
$$ m_t = \beta_1 m_{t-1} + (1 – \beta_1) \nabla L(W_t) $$
$$ v_t = \beta_2 v_{t-1} + (1 – \beta_2) (\nabla L(W_t))^2 $$
$$ W_{t+1} = W_t – \eta \cdot \frac{m_t}{\sqrt{v_t} + \epsilon} $$
代码实现
以下是一个 PyTorch 实现自定义权重更新的示例:
import torch
import torch.nn as nn
import torch.optim as optim
class CustomOptimizer(optim.Optimizer):
def __init__(self, params, lr=0.01, momentum=0.9):
defaults = dict(lr=lr, momentum=momentum)
super(CustomOptimizer, self).__init__(params, defaults)
def step(self):
for group in self.param_groups:
for p in group['params']:
if p.grad is None:
continue
d_p = p.grad.data
if group['momentum'] != 0:
param_state = self.state[p]
if 'momentum_buffer' not in param_state:
buf = param_state['momentum_buffer'] = torch.zeros_like(p.data)
else:
buf = param_state['momentum_buffer']
buf.mul_(group['momentum']).add_(d_p)
d_p = buf
p.data.add_(-group['lr'], d_p)
避坑指南
- 梯度裁剪 :梯度爆炸时,可以通过裁剪梯度来控制更新幅度。经验阈值通常设置为 1.0 或 5.0。
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
-
批量归一化与权重初始化 :批量归一化可以减少对初始权重的依赖,但仍建议使用 Xavier 或 Kaiming 初始化。
-
学习率衰减 :可以按步衰减或余弦退火调整学习率,实践中余弦退火效果较好。
scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=100)
延伸思考
- 如何设计适应非凸损失函数的权重更新策略?
- 在联邦学习场景下权重更新需要哪些特殊处理?
- 如何利用二阶导数信息(如 Hessian 矩阵)优化权重更新?
通过理解反向传播中权重更新的数学原理和实现细节,我们可以更好地调试和优化神经网络的训练过程。
