Dive-into-DL-PyTorch项目解析:深入理解小批量随机梯度下降
引言
在深度学习模型训练过程中,优化算法的选择直接影响着模型的收敛速度和最终性能。本文将深入探讨小批量随机梯度下降(Mini-batch Stochastic Gradient Descent)这一核心优化算法,帮助读者理解其原理、实现方式以及实际应用中的注意事项。
梯度下降算法家族概述
在深度学习中,梯度下降算法主要有三种变体:
- 批量梯度下降(Batch Gradient Descent):每次使用全部训练数据计算梯度
- 随机梯度下降(Stochastic Gradient Descent):每次随机使用单个样本计算梯度
- 小批量随机梯度下降(Mini-batch SGD):折中方案,每次使用一个小批量样本计算梯度
这三种方法各有优缺点,而小批量随机梯度下降因其优异的综合性能成为深度学习中最常用的优化算法。
小批量随机梯度下降的数学原理
给定目标函数$f(\boldsymbol{x}): \mathbb{R}^d \rightarrow \mathbb{R}$,小批量随机梯度下降的更新过程如下:
- 随机均匀采样一个小批量$\mathcal{B}_t$
- 计算小批量梯度: $$\boldsymbol{g}t \leftarrow \nabla f{\mathcal{B}t}(\boldsymbol{x}{t-1}) = \frac{1}{|\mathcal{B}|} \sum_{i \in \mathcal{B}t}\nabla f_i(\boldsymbol{x}{t-1})$$
- 更新参数: $$\boldsymbol{x}t \leftarrow \boldsymbol{x}{t-1} - \eta_t \boldsymbol{g}_t$$
其中$\eta_t$为学习率,$|\mathcal{B}|$为批量大小。
关键特性分析
- 无偏估计:小批量梯度$\boldsymbol{g}t$是真实梯度$\nabla f(\boldsymbol{x}{t-1})$的无偏估计
- 计算效率:每次迭代的计算复杂度为$\mathcal{O}(|\mathcal{B}|)$
- 学习率衰减:实践中常采用学习率衰减策略,如$\eta_t=\eta t^\alpha$或$\eta_t = \eta \alpha^t$
批量大小的选择策略
批量大小是影响算法性能的关键超参数:
| 批量大小 | 优点 | 缺点 | |---------|------|------| | 小 (如1) | 更新频繁,收敛快 | 方差大,难以并行化 | | 中 (如32-256) | 平衡收敛速度和稳定性 | 需要调参 | | 大 (如全数据集) | 稳定,可并行化 | 计算开销大,易陷入局部最优 |
实际案例:飞机机翼噪音预测
我们使用NASA提供的飞机机翼噪音数据集来比较不同批量大小的效果。该数据集包含1500个样本,每个样本有5个特征。
数据预处理
def get_data_ch7():
data = np.genfromtxt('airfoil_self_noise.dat', delimiter='\t')
data = (data - data.mean(axis=0)) / data.std(axis=0) # 标准化
return torch.tensor(data[:1500, :-1], dtype=torch.float32), \
torch.tensor(data[:1500, -1], dtype=torch.float32)
从零开始实现
我们实现了一个通用的SGD优化器:
def sgd(params, states, hyperparams):
for p in params:
p.data -= hyperparams['lr'] * p.grad.data
以及训练函数:
def train_ch7(optimizer_fn, states, hyperparams, features, labels,
batch_size=10, num_epochs=2):
# 初始化模型和参数
w = torch.nn.Parameter(...)
b = torch.nn.Parameter(...)
# 训练循环
for epoch in range(num_epochs):
for X, y in data_iter: # 小批量迭代
l = loss(net(X, w, b), y).mean()
l.backward()
optimizer_fn([w, b], states, hyperparams)
# 清零梯度
实验结果对比
-
批量大小=1500(梯度下降):
- 每个epoch只更新一次参数
- 收敛平稳但速度较慢
-
批量大小=1(随机梯度下降):
- 更新频繁,初期收敛快
- 后期波动较大
-
批量大小=10(小批量SGD):
- 平衡了收敛速度和稳定性
- 实际效果最佳
PyTorch简洁实现
PyTorch提供了优化器的封装,使实现更加简洁:
def train_pytorch_ch7(optimizer_fn, optimizer_hyperparams, features, labels,
batch_size=10, num_epochs=2):
net = nn.Sequential(nn.Linear(features.shape[-1], 1))
optimizer = optimizer_fn(net.parameters(), **optimizer_hyperparams)
for epoch in range(num_epochs):
for X, y in data_iter:
optimizer.zero_grad()
l = loss(net(X).view(-1), y) / 2
l.backward()
optimizer.step()
实践建议
- 批量大小选择:通常从32或64开始尝试,根据硬件条件调整
- 学习率调整:批量增大时,可适当增大学习率
- 学习率衰减:可采用步进衰减或余弦退火等策略
- 监控训练:观察训练曲线,判断是否需要调整超参数
总结
小批量随机梯度下降通过平衡计算效率和收敛稳定性,成为深度学习中的主流优化算法。理解其数学原理和实现细节,有助于在实际项目中更好地应用和调试模型。通过调整批量大小和学习率等超参数,可以在不同场景下获得最佳的训练效果。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考