第3章 输入是如何进入 Transformer 的
本章目标:
理解文字是如何一步步变成 Transformer 可以处理的向量的,以及为什么需要 Position Encoding。
3.1 从文字到向量的三步
#mermaid-svg-77WCMcyHMv8SBeFR{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-77WCMcyHMv8SBeFR .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-77WCMcyHMv8SBeFR .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-77WCMcyHMv8SBeFR .error-icon{fill:#552222;}#mermaid-svg-77WCMcyHMv8SBeFR .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-77WCMcyHMv8SBeFR .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-77WCMcyHMv8SBeFR .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-77WCMcyHMv8SBeFR .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-77WCMcyHMv8SBeFR .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-77WCMcyHMv8SBeFR .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-77WCMcyHMv8SBeFR .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-77WCMcyHMv8SBeFR .marker{fill:#333333;stroke:#333333;}#mermaid-svg-77WCMcyHMv8SBeFR .marker.cross{stroke:#333333;}#mermaid-svg-77WCMcyHMv8SBeFR svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-77WCMcyHMv8SBeFR p{margin:0;}#mermaid-svg-77WCMcyHMv8SBeFR .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-77WCMcyHMv8SBeFR .cluster-label text{fill:#333;}#mermaid-svg-77WCMcyHMv8SBeFR .cluster-label span{color:#333;}#mermaid-svg-77WCMcyHMv8SBeFR .cluster-label span p{background-color:transparent;}#mermaid-svg-77WCMcyHMv8SBeFR .label text,#mermaid-svg-77WCMcyHMv8SBeFR span{fill:#333;color:#333;}#mermaid-svg-77WCMcyHMv8SBeFR .node rect,#mermaid-svg-77WCMcyHMv8SBeFR .node circle,#mermaid-svg-77WCMcyHMv8SBeFR .node ellipse,#mermaid-svg-77WCMcyHMv8SBeFR .node polygon,#mermaid-svg-77WCMcyHMv8SBeFR .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-77WCMcyHMv8SBeFR .rough-node .label text,#mermaid-svg-77WCMcyHMv8SBeFR .node .label text,#mermaid-svg-77WCMcyHMv8SBeFR .image-shape .label,#mermaid-svg-77WCMcyHMv8SBeFR .icon-shape .label{text-anchor:middle;}#mermaid-svg-77WCMcyHMv8SBeFR .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-77WCMcyHMv8SBeFR .rough-node .label,#mermaid-svg-77WCMcyHMv8SBeFR .node .label,#mermaid-svg-77WCMcyHMv8SBeFR .image-shape .label,#mermaid-svg-77WCMcyHMv8SBeFR .icon-shape .label{text-align:center;}#mermaid-svg-77WCMcyHMv8SBeFR .node.clickable{cursor:pointer;}#mermaid-svg-77WCMcyHMv8SBeFR .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-77WCMcyHMv8SBeFR .arrowheadPath{fill:#333333;}#mermaid-svg-77WCMcyHMv8SBeFR .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-77WCMcyHMv8SBeFR .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-77WCMcyHMv8SBeFR .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-77WCMcyHMv8SBeFR .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-77WCMcyHMv8SBeFR .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-77WCMcyHMv8SBeFR .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-77WCMcyHMv8SBeFR .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-77WCMcyHMv8SBeFR .cluster text{fill:#333;}#mermaid-svg-77WCMcyHMv8SBeFR .cluster span{color:#333;}#mermaid-svg-77WCMcyHMv8SBeFR div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-77WCMcyHMv8SBeFR .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-77WCMcyHMv8SBeFR rect.text{fill:none;stroke-width:0;}#mermaid-svg-77WCMcyHMv8SBeFR .icon-shape,#mermaid-svg-77WCMcyHMv8SBeFR .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-77WCMcyHMv8SBeFR .icon-shape p,#mermaid-svg-77WCMcyHMv8SBeFR .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-77WCMcyHMv8SBeFR .icon-shape .label rect,#mermaid-svg-77WCMcyHMv8SBeFR .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-77WCMcyHMv8SBeFR .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-77WCMcyHMv8SBeFR .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-77WCMcyHMv8SBeFR :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} I love AI
Tokenizer
分词
101, 2293, 9932
Token ID
Embedding Layer
查表
\[0.1, 0.3, ...,
0.5, 0.2, ...,
0.8, 0.1, ...\]
Position Encoding
加位置信息
最终输入向量
三步:
- Tokenizer:文字 → Token ID
- Embedding:Token ID → 向量
- Position Encoding:向量 + 位置信息
3.2 Tokenizer:文字变成数字
Tokenizer 的任务是把文字切成 Token,再把每个 Token 映射到一个整数 ID。
3.2.1 什么是 Token?
Token 不一定是一个完整的单词,可以是:
- 一个完整单词:
love→2293 - 一个子词:
learning→[learn, ##ing]→[4553, 1075] - 一个字符:
A→65 - 一个标点:
.→119
3.2.2 为什么要用子词?
| 方案 | 优点 | 缺点 |
|---|---|---|
| 字符级 | 词表小 | 序列太长,语义弱 |
| 单词级 | 语义强 | 词表太大,OOV问题 |
| 子词级(BPE/WordPiece) | 平衡 | 需要训练 |
现代 LLM 几乎都用子词方案:
- GPT 系列:BPE(Byte Pair Encoding)
- BERT:WordPiece
- Qwen/Llama:BPE(基于字节)
3.2.3 一个例子
text
输入:I love deep learning.
Tokenizer 输出(BERT):
[CLS] I love deep learning . [SEP]
101 146 2293 1996 4083 119 102
[CLS] 和 [SEP] 是特殊 Token,后面章节会详细讲。
3.3 Embedding Layer:数字变成向量
Token ID 只是一个整数,神经网络无法直接处理。
Embedding Layer 的作用是:
把每个 Token ID 映射到一个 d_model 维的向量。
本质上是一个查找表(Lookup Table):
text
词表大小 = 30000
d_model = 512
Embedding 矩阵形状:[30000, 512]
Token ID = 2293
→ 取第 2293 行
→ 得到一个 512 维向量
#mermaid-svg-uu9RnQ44ViUwzLlS{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-uu9RnQ44ViUwzLlS .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-uu9RnQ44ViUwzLlS .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-uu9RnQ44ViUwzLlS .error-icon{fill:#552222;}#mermaid-svg-uu9RnQ44ViUwzLlS .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-uu9RnQ44ViUwzLlS .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-uu9RnQ44ViUwzLlS .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-uu9RnQ44ViUwzLlS .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-uu9RnQ44ViUwzLlS .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-uu9RnQ44ViUwzLlS .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-uu9RnQ44ViUwzLlS .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-uu9RnQ44ViUwzLlS .marker{fill:#333333;stroke:#333333;}#mermaid-svg-uu9RnQ44ViUwzLlS .marker.cross{stroke:#333333;}#mermaid-svg-uu9RnQ44ViUwzLlS svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-uu9RnQ44ViUwzLlS p{margin:0;}#mermaid-svg-uu9RnQ44ViUwzLlS .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-uu9RnQ44ViUwzLlS .cluster-label text{fill:#333;}#mermaid-svg-uu9RnQ44ViUwzLlS .cluster-label span{color:#333;}#mermaid-svg-uu9RnQ44ViUwzLlS .cluster-label span p{background-color:transparent;}#mermaid-svg-uu9RnQ44ViUwzLlS .label text,#mermaid-svg-uu9RnQ44ViUwzLlS span{fill:#333;color:#333;}#mermaid-svg-uu9RnQ44ViUwzLlS .node rect,#mermaid-svg-uu9RnQ44ViUwzLlS .node circle,#mermaid-svg-uu9RnQ44ViUwzLlS .node ellipse,#mermaid-svg-uu9RnQ44ViUwzLlS .node polygon,#mermaid-svg-uu9RnQ44ViUwzLlS .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-uu9RnQ44ViUwzLlS .rough-node .label text,#mermaid-svg-uu9RnQ44ViUwzLlS .node .label text,#mermaid-svg-uu9RnQ44ViUwzLlS .image-shape .label,#mermaid-svg-uu9RnQ44ViUwzLlS .icon-shape .label{text-anchor:middle;}#mermaid-svg-uu9RnQ44ViUwzLlS .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-uu9RnQ44ViUwzLlS .rough-node .label,#mermaid-svg-uu9RnQ44ViUwzLlS .node .label,#mermaid-svg-uu9RnQ44ViUwzLlS .image-shape .label,#mermaid-svg-uu9RnQ44ViUwzLlS .icon-shape .label{text-align:center;}#mermaid-svg-uu9RnQ44ViUwzLlS .node.clickable{cursor:pointer;}#mermaid-svg-uu9RnQ44ViUwzLlS .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-uu9RnQ44ViUwzLlS .arrowheadPath{fill:#333333;}#mermaid-svg-uu9RnQ44ViUwzLlS .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-uu9RnQ44ViUwzLlS .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-uu9RnQ44ViUwzLlS .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uu9RnQ44ViUwzLlS .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-uu9RnQ44ViUwzLlS .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uu9RnQ44ViUwzLlS .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-uu9RnQ44ViUwzLlS .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-uu9RnQ44ViUwzLlS .cluster text{fill:#333;}#mermaid-svg-uu9RnQ44ViUwzLlS .cluster span{color:#333;}#mermaid-svg-uu9RnQ44ViUwzLlS div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-uu9RnQ44ViUwzLlS .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-uu9RnQ44ViUwzLlS rect.text{fill:none;stroke-width:0;}#mermaid-svg-uu9RnQ44ViUwzLlS .icon-shape,#mermaid-svg-uu9RnQ44ViUwzLlS .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uu9RnQ44ViUwzLlS .icon-shape p,#mermaid-svg-uu9RnQ44ViUwzLlS .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-uu9RnQ44ViUwzLlS .icon-shape .label rect,#mermaid-svg-uu9RnQ44ViUwzLlS .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uu9RnQ44ViUwzLlS .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-uu9RnQ44ViUwzLlS .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-uu9RnQ44ViUwzLlS :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Token ID: 2293
Embedding 矩阵
30000 × 512
向量: 0.1, 0.3, 0.5, ..., 0.2
512维
3.3.1 Embedding 是如何训练的?
Embedding 矩阵是随机初始化的,在训练过程中通过反向传播更新。
训练完成后,语义相近的词,向量也相近:
text
向量(king) - 向量(man) + 向量(woman) ≈ 向量(queen)
3.3.2 Tensor Shape
text
输入 Token ID:[batch_size, seq_len]
例如 [32, 128]
经过 Embedding:[batch_size, seq_len, d_model]
例如 [32, 128, 512]
3.4 为什么 Transformer 不认识顺序?
这是一个非常重要的问题。
RNN 天然知道顺序,因为它按时间步处理:
text
t=1: I
t=2: love
t=3: AI
但 Transformer 的 Self-Attention 是:
所有 Token 同时计算,互相交互。
这意味着:
text
[I, love, AI]
和
text
[AI, love, I]
在 Self-Attention 看来,是完全一样的!
因为 Attention 只关心 Token 之间的关系,不关心顺序。
所以,必须手动告诉 Transformer:每个 Token 在第几个位置。
这就是 Position Encoding。
3.5 Absolute Position Encoding(绝对位置编码)
原始论文使用正弦/余弦函数生成位置编码:
PE(pos,2i)=sin(pos100002i/dmodel)PE_{(pos, 2i)} = \sin\left(\frac{pos}{10000^{2i/d_{model}}}\right)PE(pos,2i)=sin(100002i/dmodelpos)
PE(pos,2i+1)=cos(pos100002i/dmodel)PE_{(pos, 2i+1)} = \cos\left(\frac{pos}{10000^{2i/d_{model}}}\right)PE(pos,2i+1)=cos(100002i/dmodelpos)
其中:
pos:Token 的位置(0, 1, 2, ...)i:向量的维度索引d_model:向量维度(如 512)
3.5.1 为什么用正弦/余弦?
| 特性 | 说明 |
|---|---|
| 有界 | 值在 -1, 1 之间,不会太大 |
| 唯一 | 每个位置的编码都不同 |
| 相对关系 | 任意两个位置的相对距离可以用线性变换表示 |
| 外推 | 可以处理训练时没见过的更长序列 |
3.5.2 如何使用?
text
Token Embedding:[batch, seq_len, d_model]
Position Encoding:[seq_len, d_model]
最终输入 = Token Embedding + Position Encoding
#mermaid-svg-QUAJIzqUR3eUVKWb{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-QUAJIzqUR3eUVKWb .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-QUAJIzqUR3eUVKWb .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-QUAJIzqUR3eUVKWb .error-icon{fill:#552222;}#mermaid-svg-QUAJIzqUR3eUVKWb .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-QUAJIzqUR3eUVKWb .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-QUAJIzqUR3eUVKWb .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-QUAJIzqUR3eUVKWb .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-QUAJIzqUR3eUVKWb .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-QUAJIzqUR3eUVKWb .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-QUAJIzqUR3eUVKWb .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-QUAJIzqUR3eUVKWb .marker{fill:#333333;stroke:#333333;}#mermaid-svg-QUAJIzqUR3eUVKWb .marker.cross{stroke:#333333;}#mermaid-svg-QUAJIzqUR3eUVKWb svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-QUAJIzqUR3eUVKWb p{margin:0;}#mermaid-svg-QUAJIzqUR3eUVKWb .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-QUAJIzqUR3eUVKWb .cluster-label text{fill:#333;}#mermaid-svg-QUAJIzqUR3eUVKWb .cluster-label span{color:#333;}#mermaid-svg-QUAJIzqUR3eUVKWb .cluster-label span p{background-color:transparent;}#mermaid-svg-QUAJIzqUR3eUVKWb .label text,#mermaid-svg-QUAJIzqUR3eUVKWb span{fill:#333;color:#333;}#mermaid-svg-QUAJIzqUR3eUVKWb .node rect,#mermaid-svg-QUAJIzqUR3eUVKWb .node circle,#mermaid-svg-QUAJIzqUR3eUVKWb .node ellipse,#mermaid-svg-QUAJIzqUR3eUVKWb .node polygon,#mermaid-svg-QUAJIzqUR3eUVKWb .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-QUAJIzqUR3eUVKWb .rough-node .label text,#mermaid-svg-QUAJIzqUR3eUVKWb .node .label text,#mermaid-svg-QUAJIzqUR3eUVKWb .image-shape .label,#mermaid-svg-QUAJIzqUR3eUVKWb .icon-shape .label{text-anchor:middle;}#mermaid-svg-QUAJIzqUR3eUVKWb .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-QUAJIzqUR3eUVKWb .rough-node .label,#mermaid-svg-QUAJIzqUR3eUVKWb .node .label,#mermaid-svg-QUAJIzqUR3eUVKWb .image-shape .label,#mermaid-svg-QUAJIzqUR3eUVKWb .icon-shape .label{text-align:center;}#mermaid-svg-QUAJIzqUR3eUVKWb .node.clickable{cursor:pointer;}#mermaid-svg-QUAJIzqUR3eUVKWb .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-QUAJIzqUR3eUVKWb .arrowheadPath{fill:#333333;}#mermaid-svg-QUAJIzqUR3eUVKWb .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-QUAJIzqUR3eUVKWb .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-QUAJIzqUR3eUVKWb .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-QUAJIzqUR3eUVKWb .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-QUAJIzqUR3eUVKWb .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-QUAJIzqUR3eUVKWb .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-QUAJIzqUR3eUVKWb .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-QUAJIzqUR3eUVKWb .cluster text{fill:#333;}#mermaid-svg-QUAJIzqUR3eUVKWb .cluster span{color:#333;}#mermaid-svg-QUAJIzqUR3eUVKWb div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-QUAJIzqUR3eUVKWb .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-QUAJIzqUR3eUVKWb rect.text{fill:none;stroke-width:0;}#mermaid-svg-QUAJIzqUR3eUVKWb .icon-shape,#mermaid-svg-QUAJIzqUR3eUVKWb .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-QUAJIzqUR3eUVKWb .icon-shape p,#mermaid-svg-QUAJIzqUR3eUVKWb .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-QUAJIzqUR3eUVKWb .icon-shape .label rect,#mermaid-svg-QUAJIzqUR3eUVKWb .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-QUAJIzqUR3eUVKWb .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-QUAJIzqUR3eUVKWb .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-QUAJIzqUR3eUVKWb :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Token Embedding
batch, seq, d_model
Position Encoding
seq, d_model
最终输入
batch, seq, d_model
3.5.3 为什么相加不会互相干扰?
一个自然的疑问:位置信息和语义信息直接相加,后面的网络怎么分辨哪些是位置、哪些是语义?
答案有三层:
-
高维空间的正交性:在 512 维空间中,两个随机向量几乎总是接近正交的(夹角接近 90°)。这意味着 Position Encoding 和 Token Embedding 在大多数维度上不会互相干扰------它们各自占据了高维空间的不同"方向"。
-
网络会学着分辨 :Attention 层的 WQW_QWQ、WKW_KWK、WVW_VWV 矩阵是可学习的。它们可以学会用某些维度关注位置信息、用另一些维度关注语义信息。实际上,研究表明某些 Attention Head 确实学到了主要关注位置关系的模式。
-
这确实不是最优方案 :你的直觉是对的------相加确实存在信息混淆的问题。这也是为什么后来 RoPE 取代了绝对位置编码。RoPE 不是把位置"加"到向量上,而是把位置编码到 Q 和 K 的旋转中(见第15章),从根本上避免了这个问题。
3.6 Learned Position Embedding(可学习位置编码)
BERT 和 GPT 使用的是可学习的位置编码:
位置编码也是一个 Embedding 矩阵,通过训练学习。
text
Position Embedding 矩阵:[max_seq_len, d_model]
例如 [512, 768]
位置 0 → 取第 0 行
位置 1 → 取第 1 行
...
| 方案 | 优点 | 缺点 |
|---|---|---|
| 正弦/余弦(固定) | 可外推到更长序列 | 不能学习 |
| 可学习 | 更灵活 | 不能外推到训练时没见过的长度 |
3.6.1 绝对位置编码的根本问题
无论是正弦/余弦还是可学习方案,绝对位置编码都有一个深层问题:
问题:同一个词在不同位置会得到完全不同的输入向量
text
句子A: "I love AI" → love 的输入 = E(love) + P₂
句子B: "... I love AI" → love 的输入 = E(love) + P₁₀₂
两个 love 的语义完全相同,但因为位置不同,送入 Transformer 的向量截然不同。
更深的问题:语言真正在意的是相对位置,而非绝对位置
text
"The cat sits on the mat."
"Yesterday the little black cat sits on the old mat."
虽然 cat 的绝对位置从2变成了5,但 cat 和 sits 的相对距离没变------语法关系不取决于"第几个词",而取决于"离谁多远"。
这就是为什么绝对位置编码最终被 RoPE 取代------RoPE 把位置编码到 Q 和 K 的旋转中,使得 Attention Score 天然只依赖相对距离。
3.7 RoPE(Rotary Position Embedding)
RoPE 是 Qwen、Llama、DeepSeek 等现代 LLM 使用的位置编码方案。
3.7.1 核心思想
RoPE 不是把位置信息加到向量上,而是:
把位置信息编码到 Query 和 Key 的旋转中。
数学上,对于位置 m 的 Query 向量 qqq,RoPE 将其旋转一个角度:
qm=Rm⋅qq_m = R_m \cdot qqm=Rm⋅q
其中 RmR_mRm 是一个旋转矩阵,角度与位置 m 相关。
这样,两个 Token 的 Attention Score 只依赖于它们的相对位置,而不是绝对位置。
3.7.2 为什么 RoPE 更好?
| 特性 | 绝对位置编码 | RoPE |
|---|---|---|
| 外推能力 | 差 | 好 |
| 相对位置感知 | 间接 | 直接 |
| 长序列支持 | 有限 | 强(配合 YaRN 等技术) |
| 实现复杂度 | 简单 | 中等 |
3.8 TensorFlow 实现
3.8.1 Embedding Layer
python
import tensorflow as tf
vocab_size = 30000
d_model = 512
seq_len = 128
batch_size = 32
# Token Embedding
embedding = tf.keras.layers.Embedding(vocab_size, d_model)
# 输入 Token ID: [batch, seq_len]
token_ids = tf.random.uniform([batch_size, seq_len], maxval=vocab_size, dtype=tf.int32)
# 输出: [batch, seq_len, d_model]
x = embedding(token_ids)
print(x.shape) # (32, 128, 512)
3.8.2 正弦位置编码
python
import numpy as np
def get_positional_encoding(seq_len, d_model):
positions = np.arange(seq_len)[:, np.newaxis] # [seq_len, 1]
dims = np.arange(d_model)[np.newaxis, :] # [1, d_model]
angle_rates = 1 / np.power(10000, (2 * (dims // 2)) / d_model)
angles = positions * angle_rates
# 分别计算 sin 和 cos,写入新数组(避免原地修改)
pe = np.zeros((seq_len, d_model))
pe[:, 0::2] = np.sin(angles[:, 0::2])
pe[:, 1::2] = np.cos(angles[:, 1::2])
return tf.cast(pe[np.newaxis, :, :], dtype=tf.float32) # [1, seq_len, d_model]
pe = get_positional_encoding(128, 512)
print(pe.shape) # (1, 128, 512)
# 加到 Embedding 上
x = x + pe
print(x.shape) # (32, 128, 512)
3.9 Tensor Shape 总结
#mermaid-svg-NG4WlmtErSBWpf7U{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-NG4WlmtErSBWpf7U .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-NG4WlmtErSBWpf7U .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-NG4WlmtErSBWpf7U .error-icon{fill:#552222;}#mermaid-svg-NG4WlmtErSBWpf7U .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-NG4WlmtErSBWpf7U .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-NG4WlmtErSBWpf7U .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-NG4WlmtErSBWpf7U .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-NG4WlmtErSBWpf7U .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-NG4WlmtErSBWpf7U .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-NG4WlmtErSBWpf7U .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-NG4WlmtErSBWpf7U .marker{fill:#333333;stroke:#333333;}#mermaid-svg-NG4WlmtErSBWpf7U .marker.cross{stroke:#333333;}#mermaid-svg-NG4WlmtErSBWpf7U svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-NG4WlmtErSBWpf7U p{margin:0;}#mermaid-svg-NG4WlmtErSBWpf7U .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-NG4WlmtErSBWpf7U .cluster-label text{fill:#333;}#mermaid-svg-NG4WlmtErSBWpf7U .cluster-label span{color:#333;}#mermaid-svg-NG4WlmtErSBWpf7U .cluster-label span p{background-color:transparent;}#mermaid-svg-NG4WlmtErSBWpf7U .label text,#mermaid-svg-NG4WlmtErSBWpf7U span{fill:#333;color:#333;}#mermaid-svg-NG4WlmtErSBWpf7U .node rect,#mermaid-svg-NG4WlmtErSBWpf7U .node circle,#mermaid-svg-NG4WlmtErSBWpf7U .node ellipse,#mermaid-svg-NG4WlmtErSBWpf7U .node polygon,#mermaid-svg-NG4WlmtErSBWpf7U .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-NG4WlmtErSBWpf7U .rough-node .label text,#mermaid-svg-NG4WlmtErSBWpf7U .node .label text,#mermaid-svg-NG4WlmtErSBWpf7U .image-shape .label,#mermaid-svg-NG4WlmtErSBWpf7U .icon-shape .label{text-anchor:middle;}#mermaid-svg-NG4WlmtErSBWpf7U .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-NG4WlmtErSBWpf7U .rough-node .label,#mermaid-svg-NG4WlmtErSBWpf7U .node .label,#mermaid-svg-NG4WlmtErSBWpf7U .image-shape .label,#mermaid-svg-NG4WlmtErSBWpf7U .icon-shape .label{text-align:center;}#mermaid-svg-NG4WlmtErSBWpf7U .node.clickable{cursor:pointer;}#mermaid-svg-NG4WlmtErSBWpf7U .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-NG4WlmtErSBWpf7U .arrowheadPath{fill:#333333;}#mermaid-svg-NG4WlmtErSBWpf7U .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-NG4WlmtErSBWpf7U .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-NG4WlmtErSBWpf7U .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-NG4WlmtErSBWpf7U .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-NG4WlmtErSBWpf7U .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-NG4WlmtErSBWpf7U .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-NG4WlmtErSBWpf7U .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-NG4WlmtErSBWpf7U .cluster text{fill:#333;}#mermaid-svg-NG4WlmtErSBWpf7U .cluster span{color:#333;}#mermaid-svg-NG4WlmtErSBWpf7U div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-NG4WlmtErSBWpf7U .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-NG4WlmtErSBWpf7U rect.text{fill:none;stroke-width:0;}#mermaid-svg-NG4WlmtErSBWpf7U .icon-shape,#mermaid-svg-NG4WlmtErSBWpf7U .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-NG4WlmtErSBWpf7U .icon-shape p,#mermaid-svg-NG4WlmtErSBWpf7U .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-NG4WlmtErSBWpf7U .icon-shape .label rect,#mermaid-svg-NG4WlmtErSBWpf7U .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-NG4WlmtErSBWpf7U .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-NG4WlmtErSBWpf7U .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-NG4WlmtErSBWpf7U :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Token IDs
batch, seq_len
例: 32, 128
Embedding Layer
Token Embeddings
batch, seq_len, d_model
例: 32, 128, 512
Position Encoding
1, seq_len, d_model
例: 1, 128, 512
+
最终输入
batch, seq_len, d_model
例: 32, 128, 512
本章总结
| 步骤 | 输入 | 输出 | 作用 |
|---|---|---|---|
| Tokenizer | 文字 | Token ID | 文字→整数 |
| Embedding | Token ID | 向量 | 整数→语义向量 |
| Position Encoding | 向量 | 向量+位置 | 告诉模型顺序 |
本章思考题
- 为什么 Transformer 需要显式的 Position Encoding,而 RNN 不需要?
- 如果去掉 Position Encoding,Transformer 会有什么问题?
- BPE 和 WordPiece 的主要区别是什么?
- 为什么 RoPE 比绝对位置编码更适合长序列?
下一章预告
下一章我们进入 Transformer Block。
这是整本书最核心的部分,我们将看到:
- Self-Attention 是如何计算的?
- Residual 为什么能防止梯度消失?
- LayerNorm 在哪里?
- Feed Forward 的作用是什么?