Skip to content

Transformer 的直觉

上一节我们看到,简单神经网络处理语言有三个硬伤:要求固定长度、不在乎顺序、抓不住远距离关系。我们需要一种全新的网络结构来解决这些问题。Transformer 就是答案。

它的核心创新是一个叫"注意力"的机制。这一节我们先建立直觉,不碰公式,不写代码。

注意力机制:每个词都在"看"其他词

小明要去图书馆写一篇关于蓝鲸的报告。他走进图书馆,脑子里只有一个问题:"蓝鲸吃什么?体型有多大?"

图书馆里有几万本书。如果小明一本一本地从头翻到尾,翻到明年也写不完。他需要一种聪明的办法。

先看看笨办法:把每本书都翻开,每本花同样的时间读。读了 200 本书,发现 190 本跟蓝鲸毫无关系——有烘焙教程、世界历史、gardening 指南。真正有用的只有几本关于海洋生物的书。时间全浪费在了无关的书上。

聪明办法是先看标签:每本书的脊背上都贴着标签,写着这本书的主题。小明拿着自己的问题("蓝鲸吃什么")去和标签逐一比对。"海洋生物"——匹配!"烘焙教程"——不匹配,跳过。找到几本相关的书后,小明重点阅读这些书里的内容。最后把自己从几本相关书里收集到的信息整合起来,完成了报告。

注意力机制做的也是同一件事。

查资料的比喻

注意力机制里最关键的三个概念是 Query、Key、Value。用图书馆的场景来对应:

Query(查询) = 小明手里的小纸条,上面写着"蓝鲸的体型数据"
Key(键)     = 每本书脊背上的标签:"海洋生物""烘焙教程""世界历史"
Value(值)   = 翻开书后看到的正文内容

小明拿着纸条(Query)走到书架前,逐一对比每本书的标签(Key)。标签和问题越匹配,他就越关注那本书,翻开读里面的内容(Value)。最后把自己从几本相关书里收集到的信息融合起来,完成了关于蓝鲸的报告。

注意力机制里也是一样的。句子里的每个词都会准备自己的 Query、Key、Value:

  • 拿着自己的 Query(问题)去和其他词的 Key(标签)对比
  • 找到相关的词之后,从它们的 Value(内容)里读取信息
  • 最后把自己收集到的信息融合起来,更新自己的表示
每个词拿着自己的问题
  -> 和其他词的标签逐一对比
  -> 越相关的词,读取越多
  -> 融合收集到的信息,变成新的自己

回到句子:每个词都是小明

来看一个具体的句子:

text
一只蓝色的怪兽走进了森林

句子里的每个词都像小明一样,拿着自己的问题去和其他词的标签对比。

当处理到"怪兽"的时候,它会问自己:"什么样的怪兽?"

"怪兽"拿着自己的问题去对比:
  "一只"的标签 -> 匹配度低(只是数量词)
  "蓝色"的标签 -> 匹配度高!回答了"什么样的"
  "怪兽"的标签 -> 匹配度低(自己不需要了解自己)
  "走进"的标签 -> 匹配度低(是动作,不修饰自己)
  "森林"的标签 -> 匹配度低(是地点,不修饰自己)

结果:"怪兽"从"蓝色"那里读取了大量信息
融合后:"怪兽"变成了"蓝色+怪兽"的理解

当处理到"走进"的时候,它会问自己:"走进了哪里?"

"走进"拿着自己的问题去对比:
  "一只"的标签 -> 匹配度低
  "蓝色"的标签 -> 匹配度低
  "怪兽"的标签 -> 匹配度中等(知道是谁走进)
  "走进"的标签 -> 匹配度低(自己不需要了解自己)
  "森林"的标签 -> 匹配度高!回答了"走进了哪里"

结果:"走进"从"森林"那里读取了大量信息
融合后:"走进"变成了"走进+森林"的理解

用一张表格来直观地看每个词的注意力分配:

当前词    看"一只"  看"蓝色"  看"怪兽"  看"走进"  看"森林"
---------------------------------------------------------
怪兽       10%       70%       5%       10%       5%
走进       5%        5%        30%       5%        55%
森林       5%        10%       15%       60%       10%

每一行的百分比加起来是 100%,代表这个词把注意力分配给了其他哪些词。可以看到"怪兽"主要看"蓝色","走进"主要看"森林","森林"主要看"走进"——这正是它们之间语义关系的体现。

