nanogpt¶
nanogpt来自Andrej Karpathy的开源项目,旨在让开发者能够以最直观的方式理解、训练和微调中等规模的 GPT(生成式预训练 Transformer)模型
1. 总览¶
nanoGPT是对 Karpathy minGPT 项目的重写,也就是05-gpt_Karpathy.md, Karpathy 认为 minGPT 太过侧重于教育而牺牲了性能,因此 nanoGPT 在保持代码高度可读的同时,大幅优化了训练效率。 整个核心模型定义(model.py)和训练循环(train.py)通常只有几百行代码,非常适合人类阅读和修改。 性能卓越: 支持分布式训练(DDP)、混合精度训练(FP16/BF16)以及 PyTorch 2.0 的 torch.compile 编译加速,显著提升了训练速度。
功能完备: - 从零预训练(Pre-training): 可以从头开始训练类似 GPT-2 规模的模型。
-
微调(Fine-tuning): 支持加载 OpenAI 发布的 GPT-2 权重,并根据自己的数据集进行微调。
-
生成采样: 包含一个简单的脚本用于从训练好的模型中生成文本。
2. model.py¶
顺着数据的流向(从输入一个单词 ID 到输出预测概率),可以将 GPT 类中的核心前向传播过程拆解为以下三个关键阶段:
2.1 输入编码阶段:Token 与 Position¶
在 GPT.forward 方法中,第一步是将离散的单词索引变成连续的向量
| Python | |
|---|---|
1 2 3 4 5 6 7 8 9 10 | |
wte (Word Token Embedding):gpt2 中使用的词表(\(50304 \times 768\))。每个单词 ID 对应一行向量,在gpt2中共有50304个token, embedding维度为768
wpe (Word Position Embedding):GPT-2 的位置特征。由于 Transformer 并行处理所有单词,它无法识别顺序。在这里为每个位置(0 到 1023)训练了一个专门的向量。此外,这里也决定了gpt2的上下文最大是1024
2.2 核心计算阶段:Block 的循环迭代¶
数据经过 Embedding 后,会进入 n_layer(通常是 12 层)个重复的 Block。
| Python | |
|---|---|
1 2 3 4 5 6 7 8 9 10 | |
| Python | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
self.ln_1与self.ln_2为LayerNorm(), self.attn 为因果自注意力 (Causal Self-Attention),self.mlp为前馈网络,下面分别介绍自注意力和前馈网络。
2.2.1 Causal Self-Attention¶
| Python | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | |
此外,需要注意的是, self.c_attn = nn.Linear(config.n_embd, 3 * config.n_embd, bias=config.bias)
- 输入:
(B, T, n_embd) - 输出:
(B, T, 3 * n_embd) - 一次性算 Q、K、V(效率高)
- 后面用
.split()拆成三份 这是 GPT 系列的经典写法
dropout
att = self.attn_dropout(att)
Dropout 会 随机把一部分 attention 权重置 0, 防止依赖某 token
y = self.resid_dropout(self.c_proj(y))
放在residual之前, 削弱子模块(Attention)的支配力,防止模块过强
model.eval()推理阶段, 所有dropout自动关闭
2.2.2 MLP¶
| Python | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
为什么是 4 * n_embd
这是 Transformer 的经验设定(来自原论文),维度太小表达能力不够,太大则算力& 显存爆炸,4C 是一个性价比最优点。GPT / BERT / ViT 都用这个比例
| Python | |
|---|---|
1 | |
GELU = Gaussian Error Linear Unit
公式(近似):
值越大,越“可信”,越容易通过
比 ReLU 更“平滑”,对大模型训练更友好
3. bench.py¶
benchmark脚本,train.py 的精简版,只用来跑性能
- 构建一个 GPT 模型
- 准备 真实或伪造的数据
- 跑一个 标准训练 step:
| Text Only | |
|---|---|
1 | |
- 每步多快
- GPU 利用率(MFU)
- Flash Attention / bf16 / torch.compile 的效果
| Python | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | |
这是一个 GPT-2 Small 级别模型:
| 参数 | 值 |
|---|---|
| 层数 | 12 |
| hidden | 768 |
| heads | 12 |
| 参数量 | ~124M |
4. sample.py¶
文本生成,推理任务,加载一个已训练好的 GPT(自己训的 or GPT-2),给定一个 prompt,用自回归方式采样生成文本
| Text Only | |
|---|---|
1 2 3 4 5 6 7 8 9 | |
| Python | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | |