可靠训练工程
训练工程让实验正确、可恢复、可比较、可复现。
学习目标
- 带动量 SGD 的断点恢复核对
- 只保存 model.state_dict 能精确续训吗?
- 说明:本例证明优化器状态的重要性,不承诺跨硬件或分布式训练完全确定。
为什么需要这个概念
训练工程将配置、数据版本、数值检查、日志、检查点和恢复流程组织成可追踪系统,并在正确性明确后优化吞吐与资源使用。
学习前需要掌握
背景与问题
长训练可能中断,实验也需要复查。只有权重而没有优化器、随机状态和数据进度,通常只能重新开始一个相近实验,不能保证接着原轨迹走。
概念定义
训练工程将配置、数据版本、数值检查、日志、检查点和恢复流程组织成可追踪系统,并在正确性明确后优化吞吐与资源使用。
直观理解
断点像游戏存档:只存角色位置而不存背包、任务进度和随机状态,继续游戏就可能发生不同结果。
核心原理
用于恢复的检查点通常包含模型、优化器、调度器、AMP scaler、当前进度、最佳指标及配置。随机采样还依赖 Python、NumPy、PyTorch 和设备随机状态,数据加载器或采样器进度也可能需要保存。
指标记录应带样本计数和步骤定义,非有限损失或梯度应及时暴露。保存时注意 state_dict 引用当前张量;如果把“最佳状态”仅留在内存,需深拷贝或立即序列化,避免后续训练继续改动它。
恢复一致性最好用“连续两步”和“第一步保存、恢复后第二步”比较。分布式算子、工作进程和设备差异仍可能带来不确定性,因此不要从设置 seed 就宣称所有环境位级复现。
数学表达
核心公式
训练工程将配置、数据版本、数值检查、日志、检查点和恢复流程组织成可追踪系统,并在正确性明确后优化吞吐与资源使用。
变量含义
Nbatch sizeD/H特征或隐藏维度
计算步骤
- 1第一步参数变为 0.9,动量 buffer 为 1。
- 2第二步方向为 0.9×1+1=1.9,参数变为 0.71。
- 3保存第一步的参数和优化器状态,恢复后重复第二步。
代码对应位置
示例 1带动量 SGD 的断点恢复核对的最小验证:使用完整构造输入核对带动量 SGD 的断点恢复核对,输出只表示本例计算。
变量解释
| 变量 | 含义 |
|---|---|
N | batch size |
D/H | 特征或隐藏维度 |
完整数值示例
带动量 SGD 的断点恢复核对
已知条件
- 参数初值 1,学习率 0.1,momentum=0.9
- 每步梯度固定为 1
计算步骤
- 第一步参数变为 0.9,动量 buffer 为 1。
- 第二步方向为 0.9×1+1=1.9,参数变为 0.71。
- 保存第一步的参数和优化器状态,恢复后重复第二步。
计算结果
连续与恢复路径均得到 0.7100。
处理前后对比
- 本例证明优化器状态的重要性,不承诺跨硬件或分布式训练完全确定。
带动量 SGD 的断点恢复核对
若只恢复参数 0.9 而没有动量,第二步只减去 0.1,会得到 0.8。代码通过内存序列化快照保存真正的第一步状态,避免被第二步覆盖。
真实任务还有数据顺序与随机增强,因此这个确定性例子只隔离优化器状态。需要精确续训时,应扩展到完整数据与随机状态检查。
计算与实现步骤
- 第一步参数变为 0.9,动量 buffer 为 1。
- 第二步方向为 0.9×1+1=1.9,参数变为 0.71。
- 保存第一步的参数和优化器状态,恢复后重复第二步。
代码实现
示例 1
带动量 SGD 的断点恢复核对的最小验证
example_01.py用途:使用完整构造输入核对带动量 SGD 的断点恢复核对,输出只表示本例计算。
import io
import torch
p = torch.nn.Parameter(torch.tensor(1.))
opt = torch.optim.SGD([p], lr=0.1, momentum=0.9)
p.grad = torch.ones_like(p)
opt.step()
buffer = io.BytesIO()
torch.save({"parameter": p.detach().clone(), "optimizer": opt.state_dict()}, buffer)
p.grad = torch.ones_like(p)
opt.step()
buffer.seek(0)
state = torch.load(buffer, weights_only=True)
q = torch.nn.Parameter(state["parameter"].clone())
resumed = torch.optim.SGD([q], lr=0.1, momentum=0.9)
resumed.load_state_dict(state["optimizer"])
q.grad = torch.ones_like(q)
resumed.step()
print(f"continuous={p.item():.4f} resumed={q.item():.4f}")代码解析
解析始终位于完整代码下方,并按实际代码段逐项对应。
输入数据与任务
使用完整构造输入核对带动量 SGD 的断点恢复核对,输出只表示本例计算。
Step 1 · 1–18 行
导入当前步骤需要的数值计算、预处理、模型或评价工具。依赖集中写在代码开头,便于复现。
import io
import torch
p = torch.nn.Parameter(torch.tensor(1.))
opt = torch.optim.SGD([p], lr=0.1, momentum=0.9)
p.grad = torch.ones_like(p)
opt.step()
buffer = io.BytesIO()
torch.save({"parameter": p.detach().clone(), "optimizer": opt.state_dict()}, buffer)
p.grad = torch.ones_like(p)
opt.step()
buffer.seek(0)
state = torch.load(buffer, weights_only=True)
q = torch.nn.Parameter(state["parameter"].clone())
resumed = torch.optim.SGD([q], lr=0.1, momentum=0.9)
resumed.load_state_dict(state["optimizer"])
q.grad = torch.ones_like(q)
resumed.step()
print(f"continuous={p.item():.4f} resumed={q.item():.4f}")预期输出或运行结果
continuous=0.7100 resumed=0.7100
常见错误 · 4 条
- 只保存最后模型
- 恢复漏 optimizer
- batch loss 平均有偏
- 只设一个 seed
实际应用
- 长训练中断恢复
- 记录可追溯实验与数值异常
常见错误
- 只保存最后模型
- 恢复漏 optimizer
- batch loss 平均有偏
- 只设一个 seed
常见问题
只保存 model.state_dict 能精确续训吗?
通常不能,优化器矩、调度位置、scaler 和随机数据进度都会影响后续更新;仅推理则通常不需要这些训练状态。
这个示例能说明什么边界?
本例证明优化器状态的重要性,不承诺跨硬件或分布式训练完全确定。
推荐学习资料
PyTorch Tutorials
从张量、数据加载、自动微分和网络训练逐步进入视觉、NLP、性能与部署。
PyTorch Contributors · PyTorch
资料笔记
pytorch/examples
提供视觉、文本、强化学习和分布式训练等 PyTorch 参考示例。
PyTorch · GitHub
仓库信息
运行和研究常见 PyTorch 模型示例
主要语言:Python包含数据集或实验需要额外环境