1、Checkpoint 基础概念:什么是 Checkpoint?为什么需要它?
大家好,我是你们这门课的主讲。今天咱们正式开篇,聊聊 Checkpoint 最基础的东西。
说实话,我刚开始做深度学习那会儿,对 Checkpoint 的理解特别肤浅。就觉得它是个“存档点”,跟打游戏存档差不多。后来在分布式训练上栽了几个跟头,才真正明白——Checkpoint 不是可有可无的附属品,它是整个训练流程的“安全绳”。
1.1 什么是 Checkpoint?
用一句话说:Checkpoint 就是把模型在某个训练时刻的“快照”完整保存下来。
这个快照里有什么?我列个清单给你看:
- 模型参数(权重、偏置)—— 模型学到的知识
- 优化器状态(动量、学习率调度器位置)—— 训练继续的“惯性”
- 当前 epoch / step 编号—— 训练进度标记
- 损失值、评估指标—— 模型当前表现
- 随机数生成器状态—— 保证可复现性
说白了,Checkpoint 就是一个“训练现场的全息备份”。有了它,你可以随时把训练恢复到某个时间点,继续往下跑。
核心理解:Checkpoint ≠ 模型权重文件。模型权重只保存了参数,而 Checkpoint 保存的是“训练上下文”。少了优化器状态,你恢复训练时学习率曲线会断掉,动量会清零,效果大打折扣。
1.2 为什么需要 Checkpoint?
这个问题,我分三个层面来讲。
1.2.1 防崩溃 —— 训练容错的最后一道防线
你想想看,一个大型模型训练,动不动就是几天甚至几周。GPU 集群上跑着跑着,突然节点挂了、网络断了、机房断电了……没有 Checkpoint,前面所有算力投入全部归零。
我记得有一次,团队训练一个 70B 参数的模型,跑了整整 6 天。第 6 天晚上,一个 GPU 节点因为散热故障宕机了。幸好我们每 30 分钟写一次 Checkpoint,最后只损失了 20 分钟的训练进度。要是没这个习惯……嗯,那周就白干了。
避坑指南:我曾经见过有人只在每个 epoch 结束时保存一次 Checkpoint。一个 epoch 跑 8 小时,中间挂了就丢 8 小时。我的建议是:按时间间隔保存,而不是按 epoch 保存。比如每 15 分钟写一次,这样最大损失可控。
1.2.2 调优与回溯 —— 找到“最佳状态”
训练过程中,模型性能不是一直上升的。过拟合、学习率衰减过快、梯度爆炸……各种问题都会导致模型在某个点之后反而变差。
有了 Checkpoint,你可以:
- 在验证集上监控性能,自动保存最佳模型(Early Stopping 的搭档)
- 训练结束后,回退到性能最好的那个 Checkpoint
- 对比不同阶段的 Checkpoint,分析模型学到了什么
我个人的习惯是:同时保存“最近 N 个 Checkpoint”和“验证集最佳 Checkpoint”。前者用于容错恢复,后者用于最终选型。
1.2.3 分布式训练的“粘合剂”
这一点,是很多初学者容易忽略的。在分布式训练中,多个 GPU 甚至多台机器协同工作。如果某个 worker 挂了,整个集群都得等它恢复。Checkpoint 在这里扮演了“同步点”的角色。
具体来说:
- Allreduce 同步:所有 worker 在 Checkpoint 时刻同步梯度,保证模型状态一致
- 故障恢复:某个节点挂了,新节点从最近的 Checkpoint 加载,其他节点回滚到同一状态
- 弹性训练:动态增减节点时,Checkpoint 是重新分配任务的基准
小技巧:在分布式场景下,我建议把 Checkpoint 保存到共享存储(如 NFS、Ceph、S3)上,而不是本地磁盘。否则节点挂了,它的本地 Checkpoint 也丢了,等于白存。
1.3 Checkpoint 在深度学习中的角色
我用一张图来概括 Checkpoint 在整个训练流程中的位置:
从这张图你能看到,Checkpoint 不是训练流程的“附属品”,而是连接各个关键环节的枢纽。它同时服务于:
- 容错恢复:训练崩溃后快速回滚
- 最佳模型选择:从多个 Checkpoint 中挑出最优
- 分布式同步:多节点训练的协调基准
1.4 一个简单的 Checkpoint 示例
光说不练假把式。我写个最简单的 PyTorch Checkpoint 保存和加载代码,让你直观感受一下:
import torch
import torch.nn as nn
# 假设我们有一个简单的模型
model = nn.Linear(10, 2)
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
# 模拟训练了 5 个 epoch
for epoch in range(5):
# ... 训练代码 ...
loss = 0.5 # 假设的损失值
# 保存 Checkpoint
checkpoint = {
'epoch': epoch,
'model_state_dict': model.state_dict(),
'optimizer_state_dict': optimizer.state_dict(),
'loss': loss,
}
torch.save(checkpoint, f'checkpoint_epoch_{epoch}.pt')
print(f"已保存 epoch {epoch} 的 Checkpoint")
# 加载 Checkpoint
checkpoint = torch.load('checkpoint_epoch_3.pt')
model.load_state_dict(checkpoint['model_state_dict'])
optimizer.load_state_dict(checkpoint['optimizer_state_dict'])
start_epoch = checkpoint['epoch'] + 1
print(f"从 epoch {start_epoch} 继续训练")
注意:实际项目中,Checkpoint 还会包含学习率调度器状态、梯度裁剪参数、数据加载器状态等。但核心骨架就是上面这样——一个字典,包含所有需要恢复训练的信息。
1.5 本章小结
好了,第一节课的内容就这些。我帮你梳理一下核心要点:
| 概念 | 核心理解 |
|---|---|
| Checkpoint 是什么 | 训练过程的完整快照,包含模型参数、优化器状态、训练进度等 |
| 为什么需要 | 容错恢复、最佳模型回溯、分布式训练协调 |
| 在训练中的角色 | 连接训练、评估、容错、选型和分布式协调的枢纽 |
| 保存频率建议 | 按时间间隔(如 15 分钟)而非按 epoch 保存 |