跳转至

从零构建 LLM 七阶段实战教程

Ch01.878 从零构建 LLM 七阶段实战教程

📊 Level ⭐⭐⭐ | 8.6KB | entities/llm-from-scratch-7-stage-pytorch-tutorial.md

核心框架:七阶段构建计划

阶段 内容 关键产出
Stage 1 数据准备 + 注意力机制 分词器、token 嵌入、位置编码
Stage 2 构建 LLM + 预训练 1.63 亿参数模型、困惑度从 48,725 → 0.39
Stage 3 微调(分类 + 指令) 分类准确率 95.67%、Alpaca 格式指令微调

Stage 1:数据预处理

BPE(Byte Pair Encoding,分词算法)

GPT-2 采用 Byte Pair Encoding,词汇表 50,257 个 token。核心优势:永不遇到 unknown token——任何词都可以拆成子词甚至单个字符。

# GPT-2 BPE 词汇表大小
VOCAB_SIZE = 50257

词嵌入 + 位置编码

  • GPT-2 Small 嵌入维度:768
  • GPT-3 最大版:12,288
  • 位置编码:可训练的位置嵌入,直接加到 token 嵌入上

滑动窗口制造训练数据

stride=1 时,输入 [1,2,3] → 输出 [2,3,4],从一篇短篇小说可造出海量的训练样本对。

Stage 2:GPT 架构实现

GPT-2 Small 配置(1.24 亿参数)

参数
词汇量 50,257
上下文长度 1,024
嵌入维度 768
注意力头数 12(每头 64 维)
Transformer 层数 12
Dropout 0.1
参数量 1.63 亿(621 MB @ float32)

Transformer Block 结构(Pre-LayerNorm)

LayerNorm → Multi-Head Attention → Dropout → Shortcut
LayerNorm → FeedForward → Dropout → Shortcut
关键设计:

  • Pre-LayerNorm:先归一化再进子层,比 Post-LayerNorm 训练更稳定
  • GELU 激活:比 ReLU 温柔,负数区域也保留非零梯度
  • Shortcut(残差连接):给梯度修"高速公路",无 shortcut 时第一层比第五层梯度小 25 倍
  • FeedForward:Linear(768 → 3072) → GELU → Linear(3072 → 768),先扩大 4 倍再缩小

因果注意力(不许"开天眼")

在注意力权重矩阵右上角加一个上三角掩码(softmax 前设为 -inf),确保预测第 N 个词时只能看到前 N-1 个词。

预训练结果

  • 训练数据:The Verdict 短篇小说(5,145 tokens)
  • 优化器:AdamW
  • 10 epochs 后:训练 loss 0.39,验证 loss 6.45(过拟合——数据集太小) | Epoch | Loss | 生成质量 | |-------|------|---------| | 1 | 9.78 | "Every effort moves you,,,,,,,,,,"(逗号复读机) | | 2 | 6.66 | "Every effort moves you, and, and, and..."("and"复读机) | | 9 | 0.54 | 开始输出语法正确的句子 | | 10 | 0.39 | 能写出通顺的英文句子 |

解码策略

  • Greedy:选概率最高 token,安全但无聊
  • Temperature:temperature=0.1 像严谨科学家,temperature=5 放飞自我
  • Top-k:只保留概率最高的 k 个 token 再采样

Stage 3:微调

分类微调(专才)

  • 数据集:SMS Spam Collection(5,572 条短信),平衡至 747 spam / 747 not-spam
  • 冻结大部分参数,只训练:输出层 + 最后一个 Transformer block + 最后的 LayerNorm
  • 只用最后一个 token 的输出做分类(因果注意力掩码保证该 token 看到全部信息)
  • 学习率 5e-5,5 epochs,M3 MacBook Air 上跑 5.65 分钟 | 指标 | 数值 | |------|------| | 训练集准确率 | 97.21% | | 验证集准确率 | 97.32% | | 测试集准确率 | 95.67% |

