跳到主要内容

11 · 训练实战:让长训练不翻车

1. 这一章讲什么

前面各章的技术都是「零件」,原书第 11 章把它们装配成一条训练流水线:数据预处理与分词的细节、多 GPU/多节点的启动配置、训练过程的监控与中间结果保存、中断与恢复机制1。导语里最有分量的是最后半句——「保障训练不受突发事件影响」:真实训练以天计,中途断电、抢卡、OOM 是常态,不能从头再来。

这一章与 12 章构成全书落点:一个讲「训练怎么守护」,一个讲「微调怎么落地」。

2. 顶层全景:流水线五站

原始语料
│ ① 清洗 → 去重 → 切分 → 标注

│ ② 分词器:BERT=WordPiece / GPT-2=BPE → input_ids + attention_mask

│ ③ 启动:每卡一个进程(Rank 0,1,…)、gloo/NCCL 通信、DistributedSampler 分数据

│ ④ 监控:TensorBoard 记曲线;每 10 个 epoch 存检查点

│ ⑤ 中断 → 找最近检查点 → 载入模型+优化器状态 → 接着跑

测试集评估(Test Accuracy 89.15%)

3. 核心原理

3.1 数据站:四道工序的规模化版本

06 章的清洗在「大规模」语境下多了两条硬要求。去重:书里的做法是把数据转成集合形式,完全相同的文本只留一条——set(cleaned_data) 一行搞定2切分:长文本要切成短片段才进得了模型的输入窗口,按句子或按固定长度切3标注:分类任务用简单规则映射打标签(「Machine learning…」→Technology)4

分词器这一站没有新机制,但有选型知识:BERT 用 WordPiece(子词单元,「unbelievable」拆成「un + believ + able」式的块),GPT-2 用 BPE(06 章讲过的字对合并),两者都返回编号串,再配一个 attention_mask 标出哪些位置是真实词、哪些是填充5——填充是为了让一个批次里的句子等长,mask 告诉模型「填充部分别看」。

3.2 启动站:DDP 的启动清单

07 章讲了 DDP 的原理,这一章给启动清单:每张卡起一个进程(编号 Rank 0、Rank 1……),init_process_group 建通信组,原书示例用 gloo 后端并注明 GPU 环境推荐 NCCL6;多节点(多台机器)则要配置主节点的 IP 和端口,让节点间能互相通信7

主走查:一次 10-epoch 分布式训练的账。 原书输出的读法:

Rank 0, Epoch [1/10], Step [1/16], Loss: 1.2345
Rank 1, Epoch [1/10], Step [1/16], Loss: 1.3456 ← 两个进程各自的损失

Rank 0, Epoch [10/10], Step [16/16], Loss: 0.2345 ← 两卡都从 1.2+ 降到 0.2-0.3
Rank 1, Epoch [10/10], Step [16/16], Loss: 0.3456

走查说明:三件事从输出里可读出——①Rank 是进程编号,两个 Rank 各跑各的批次8;②Step 上限 16 是每卡每 epoch 要喂的份数,总吞吐(单位时间处理量)=单卡×卡数;③两卡损失同步下降且数值接近,说明梯度同步在正常工作(各卡模型保持一致)。哪个 Rank 的损失突然发散,分布式的排查就从那一行开始。

3.3 监控站:曲线+存档双保险

长时间训练最怕两件事:跑歪了没人知道、断了没法续。监控靠 TensorBoard:每个 epoch 把损失写进 SummaryWriter,训练曲线实时可看9。存档靠检查点:每 save_interval(原书设 10)个 epoch,把「模型状态+优化器状态+损失值」整套存盘10

注意检查点存的是三样而不是一样:只存模型权重,重启后优化器的动量记忆、当前学习率就全丢了——等于换了个「失忆的模型」继续跑,收敛行为会变形。原书明确列了三样10

3.4 恢复站:断点续训

中断恢复的流程原书拆成两段:训练时每 10 个 epoch 落一个 .pth 检查点文件;中断后从指定检查点加载模型与优化器状态,从断开的 epoch 继续跑11。原书的演示输出把衔接处拍得很实:第一次训练到 Epoch 10(损失 0.4208)存档;恢复时打印「starting from epoch 10 with loss 0.4208」,随后 Epoch 11 损失 0.4103——比存档点还低,证明恢复接得无缝12

3.5 综合案例:五站串成一条线

原书 11.5 用 IMDB 影评分类把五站全走一遍:预处理+分词 → 多 GPU 分布式设置 → TensorBoard+检查点 → 中断恢复 → 测试集 89.15%13。案例的价值不在数字,在于展示了「每一站都有现成接口」:数据站是 datasets+tokenizer,启动站是 DDP 的模板代码,监控站是 SummaryWriter+save_interval,恢复站是一个 resume_training 函数14

4. 作者的判断与证据

  • 有演示数据的: DDP 两 Rank 的十个 epoch 损失(11.2)、检查点保存/恢复的衔接输出(11.3/11.4)、综合案例 89.15%(11.5)。
  • 是作者判断的: 「中断对模型收敛的潜在影响与应对策略」——导语许诺了这个话题,正文实际只演示了「能恢复」,没有讨论「恢复后的收敛轨迹是否与不中断时相同」这类实质问题。
  • 是书里坦白的: 综合案例的部分代码块在书里以图片呈现,正文只保留关键函数(如 resume_training)的文本。

