AI Infra学习之旅-从序列建模到文本向量化
AI Infra学习之旅-从序列建模到文本向量化
这是“Transformer 原理深讲系列”的第 1 篇。
这一篇不急着讲公式,也不急着讲多头注意力,而是先把两个最根本的问题讲清楚:
为什么需要 Transformer?文本为什么能进入神经网络?
如果这两个问题没想透,后面的 Q/K/V、Attention、FFN、KV Cache 都会变成“记术语”,而不是“理解结构”。
一、为什么需要 Transformer:先从序列建模的问题说起
语言天然是序列。
一句话不是一堆无序词的集合,而是一个有前后关系、有依赖结构、有局部搭配和长程关联的排列。例如:
- “狗咬人”
- “人咬狗”
出现的词几乎一样,但顺序一变,意思就完全不同。
因此,处理语言时,模型至少要解决两件事:
- 每个位置上是什么内容
- 这些位置之间是什么关系
这就是序列建模的核心。
二、Transformer 出现之前,主流序列模型是什么
在 Transformer 之前,主流序列模型主要是:
- RNN
- LSTM
- GRU
它们的共同特点是:按顺序一步一步处理 token。
如果输入序列是:
那么它们通常以这样的形式递推:
其中:
- (x_t) 是当前输入
- (h_{t-1}) 是上一步隐藏状态
- (h_t) 是当前步新的隐藏状态
这个形式说明了一件事:
第 (t) 步必须依赖第 (t-1) 步。
这使得 RNN 系列模型非常符合人的直觉:
语言是一串东西,所以模型也按顺序一个个往后读。
但这个直觉在工程和数学上会带来很明显的问题。
三、RNN / LSTM / GRU 的三个核心局限
1. 很难并行
由于:
所以要算第 (t) 步,必须先算完第 (t-1) 步。
这意味着同一层上不同时间步无法同时计算。
而现代 GPU 最擅长的事情恰恰是:
- 大规模并行矩阵运算
- 高吞吐批量计算
RNN 的这种时间依赖使它很难像矩阵那样一次性并行展开整段序列。
结果就是:
- 训练速度慢
- 序列越长越慢
- 很难充分发挥 GPU 的并行优势
2. 长距离依赖难学
看一句英文:
The animal didn’t cross the street because it was too tired.
这里的 “it” 指代 “the animal”。
再看一句:
The animal didn’t cross the street because it was too wide.
这里的 “it” 指代 “the street”。
模型想正确理解 “it”,就必须把它和前面较远位置的词建立联系。
这就是长距离依赖问题。
在 RNN 里,前面的信息想影响后面的词,必须通过隐藏状态一层层往后传:
信息传得越远,就越容易:
- 衰减
- 扭曲
- 被后续新信息覆盖
从反向传播角度看,这对应经典的:
- 梯度消失
- 梯度爆炸
虽然 LSTM / GRU 通过门控机制缓解了这个问题,但并没有从结构上消除它。
3. 历史信息都被压进一个递推状态里
RNN 的思路本质上是:
把前面所有历史都压进当前状态 (h_t) 里。
也就是说,第 (t) 个位置的状态 (h_t),既要表示当前输入,又要尽量保留前面所有历史信息。
这相当于让一个固定维度的向量去承担越来越长上下文的压缩表达。
短序列还可以,长序列就会越来越吃力。
所以即使 LSTM 比普通 RNN 强很多,它依然没有改变一个根本事实:
历史信息还是要通过递推状态一路传下去。
四、Transformer 的根本突破:不要“传话”,而要“直接看”
面对上面的三个问题,Transformer 的核心思想非常直接:
不要让信息只能沿着时间链条一格一格传递,而是让每个位置直接去看整个序列中所有位置。
这就是 Attention 的思想。
RNN 更像:
我当前只能依赖上一步传给我的摘要。
Transformer 更像:
我当前这个位置,可以直接根据需要去查看全局上下文中所有位置的信息。
这带来两个决定性的变化:
- 任意两个位置之间的信息路径变短了
- 整段序列的很多计算可以并行化了
五、为什么说 Transformer 本质上是“全局交互”而不是“链式传递”
如果从图结构角度看:
- RNN 更像一条链
- Transformer 的 Self-Attention 更像一个全连接图
在链式结构里,如果第 1 个词想影响第 50 个词,它必须跨越很多步。
但在 Self-Attention 里,只要相关性高,第 50 个位置可以一步直接关注第 1 个位置。
这使得:
- 长距离依赖更容易建模
- 梯度传播路径更短
- 表示之间的交互更灵活
所以 Transformer 最本质的变化,不是“用了一个新公式”,而是:
把序列建模的主路径,从递推传递改成了全局关系建模。
六、为什么 Transformer 更适合大规模训练
Transformer 的另一个革命性优势,是它更适合现代硬件。
即使语言建模在逻辑上仍然有因果方向,Transformer 训练时仍然可以把整段序列组织成大矩阵运算。
这意味着:
- 不同位置的表示计算可以在同一层内并行展开
- 更适合 GPU / TPU 这类并行硬件
- 更容易扩展到大模型、大数据、大 batch
从工程角度看,这比“是否更聪明”还重要。
因为大模型时代真正决定胜负的,不只是结构有没有道理,而是:
它能不能被高效地放大。
Transformer 恰恰非常适合被放大。
七、Transformer 也不是没有代价
Transformer 解决了 RNN 的旧问题,同时也引入了自己的新问题。
最典型的是:
1. 标准 Attention 的复杂度高
如果序列长度是 (n),attention 要计算一个:
的关系矩阵。
这意味着长上下文时,计算量和显存开销都很可观。
2. Decoder-only 模型推理天然串行
虽然训练能并行,但生成时未来 token 尚不存在,所以仍然必须一个 token 一个 token 地往后生成。
3. KV Cache 会成为系统中心资源
因为 attention 要不断使用历史上下文的 Key / Value,所以推理时必须缓存它们。
上下文越长,缓存压力越大。
也就是说:
Transformer 不是没有问题,而是把问题从“递推链条难训练”换成了“全局注意力难部署”。
而现代推理系统的大量优化,正是围绕这些新问题展开的。
八、到这里你应该真正记住的第一结论
如果把“为什么需要 Transformer”压缩成一句话,那就是:
因为传统循环序列模型在并行效率、长距离依赖和信息压缩路径上都有先天限制;Transformer 通过 attention 让每个位置可以直接访问全局信息,从而大幅改善了序列建模能力,并且更适合现代大规模并行训练。
这才是 Transformer 出现的真正背景。
九、但 Transformer 再强,也要先回答一个更基础的问题:文本怎么进入网络
上面我们其实只解决了“为什么需要这种结构”,但还没有回答另一个根本问题:
语言是字、词、子词、标点,它们都是符号。
神经网络只能处理数值。
那文本是怎么进模型的?
这就是“文本向量化”的问题。
很多人学 Transformer 时一上来就看 attention,结果在最前面的输入表示上其实没有真正想透。
如果不想清楚:
- token 是什么
- 词表是什么
- token id 是什么
- embedding 到底是什么
那后面的所有矩阵乘法都会变得很悬浮。
所以接下来我们就从最底层讲:
文本为什么能变成数字。
十、为什么不能把文字直接丢给网络
神经网络的基本运算是:
- 加法
- 乘法
- 向量点积
- 矩阵乘法
- 非线性激活
这些都只对数值有意义。
而原始文本是字符串,例如:
- “我”
- “喜欢”
- “Transformer”
这些对网络来说不是数值对象。
所以必须先经过一层离散化处理。
十一、第一步:把文本切成 token
原始文本不会直接作为“整句话”进入模型,因为整句话的可能性几乎无限。
所以模型需要一个更小、更稳定的基本单位。
这一步叫 tokenization。
现代模型常见的 token 可以是:
- 单字
- 单词
- 子词(subword)
- 标点
- 特殊符号
之所以很多模型喜欢用 子词,是因为它能同时兼顾:
- 词表大小可控
- 对未登录词有更好泛化
- 不至于像按字符切那样过碎
例如一句话:
Transformer 非常强大
可能会被切成:
也可能在别的词表下切成:
切分方式取决于 tokenizer 和词表设计。
十二、第二步:token 变成 token id
tokenizer 切出 token 之后,会去查词表,把每个 token 映射成一个整数编号。
例如:
- “Transformer” → 3051
- “非常” → 782
- “强” → 116
- “大” → 91
那么刚才那句话就变成:
这时候文本已经变成一串整数了。
但注意:
这串整数仍然只是索引,并不具备真正的语义几何意义。
例如:
- “猫” = 17
- “狗” = 18
- “宇宙” = 19
这不代表“狗”和“猫”比“狗”和“宇宙”更接近。
编号只是编号,不是语义坐标。
所以 token id 只是中间层,不是最终表示。
十三、第三步:token id 通过 embedding 变成向量
真正让文本进入神经网络的是 embedding。
设词表大小是 (V),模型维度是 (d_{\text{model}}),那么会有一个可学习矩阵:
其中:
- 每一行对应一个 token
- 每一列对应向量的一个维度
如果某个 token id 是 (i),那么它的 embedding 就是矩阵第 (i) 行:
所以 embedding 的本质就是:
一个可学习的查表矩阵。
十四、从线性代数角度看 embedding
如果把 token id 对应成 one-hot 向量 (e_i),那么 embedding 可以写成:
也就是说:
- one-hot 向量选中矩阵中的某一行
- 那一行就是这个 token 的向量表示
所以 embedding 在数学上,本质上是:
把离散符号通过一个可学习线性映射,送进连续向量空间。
这非常关键,因为从这一刻开始,语言才真正变成神经网络可以操作的对象。
十五、为什么 embedding 能逐渐学出“语义”
embedding 一开始通常是随机初始化的。
但在训练中,它会随着任务目标不断更新。
如果某些 token 经常出现在相似上下文里,那么它们的 embedding 往往会逐渐靠近。
例如:
- “猫”和“狗”可能在很多上下文里行为相似
- “北京”和“上海”也可能在某些方向上更接近
所以 embedding 最终不是简单的“随机查表”,而是形成一个高维语义空间:
- 相近语义的 token 在空间中更接近
- 不同功能的 token 会占据不同区域
- 某些关系甚至能表现为向量方向差异
所以 embedding 的本质,不只是“把文字变成数字”,而是:
把语言符号嵌入一个可计算的几何空间。
十六、一个句子最终如何变成矩阵
如果一句话有 (n) 个 token,每个 token 的向量维度是 (d_{\text{model}}),
那么整句话会变成一个矩阵:
也就是说:
- 每一行是一个 token 的向量
- 每一列是这个 token 的某个特征维度
例如:
- 序列长度 (n=4)
- 模型维度 (d_{\text{model}}=6)
那么句子就会变成:
从这里开始,文本才真正进入了 Transformer 的矩阵计算世界。
十七、但到这里还缺一个决定性的东西:顺序
虽然文本已经变成向量矩阵,但这些向量目前只表达了:
- token 是什么
还没有表达:
- token 在第几个位置
- 谁在前,谁在后
- 位置之间的距离结构
换句话说,embedding 只回答了:
“它是什么?”
没有回答:
“它在哪里?”
而 Transformer 的 attention 本身并不会天然理解顺序。
所以接下来必须做一件事:
给这些向量加入位置信息。
这正是下一篇要讲的内容:位置编码。
十八、本篇真正要记住的两条主线
第一条主线:为什么需要 Transformer
- RNN / LSTM / GRU 在并行、长依赖和递推状态压缩上有先天限制
- Transformer 用 attention 把“链式传递”改成“全局交互”
- 它更适合大规模并行训练,也更容易扩展
第二条主线:文本为什么能进入 Transformer
- 文本先经过 tokenizer 切成 token
- token 再映射成 token id
- token id 通过 embedding 矩阵变成连续向量
- 句子最终变成一个矩阵,进入后续网络层
十九、用一句话压缩本篇
Transformer 之所以会出现,是因为传统循环序列模型在并行效率和长距离依赖上存在结构性限制;而文本之所以能进入 Transformer,是因为它先被离散化成 token id,再通过 embedding 映射到可计算的连续向量空间。
下一篇预告
下一篇进入真正的 Transformer 内核,主题是:
位置编码为什么必须存在
会重点讲清楚:
- 为什么 embedding 还不够
- 为什么 attention 本身天然不知道顺序
- 位置编码到底在解决什么问题
- 为什么位置编码通常和 token embedding 直接相加
- 原始 Transformer 的正弦余弦位置编码到底是什么意思