指令微调(通才)

  • 数据集:1,100 条指令-回答对(Alpaca 格式)
  • 使用 GPT-2 medium(3.55 亿参数),因为指令微调任务复杂,小模型撑不住
  • target padding 技巧:padding token 在 target 中对应位置设为 -100,PyTorch 交叉熵损失自动忽略
  • 学习率 5e-5,2 epochs,A100 GPU 上 52 秒
  • 用 Llama 3 8B 做自动化评估,110 条测试集平均分 50.32

关键工程细节

  1. 涌现能力(emergent behavior):GPT-3 96 层、1750 亿参数,没专门学过翻译但能翻译
  2. 预训练成本:GPT-3 花了 460 万美元云计算费用
  3. 数据规模:GPT-3 训练了 3000 亿 token(9.5 万年阅读量)
  4. 节省计算:每个 batch 各自填充到当前 batch 最长长度,而不是整个数据集最长长度

深度分析

知识体系的承上启下

这篇教程以 Makeling LLM 风格呈现,将大语言模型的核心知识分解为数据预处理、注意力机制、GPT 架构、预训练、微调七个阶段。从初学者视角看,这种渐进式结构降低了学习门槛;从工程师视角看,每个阶段的产出物(分词器、注意力矩阵、预训练模型)都是可验证的实体,兼顾了教学清晰度与工程实践性。

从"婴儿说话"到"通顺句子"的质变轨迹

训练 loss 从 9.78(逗号复读机)→ 6.66("and"复读机)→ 0.39(通顺句子)的演变过程,展示了预训练中小数据集过拟合的必然性。这个现象与 GPT-3 使用 3000 亿 token 训练形成对比,提示参数量与数据量的匹配关系:1.63 亿参数的模型在 5,145 tokens 上的过拟合几乎是确定事件,关键在于理解这是小数据集的局限而非模型错误。

因果注意力的工程简洁性

教程强调"右上角上三角掩码 + softmax 前设 -inf"的实现方式,相比其他方法(如注意力矩阵后置 mask、随机 mask 策略),这种设计在工程上极为简洁——只需一次矩阵运算即可完成因果约束,且在推理时天然支持增量生成。

微调的两种范式对比

维度 分类微调(专才) 指令微调(通才)
目标 单任务高准确率 多任务泛化能力
数据规模 1,494 条 1,100 条
模型规模 GPT-2 Small(1.63亿) GPT-2 Medium(3.55亿)
训练代价 5.65 分钟(M3 MacBook) 52 秒(A100 GPU)
评估方式 测试集准确率 95.67% Llama 3 8B 打分 50.32
两者的本质区别在于:分类微调只需要"最后一个 token",因为因果注意力已经保证了该 token 看到了全部上下文;指令微调则需要处理完整的 prompt-completion 对,使用 -100 padding 技巧避免无效计算。

实践启示

  1. 小数据集验证流程:在本地用小数据集验证整个流程(数据处理→模型训练→推理),确认 pipeline 正确后再迁移到大数据集。The Verdict 实验完美承担了这个角色。
  2. 参数冻结策略:微调时冻结大部分参数是工程上常见的选择,可以将分类头视为一个"适配器"(adapter),这与 LoRA 等轻量化微调方法的思想一脉相承。
  3. Batch 内动态 padding:每个 batch 填充到当前 batch 最长长度而非数据集最长长度,可以显著节省计算资源。这个优化在长上下文场景下尤为重要。
  4. 预训练权重加载:教程直接加载 OpenAI 的 GPT-2 权重验证模型正确性,这是一个重要的工程技巧——先确保模型架构实现正确,再用自己的数据训练。
  5. 涌现能力的工程启示:GPT-3 在 96 层、1750 亿参数时才出现涌现能力,这意味着如果只是在 GPT-2 级别(12 层、1.63 亿参数)工作,很多"神奇能力"可能不会出现,需要有合理的预期管理。

相关资源

相关实体