5. 边界与局限

  • 去重只讲了 set() 精确去重;大规模文本真正难的是近似去重(换皮重复),书里没有覆盖——这是它与真实预训练数据工程之间最大的缺口。
  • 监控只记了损失一个指标;真实训练还要盯学习率曲线、梯度范数、验证集困惑度等,书里没有展开。
  • 多节点部分停在「配置主节点 IP 和端口」,没有讲节点间带宽(网线一次能运多少数据)、拓扑、容错——多机训练最难的地方恰恰在这里。
  • 「大规模」的演示规模其实很小(示例模型+玩具数据);流程是真的,规模感是假的,读时要有这根弦。

6. 可带走的

  1. 训练流水线五站:清洗去重切分标注 → 分词 → DDP 启动 → 监控存档 → 断点续训;每一站都有模板代码。
  2. 检查点必须存三样:模型状态、优化器状态、损失值;只存权重等于让模型失忆。
  3. attention_mask 和 padding 成对出现:填充为了等长,mask 为了「填充别看」。
  4. DDP 输出按 Rank 读:各 Rank 损失接近且同步下降=同步正常;发散=先查那一路。
  5. 断点续训的验收标准:恢复后的第一个 epoch 损失应低于存档点(衔接无缝的旁证)。
  6. 「中断影响收敛」是个真问题,但原书没答;重要训练自己留对照(同一配置中断 vs 不中断)。
  7. 训练曲线要看的不止 loss:学习率、梯度范数一起记,排查才有线索。

7. 原文地图

主题原书章原文位置
章导语第11章text/68-ch11.txt:24(搜「数据预处理与Tokenization」)
清洗去重切分标注11.1text/69-fm.txt:33(搜「清洗、去重、切分和标注」) · text/69-fm.txt:54(搜「set(cleaned_data)」) · text/69-fm.txt:79(搜「切分成更短的片段」) · text/69-fm.txt:88(搜「简单的规则或映射来标注」)
WordPiece vs BPE、掩码11.1text/69-fm.txt:220(搜「WordPiece」) · text/69-fm.txt:223(搜「基于BPE的分词方法」) · text/69-fm.txt:238(搜「填充位置」)
DDP 设置与后端11.2text/70-fm.txt:24(搜「Distributed Data Parallel,DDP」) · text/70-fm.txt:98(搜「NCCL」) · text/70-fm.txt:58(搜「主节点的IP地址和端口」)
Rank 与分布式输出11.2text/70-fm.txt:147(搜「Rank表示进程编号」) · text/70-fm.txt:116(搜「Rank 0, Epoch [1/10]」)
监控与检查点三样11.3text/71-fm.txt:24(搜「监控和中间结果的保存至关重要」) · text/71-fm.txt:135(搜「优化器状态以及损失值」) · text/71-fm.txt:171(搜「每10个epoch保存一次检查点」)
断点续训11.4text/72-fm.txt:24(搜「从最后保存的检查点继续训练」) · text/72-fm.txt:97(搜「model_epoch_10.pth」)
IMDB 综合案例11.5text/73-fm.txt:1(搜「IMDB文本分类训练全流程」) · text/73-fm.txt:103(搜「resume_training」) · text/73-fm.txt:164(搜「89.15%」)

Footnotes

  1. 出处:「第11章 模型训练实战」第 24 段(text/68-ch11.txt:24,搜「数据预处理与Tokenization」)。

  2. 出处:「11.1 数据预处理与Tokenization细节」第 49-51 段(text/69-fm.txt:48,搜「重复项」;text/69-fm.txt:54,搜「set(cleaned_data)」)。

  3. 出处:「11.1 数据预处理与Tokenization细节」第 77-79 段(text/69-fm.txt:79,搜「切分成更短的片段」)。

  4. 出处:「11.1 数据预处理与Tokenization细节」第 85-87 段(text/69-fm.txt:88,搜「简单的规则或映射来标注」)。

  5. 出处:「11.1 数据预处理与Tokenization细节」第 220-223 与 238 段(text/69-fm.txt:220,搜「WordPiece」;text/69-fm.txt:223,搜「基于BPE的分词方法」;text/69-fm.txt:238,搜「填充位置」)。

  6. 出处:「11.2 大规模预训练模型的设置与启动」第 96-98 段(text/70-fm.txt:79,搜「gloo」;text/70-fm.txt:98,搜「NCCL」)。

  7. 出处:「11.2 大规模预训练模型的设置与启动」第 58-59 段(text/70-fm.txt:58,搜「主节点的IP地址和端口」)。

  8. 出处:「11.2 大规模预训练模型的设置与启动」第 147 段(text/70-fm.txt:147,搜「Rank表示进程编号」)。

  9. 出处:「11.3 预训练过程中的监控与中间结果保存」第 24 与 139 段(text/71-fm.txt:24,搜「监控和中间结果的保存至关重要」;text/71-fm.txt:138,搜「TensorBoard记录」)。

  10. 出处:「11.3 预训练过程中的监控与中间结果保存」第 135 与 171 段(text/71-fm.txt:135,搜「优化器状态以及损失值」;text/71-fm.txt:171,搜「每10个epoch保存一次检查点」)。 2

  11. 出处:「11.4 训练中断与恢复机制」第 24 与 138-141 段(text/72-fm.txt:24,搜「从最后保存的检查点继续训练」;text/72-fm.txt:138,搜「中断保存与恢复机制」)。

  12. 出处:「11.4 训练中断与恢复机制」第 113-121 段(text/72-fm.txt:97,搜「model_epoch_10.pth」)。

  13. 出处:「11.5 综合案例:IMDB文本分类训练全流程」第 24 与 165 段(text/73-fm.txt:1,搜「IMDB文本分类训练全流程」;text/73-fm.txt:164,搜「89.15%」)。

  14. 出处:「11.5 综合案例:IMDB文本分类训练全流程」第 103-121 段(text/73-fm.txt:103,搜「resume_training」)。