注意一个细节:小明在图书馆是主动去看别的书,而注意力机制里每个词既当"小明"(主动查看别人),也当"被查看的书"(被别人查看)。每个词同时扮演两个角色——这是注意力机制和图书馆场景唯一的不同。但核心直觉是一样的:通过匹配问题(Query)和标签(Key),从相关内容(Value)中读取信息,然后融合。

只能看前面的:因果 Mask

现在有一个问题:在生成文本的时候,模型是一个词一个词往后写的。写到第三个词的时候,第四个词还没生成出来呢。

所以模型必须遵守一条规则:只能看前面的词,不能偷看后面的。

text
写到"怪兽"的时候,可以看"一只""蓝色""怪兽"
但不能看"走进""森林"

这条规则通过一个叫"因果 Mask"的机制来保证。它像一块遮布,把当前位置后面的词全部遮住,不让当前词看到。

text
"一只" 的视野:一只
"蓝色" 的视野:一只、蓝色
"怪兽" 的视野:一只、蓝色、怪兽
"走进" 的视野:一只、蓝色、怪兽、走进
"森林" 的视野:一只、蓝色、怪兽、走进、森林

你可能会觉得这条规则是限制。但仔细想想,它其实和模型的任务完美对应——模型的任务就是"根据前面的词,预测下一个词"。只能看前面的词,这正是它该做的事。

位置编码:告诉模型顺序

注意力机制有一个盲区:它不关心词的顺序。

对注意力机制来说,"猫追狗"和"狗追猫"看起来是一样的。因为每个词都在看其他所有词,不管谁在前谁在后。这就好比你把书架上的书重新排了个顺序,但每本书的标签和内容都没变,你查资料的结果其实不会变。

但顺序对语言来说太重要了。"猫追狗"和"狗追猫"的意思完全相反。

所以我们需要额外告诉模型:每个词在什么位置。

解决方法很直觉——给每个位置加一个"位置标签"。

text
位置 0 的词 = "一只" + 位置标签 0
位置 1 的词 = "蓝色" + 位置标签 1
位置 2 的词 = "怪兽" + 位置标签 2
...

这样,即使两个词本身相同,出现在不同位置时,模型也能区分它们。这个"位置标签"就是位置编码。

位置编码具体怎么生成、用什么公式,不同模型有不同的做法,但目的都一样:

text
让模型知道每个词在哪里,以及词和词之间的相对距离。

Decoder-only:一个词一个词地生成

现在把上面的几个概念串起来,看看一个完整的大语言模型长什么样。

现代大语言模型几乎都采用 Decoder-only 结构,也就是"只有解码器"的结构。它的核心思路非常直觉:

text
根据前面的词,预测下一个词。

这正好就是语言模型的定义。所以 Decoder-only 结构和语言模型的任务是天然匹配的。

整体结构可以概括为"一堆相同的模块堆叠在一起"。每个模块(叫一个 Decoder Block)内部做两件事:

text
第一步:自注意力
  每个词去看其他词(只能看前面的),理解上下文关系

第二步:前馈网络
  在理解了上下文之后,进一步加工每个词的信息

用一句话概括每个 Decoder Block 做的事:

text
读前文 -> 理解关系 -> 加工信息

很多个这样的 Block 堆在一起,每一层都在前一层的基础上进一步理解上下文、加工信息。层数越多,模型能捕捉到的关系就越复杂、越微妙。

最后,经过所有 Block 处理之后,模型拿最后一个词的表示,去预测下一个词是什么。

整个过程画出来是这样的:

text
输入词序列
  -> 加上位置编码(告诉模型顺序)
  -> 通过 N 个 Decoder Block(每个 Block 做自注意力 + 前馈网络)
  -> 预测下一个词

回顾:Transformer 解决了三个问题

还记得上一节简单神经网络的三个局限吗?Transformer 一一解决了它们。

text
简单神经网络的问题       Transformer 的解法
------------------       ------------------------------
要求固定输入长度    -->  注意力机制天然支持任意长度
不在乎顺序          -->  位置编码告诉模型每个词在哪里
抓不住远距离关系    -->  注意力让任何两个词都能直接关联

第三点尤其重要。在注意力机制里,不管两个词隔了多远,它们之间都是一步直达的。不需要信号一层层传过去,不需要信息被中间的词稀释。每个词都可以直接"看到"其他任何词,直接判断它们之间的关系。

这就是 Transformer 的核心直觉。理解了注意力、因果 Mask、位置编码这三个概念,你就理解了现代大语言模型的基础架构。