算法可视化与交互学习平台
学习 GPT:从预测下一个 token 到 TinyGPT 与规模化范式GPT: From Next-Token Prediction to TinyGPT and the Scaling Paradigm
用一个最小字符级 GPT 实验理解 decoder-only Transformer:文本如何变成 token 和 embedding,causal self-attention 如何禁止偷看未来,cross entropy loss 如何驱动模型学习下一个 token 的概率分布;再通过文本续写、一位数加法、涌现能力、参数压缩和世界模型视角,理解 GPT 如何从 TinyGPT 骨架走向大规模语言模型范式。
先抓住 GPT 的最小目标
这一节把 GPT 缩到一个能在本地 CPU 上跑的小实验:**字符级 TinyGPT**。
核心任务非常简单:
也就是让模型在每个位置都做同一件事:根据已经看到的上下文,预测下一个字符。它不是为了训练一个会聊天的大模型,而是为了把 GPT 的主干看清楚:
学完后你应该能回答三个问题:
1. GPT 和 Transformer 的关系是什么? 2. 为什么 GPT 训练时必须戴上 causal mask? 3. 一段短文本如何真的训练出一个可以继续生成字符的小模型?
GPT 本质上是什么
1. 一句话:GPT 是 decoder-only Transformer
Transformer 原始结构可以分成 Encoder 和 Decoder。GPT 走的是 Decoder-only 路线:它不接收另一段 encoder 输出,而是只看自己前面的 token,一步一步预测下一个 token。
因此,前一个 Transformer 模块里学到的 Q/K/V、multi-head attention、feed forward、residual connection、LayerNorm,在 GPT 里都会出现。真正关键的差异是:GPT 的 self-attention 是 causal 的,也就是当前位置不能看到未来位置。
2. GPT 学到的不是“整句答案”,而是概率分布
每个位置都会输出一个长度为 vocabulary size 的向量,也就是 logits。softmax 之后,它表示“下一个 token 是每个候选 token 的概率”。例如看到 hell 之后,小模型可能给出:
| next char | probability |
|---|---|
o | 0.62 |
| 0.13 |
e | 0.07 |
| other | 0.18 |
训练就是不断提高真实下一个字符的概率,降低错误字符的概率。
3. 字符级 GPT 为什么适合入门
真实 GPT 使用更复杂的 tokenizer,把文本切成 subword token。入门时可以先把每个字符当作一个 token,因为字符表很小,编码、解码、训练目标都能直接看见。这个最小版本不会理解世界知识,但足够理解 GPT 的骨架。
训练目标:预测下一个 token
GPT 在第 t 个位置根据前文 x_<t 预测当前 token x_t。训练时使用 cross entropy:它只盯住真实下一个 token 的概率,概率越高 loss 越小,概率越低惩罚越大。
Cross entropy 在问什么
对每个位置,模型会给整个字符表或词表输出一组概率。Cross entropy 不要求模型只输出一个答案,而是检查:真实下一个 token 被分到了多少概率。真实 token 的概率越接近 1,loss 越接近 0。
为什么是负对数概率
单个位置的 loss 可以写成 。如果模型很确信正确 token,p 很大,负对数很小;如果模型几乎没把概率分给正确 token,p 很小,负对数会迅速变大。
它如何推动 TinyGPT 学习
训练时,反向传播会调整 embedding、Q/K/V、FFN 和输出层参数,让真实下一个 token 的概率升高,让错误候选的概率降低。因此 loss 曲线下降,通常表示模型越来越会根据上下文预测后面的字符。
为什么 GPT 不能偷看未来
GPT 的训练目标是 根据已经出现的上下文预测下一个 token。例如看到 我 爱 吃,模型应该预测下一个 token 可能是 鱼。如果训练时已经允许模型看到 鱼,那就不是学习语言规律,而是在直接抄答案。
1. Self-Attention 默认会看全部
普通 self-attention 中,每个 token 都可以和整段序列里的每个 token 计算 attention。例如序列 我 爱 吃 鱼,如果不加限制,我、爱、吃、鱼 都能看到完整句子。这对 GPT 会造成训练作弊:loss 可能很好看,但真实生成时未来 token 根本还不存在。
2. “允许看到的位置”是什么意思
这里的 允许看到的位置,本质上是在表示:当前 token 能关注哪些 token,也就是哪些位置信息允许参与 attention 计算。
允许看到的位置:
1 0 0 0
1 1 0 0
1 1 1 0
1 1 1 1其中 1 表示可以看,0 表示不能看。假设序列是:
| 位置 | token | 允许看到 | 对应行 |
|---|---|---|---|
| 0 | 我 | 我 | [1, 0, 0, 0] |
| 1 | 爱 | 我、爱 | [1, 1, 0, 0] |
| 2 | 吃 | 我、爱、吃 | [1, 1, 1, 0] |
| 3 | 鱼 | 我、爱、吃、鱼 | [1, 1, 1, 1] |
矩阵里的 1 都集中在主对角线和它的左下方,所以它也叫 下三角 Mask,或者 Causal Mask。
3. 代码如何禁止偷看
在 attention 里,模型会先算每个位置之间的相关性分数 scores。然后把未来位置,也就是 mask 中为 0 的地方,改成 -inf:
scores = scores.masked_fill(
tril[:T, :T] == 0,
float('-inf')
)
attn = softmax(scores, dim=-1)为什么是 -inf?因为 softmax 会把分数变成概率权重,而 e^(-inf) = 0。所以未来 token 的 attention 权重会变成 0,等价于完全看不到未来。
4. 最核心的一句话
Causal Mask 定义了当前 token 的 可见历史范围:只能看到过去和现在,不能看到未来。这样 GPT 才是在学习“根据过去预测未来”,而不是训练时偷看答案。
逐步演算:训练样本如何错一位对齐
chunk = 'hello '
# 显示为 'hello[space]'字符级 TinyGPT:训练语料并生成续写
把字符级 TinyGPT 拆成“查看语料 -> 训练模型 -> 调用训练后模型”。训练阶段学习一小段文本的下一个字符规律并临时保存模型;调用阶段直接复用已训练模型,观察 prompt、生成长度、temperature 和采样开关如何影响续写。
算术 TinyGPT:训练一位数加法并调用模型
本实验已经针对“学不会 8+7=15”进行了优化:
- 训练数据重复 20 次
- 只保留一个真正未知组合:8+7
- 默认参数更适合学习加法规律
- 支持实时打印训练日志