MiniMind — 阶段 2.1:Transformer 整体架构
Transformer 整体结构
知识点 1:什么是 Transformer?
在 2017 年之前,AI 处理文字主要靠 RNN(循环神经网络),它的学习方式是:
"今" → "天" → "天" → "气" → "真" → "好"
↓ ↓ ↓ ↓ ↓ ↓
处理 → 处理 → 处理 → 处理 → 处理 → 处理
一个字一个字地读,像你用手指指着课文一个字一个字念,很慢,而且读到后面容易忘了前面说了什么。
2017 年,Google 发表了论文《Attention Is All You Need》,提出了 Transformer,它的革命性在于:
能同时看到所有字。
"今" "天" "天" "气" "真" "好"
↕ ↕ ↕ ↕ ↕ ↕
同时互相关注,互相交换信息
就像你一眼扫过去整个句子,瞬间理解意思。这靠的是一个核心机制叫 注意力机制(Attention)——让每个字都能”看到”其他所有字,判断哪些字跟自己关系更密切。
一句话总结:Transformer = 一种能同时处理所有字、靠”注意力”理解文本的神经网络架构。
知识点 2:三种 Transformer 架构
原始 Transformer 有两半:
- Encoder(编码器):负责”理解”输入
- Decoder(解码器):负责”生成”输出
后来大家发现,不一定要两半都用,于是发展出三种玩法:
① Encoder-Only(只有编码器)
代表:BERT
特点:能看懂,但不能写
它能同时看到一句话的所有字(前面的、后面的都能看到),所以特别擅长”理解”任务,比如:
- 这句话是正面还是负面?(情感分类)
- 这段话里的人名是什么?(信息提取)
但它不擅长一个字一个字地生成文本。
② Encoder-Decoder(编码器 + 解码器)
代表:T5、原始 Transformer
特点:先看完,再写
典型场景是翻译:先用 Encoder 理解英文,再用 Decoder 生成中文。
③ Decoder-Only(只有解码器)⭐
代表:GPT、Llama、DeepSeek、MiniMind
特点:一个字一个字往后写
关键规则:每个字只能看到它前面的字,不能偷看后面的。
生成"今"时:看到 → [今]
生成"天"时:看到 → [今, 天]
生成"真"时:看到 → [今, 天, 真]
生成"好"时:看到 → [今, 天, 真, 好]
这叫 自回归生成(Autoregressive),天然适合聊天 —— 你说一句,它接着一个字一个字地回复。
MiniMind 用的就是 Decoder-Only,和 GPT、Llama 一样。
🤔 小问题:BERT(Encoder-Only)每个字能看到前面和后面所有字,GPT(Decoder-Only)每个字只能看到前面的字。你觉得为什么聊天场景下,“只能看前面”反而更合适?
回答:因为聊天时是一个字一个字出现的,后面的字还没生成
这就是 Decoder-Only 适合聊天的根本原因:
- 训练时:模型练习”根据前面的字,预测下一个字”
- 推理时:模型一个字一个字地往外蹦,每次只看已经生成的内容
而 BERT 那种”前后都能看”的能力,在理解一整段已有文本时很强,但没法用来生成新文字。
知识点 3:MiniMind 模型的整体结构
每个文本生成型 Transformer 由三大核心组件构成。
MiniMind 也一样,它的结构可以用一张”三明治”图来理解:
输入: "今天天气"
↓
┌─────────────────────────┐
│ ① Embedding 层 │ ← 把文字变成数字向量
└─────────────────────────┘
↓
┌─────────────────────────┐
│ ② Transformer Block ×N │ ← 核心处理单元,堆叠 N 层
│ ┌───────────────────┐ │
│ │ RMSNorm │ │
│ │ Attention(注意力)│ │
│ │ RMSNorm │ │
│ │ FFN(前馈网络) │ │
│ └───────────────────┘ │
└─────────────────────────┘
↓
┌─────────────────────────┐
│ ③ Output 层 │ ← 把向量变回文字(预测下一个字)
└─────────────────────────┘
↓
输出: "真"(预测的下一个字)
对应到 MiniMind 的代码文件 model/model_minimind.py,模型的主体类大概长这样:
class MiniMindModel:
def __init__(self):
self.embed_tokens = Embedding(...) # ① 词嵌入层
self.layers = [MiniMindBlock × N] # ② N个Transformer Block
self.norm = RMSNorm(...) # 最终归一化
class MiniMindForCausalLM:
def __init__(self):
self.model = MiniMindModel(...) # 上面的模型
self.lm_head = Linear(...) # ③ 输出层
我们用生活比喻来理解这三层的作用:
| 组件 | 作用 | 生活比喻 |
|---|---|---|
| Embedding | 把文字变成数字向量(电脑只认数字) | 把中文翻译成一种”数字语言” |
| Transformer Block ×N | 理解文字之间的关系 | 反复阅读、思考,理解句子含义 |
| Output (lm_head) | 根据理解,预测下一个字 | 想好了,说出下一个字 |
关键点:Transformer Block 是模型的”大脑”,堆叠越多层,模型越聪明,但参数也越多。
MiniMind 的最小模型只堆了 8 层 Transformer Block,所以参数才 26M 这么小。而 GPT-3 堆了 96 层,参数是 175B。
🤔 小问题:模型有三层结构——Embedding、Transformer Block、Output。你觉得哪一层是参数量最大、最核心的部分?为什么?
回答:Transformer层,因为它会堆叠很多层
💡 一个有趣的细节:MiniMind 的 Output 层和 Embedding 层共享同一组参数(叫做 weight tying),这样可以省下一半参数。这是小模型常用的技巧。
问题:为什么小模型用 Weight Tying,大模型不用?
Embedding 和 Output 分别干什么?
Embedding(输入层):文字 → 向量 (查字典:把字变成数字)
Output(输出层): 向量 → 文字 (反查字典:把数字变回字)
它们的功能刚好相反,但操作的都是”字和向量之间的对应关系”,所以共享同一张表是有道理的。
小模型为什么要共享?—— 因为”穷”
用 MiniMind 举例算一笔账:
词表大小 = 6400,向量维度 = 512
Embedding 参数量 = 6400 × 512 = 3.3M
Output 参数量 = 6400 × 512 = 3.3M
─────────────────────────────────────
如果不共享,两层合计 = 6.6M
模型总参数 = 26M
占比 = 6.6 / 26 = 25.4% ← 四分之一的参数!
如果共享,两层合计 = 3.3M
占比 = 3.3 / 26 = 12.7% ← 省了一半!
💡 对小模型来说,省下的 3.3M 参数可以”腾”给 Transformer Block,让”大脑”更强。
大模型为什么不共享?—— 因为”富”
而且两层想干不同的事
用 LLaMA-65B 举例:
词表大小 = 32000,向量维度 = 8192
Embedding 参数量 = 32000 × 8192 = 262M
模型总参数 = 65,000M (65B)
占比 = 262 / 65000 = 0.4% ← 微不足道!
省这 0.4% 毫无意义,反而会带来问题:
| 小模型(共享) | 大模型(不共享) | |
|---|---|---|
| 省参数 | 省 12%,很值 ✅ | 省 0.4%,没必要 ❌ |
| 功能差异 | 模型小,两层做的事差不多 | 模型大了,两层想各自专精自己的任务 |
| 性能影响 | 共享反而像”正则化”,防止过拟合 ✅ | 强制共享会限制模型表达能力 ❌ |
用生活比喻
🏠 小公司(小模型):前台和客服是同一个人,因为人手不够,一个人干两个活更划算。
🏢 大公司(大模型):前台和客服是两个人,各自专精自己的领域,效率更高。强行让一个人干两个活反而降低服务质量。
总结一句话
| 模型规模 | 策略 | 原因 |
|---|---|---|
| 小模型 | 共享 ✅ | 参数宝贵,省下来给 Transformer Block |
| 大模型 | 不共享 ✅ | 参数充裕,让两层各自学习更好的表示 |
豆知识
1. pytorch是什么?
PyTorch 是一个开源的深度学习框架,由 Meta(Facebook)开发,用于构建和训练神经网络。
先搞清楚一个问题
你想训练一个 AI(比如让它能识别猫狗照片),你需要做什么?
1. 搭一个神经网络(设计模型结构)
2. 喂数据给它(把照片扔进去)
3. 让它不断调整自己(训练过程)
4. 最终它学会了(能识别新照片)
这每一步都涉及大量的数学计算。 你自己从零写?太痛苦了。
PyTorch 就是帮你干这些脏活累活的工具箱。
具体它帮你做了什么
| 你想做的事 | 没有 PyTorch | 有 PyTorch |
|---|---|---|
| 处理数据 | 自己写读取图片、分批的代码 | DataLoader 帮你搞定 |
| 搭网络 | 自己实现每一层的数学公式 | nn.Linear(10, 1) 一行搞定 |
| 算梯度(核心难点) | 自己手推微积分、写求导代码 | loss.backward() 一行搞定 |
| 用 GPU 加速 | 自己写 CUDA 代码 | .to('cuda') 一行搞定 |
一句话总结
PyTorch 就是一个 Python 库(工具包),让你可以用几行代码就搭建、训练神经网络,而不用自己从零写那些复杂的数学运算。
就像:
- jQuery 帮你简化了 DOM 操作
- Excel 帮你简化了数据计算
- PyTorch 帮你简化了训练 AI 的过程
2. 深度学习是什么
深度学习是机器学习的一个分支,通过多层神经网络自动从数据中学习特征和规律。
可以理解为用很多层的神经网络,让机器自己从大量数据中学会规律。它是当前 AI 爆发的核心驱动力。
核心思想
传统编程:人写规则 → 计算机执行 深度学习:人给数据 → 计算机自己学规则
比喻: 像教小孩认猫 — 你不需要告诉他”猫有尖耳朵、胡须、四条腿”,你只需要给他看 1000 张猫的照片,他自己就学会了。深度学习就是这个过程。
3. 为什么叫”深度”
输入 → [第1层] → [第2层] → [第3层] → ... → [第N层] → 输出
↑ ↑
学低级特征(边缘、颜色) 学高级特征(眼睛、脸)
“深度” = 层数多。 层数越多,能学到的特征越抽象、越复杂。
举个例子:识别手写数字
图片 [28×28像素]
→ 第1层:检测边缘、线条
→ 第2层:检测拐角、圆弧
→ 第3层:组合出"6的形状"、"8的形状"
→ 输出:这是数字 "6",置信度 97%