从词袋模型到 Transformer:一步步理解注意力机制
本文从词频统计出发,沿着 NLP 词向量技术的演进脉络,逐步推导到 Transformer 的核心——Self-Attention。适合有一定机器学习基础,想要深入理解大语言模型原理的读者。
前言
当你对着一篇技术文档问"这段话在讲什么"时,人类的思维会自然而然地联系上下文。但如果让机器来做这件事,它需要经历整整 70 年的技术迭代:从最简单的"数词出现次数",到能理解"苹果在不同语境下含义不同"的 Transformer。
本文将带你完整走过这段旅程。
一、起点:词袋模型(Bag of Words)
1.1 核心思想
词袋模型是最朴素的语言表示方法。它把一篇文档看成是一个"袋子",只关心:袋子里有哪些词,每个词出现了多少次。
假设我们有 3 篇文档,词表是:[我, 吃, 苹果, 手机, 喜欢]
| 文档 | 内容 | 向量表示 |
|---|---|---|
| 文档A | 我 吃 苹果 | [1, 1, 1, 0, 0] |
| 文档B | 我 喜欢 苹果 手机 | [1, 0, 1, 1, 1] |
| 文档C | 我 吃 手机 | [1, 1, 0, 1, 0] |
每篇文档是一个长度等于词表大小的向量,每个位置记录该词的出现次数。
1.2 怎么比较相似度?
用余弦相似度:
similarity(A, B) = (A · B) / (|A| × |B|)
两个向量方向越接近,相似度越高。
1.3 致命缺陷
"我吃苹果" vs "苹果手机"
→ 词袋眼里:两者都有"苹果" → 相似度 > 0
→ 实际上:一个是水果,一个是手机,毫无关系
三个根本问题:
- 忽略词序:"我吃苹果"和"苹果吃我"向量完全一样
- 词间无关系:无法捕捉"吃"和"食物"的语义关联
- 一词一义:苹果永远是同一个向量,无法区分水果和手机
二、N-gram:捕捉局部词序
2.1 核心思想
词袋模型丢失了词序信息,N-gram 尝试弥补这一点。
把相邻的 N 个词"捆绑"成一个新单元:
原句:我 吃 苹果
Bigram:我吃 / 吃苹果
Trigram:我吃苹果
2.2 效果
"我吃苹果" → [我吃, 吃苹果]
"苹果吃我" → [苹果吃, 吃我]
现在两句话的向量就不一样了。
2.3 局限
- 只能捕捉局部(N 个词内)的顺序
- N 越大,词表指数级膨胀,数据稀疏严重
- 本质还是"数数",没有语义理解能力
三、TF-IDF:区分重要的词
3.1 核心思想
词袋模型中,“的”、“是”、"在"这些词出现频率极高,但毫无信息量。TF-IDF 的目标是找出真正有区分度的词。
公式:
TF-IDF(t,d)=TF(t,d)×logNdf(t)TF\text{-}IDF(t, d) = TF(t,d) \times \log\frac{N}{df(t)}TF-IDF(t,d)=TF(t,d)×logdf(t)N
| 符号 | 含义 |
|---|---|
| TF(t,d) | 词 t 在文档 d 中的频率 |
| N | 总文档数 |
| df(t) | 包含词 t 的文档数 |
3.2 直观理解
如果一个词:
- 在当前文档出现很多 → TF 高 ✅
- 在很多文档都出现 → IDF 低 ❌(是常见词)
- 在很少文档出现 → IDF 高 ✅(是稀有词,有区分度)
高 TF × 高 IDF → 这个词对当前文档非常重要
3.3 例子
词"苹果":
- 在 100 篇文档中,10 篇提到水果,5 篇提到手机
- df(苹果) = 15
- IDF = log(100/15) ≈ 1.9
词"的":
- 在 100 篇文档中,99 篇都出现
- df(的) = 99
- IDF = log(100/99) ≈ 0.01
→ 苹果的 TF-IDF 高,是关键词
→ "的"的 TF-IDF 几乎为 0,是噪声
3.4 局限
TF-IDF 依然是词袋模型的升级版,依然无法理解语义。"我吃苹果"和"我有苹果"的 TF-IDF 表现相同。
四、Word2Vec:词有了向量
4.1 核心思想
不再统计词频,而是让每个词对应一个固定长度的向量。语义相近的词,向量方向接近。
苹果 → [0.8, 0.2, -0.1, 0.5]
手机 → [0.7, 0.3, -0.2, 0.6]
吃 → [-0.3, 0.9, 0.4, -0.1]
训练完成后:
苹果 - 水果 ≈ 手机 - 电子产品(性别类比)国王 - 男人 + 女人 ≈ 女王(关系迁移)
4.2 怎么训练?Skip-gram 和 CBOW
Skip-gram:中间词预测上下文
窗口:[-2, -1, +1, +2]
输入:苹果 → 输出:我要吃
用梯度下降调整,使得 P(我|苹果)、P(吃|苹果) 最大化
CBOW:上下文预测中间词
输入:我 吃 苹果 → 输出:手机
用上下文词的向量相加,预测中间词
4.3 Word2Vec 的局限
| 问题 | 说明 |
|---|---|
| 一词一义 | 训练后每个词只有一个固定向量,无法区分多义词 |
| 局部窗口 | 只考虑 ±k 个词,全局语义理解不足 |
| 无序感知 | "人咬狗"和"狗咬人"训练效果类似 |
最核心的局限:"苹果"在"我吃苹果"和"苹果手机"中是同一个向量。
五、Transformer:动态上下文向量
5.1 核心问题
Word2Vec 的苹果只有一个静态向量。但现实中:
"我吃苹果" → 苹果 = 水果
"苹果手机" → 苹果 = 科技品牌
"苹果股价" → 苹果 = 公司
需要:根据上下文,动态生成不同的向量。
5.2 从点积到 Attention
第一步:原始点积(Word2Vec)
score(苹果, 吃) = e_苹果 · e_吃
问题:两个词向量都是固定的,只能衡量词本身的相似度,无法衡量"在当前句子中有多相关"。
第二步:加入投影矩阵 Wq 和 Wk
Q_苹果 = Wq · e_苹果 (苹果作为"提问者"的视角)
K_吃 = Wk · e_吃 (吃作为"被问者"的视角)
score = Q_苹果 · K_吃
关键转变:
- Wq 和 Wk 是不同的投影矩阵
- 同一个词,经过 Wq 和 Wk 投影后,进入不同的语义空间
- 这样就能捕捉"在当前任务下,两个词的相关程度"
第三步:Softmax 归一化
原始分数:
score(苹果问苹果) = 2.1
score(苹果问吃) = 1.76
score(苹果问我) = 0.3
Softmax 后(权重):
[0.46, 0.40, 0.14]
→ 苹果最关注自己(46%),其次是"吃"(40%),最后是"我"(14%)
第四步:引入 Value
打分用 K,但加权汇总的应该是"内容",于是引入 V:
V = Wv · e (每个词的信息内容)
类比:
- Q(Query):我脑子里想查什么
- K(Key):图书馆每本书的书名/索引(用于匹配)
- V(Value):书里的实际内容(用于汇总)
第五步:完整公式
Attention(Q,K,V)=softmax(QKTdk)⋅V\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right) \cdot VAttention(Q,K,V)=softmax(dkQKT)⋅V
其中 dk\sqrt{d_k}dk 是为了防止点积结果过大导致 Softmax 梯度消失。
5.3 例子:用"我吃苹果"完整走一遍
输入: 我 吃 苹果,三个词的初始向量 e_我, e_吃, e_苹果
Step 1:生成 Q、K、V
对每个词,都做三次投影:
Q_我 = Wq · e_我
K_我 = Wk · e_我
V_我 = Wv · e_我
Q_吃 = Wq · e_吃
K_吃 = Wk · e_吃
V_吃 = Wv · e_吃
Q_苹果 = Wq · e_苹果
K_苹果 = Wk · e_苹果
V_苹果 = Wv · e_苹果
Step 2:计算"苹果"的新向量
打分:
苹果问苹果:Q_苹果 · K_苹果 = 2.1
苹果问吃: Q_苹果 · K_吃 = 1.76
苹果问我: Q_苹果 · K_我 = 0.3
Softmax → 权重:
[0.46, 0.40, 0.14]
加权求和:
新向量_苹果 = 0.46 × V_苹果 + 0.40 × V_吃 + 0.14 × V_我
Step 3:同时计算"我"和"吃"的新向量
"我"的新向量 = softmax(我问苹果, 我问吃, 我问我) · [V_苹果, V_吃, V_我]
"吃"的新向量 = softmax(吃问苹果, 吃问吃, 吃问我) · [V_苹果, V_吃, V_我]
最终输出: 三个词都有了融合整句上下文的新向量。
5.4 Multi-Head Attention
只用一个 Q/K/V 视角太单一。用多个"头"并行计算:
头1:专注语法关系(主谓宾)
头2:专注语义关系(同义词)
头3:专注指代关系(它指谁)
...
最终 = Concat(头1结果, 头2结果, ...) · Wo
5.5 位置编码
Self-Attention 同时处理所有词,没有位置信息。通过位置编码(Positional Encoding)手动注入位置:
PE(pos, 2i) = sin(pos / 10000^(2i/d))
PE(pos, 2i+1) = cos(pos / 10000^(2i/d))
最终输入 = 词向量 + 位置编码
5.6 完整 Transformer Block
输入向量
↓
Multi-Head Self-Attention
↓ Add & Layer Norm(残差连接)
↓
前馈神经网络(FFN)
↓ Add & Layer Norm
↓
输出(进入下一层)
总结: Transformer 通过 Self-Attention 让每个词都能"看到"句子中的所有其他词,并根据相关性动态决定关注谁——彻底解决了 Word2Vec 的局限。
六、词向量技术演进总结
| 技术 | 表示对象 | 上下文感知 | 一词多义 | 训练方式 |
|---|---|---|---|---|
| 词袋模型 | 文档向量 | ❌ | ❌ | 统计计数 |
| TF-IDF | 文档向量 | ❌ | ❌ | 统计 + 逆文档频率 |
| Word2Vec | 词向量 | 局部窗口 | ❌ | 预测式(Skip-gram/CBOW) |
| Transformer | 词向量(动态) | 全局 | ✅ | 自监督(预测下一个词) |
结语
从词袋模型到 Transformer 的演进,本质上是 NLP 对"语义理解"不断深入的过程:
计数 → 权重 → 静态向量 → 动态上下文向量
Transformer 之所以强大,正是因为它终于解决了"一词多义"和"全局依赖"这两个核心问题。而 Self-Attention 作为其核心机制,通过 Q/K/V 的精巧设计,让"词与词之间的关联"变得可学习、可解释。
理解了这个基础,你再看 BERT、GPT、ChatGPT,就不会觉得它们是魔法,而是几十年积累的水到渠成。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)