简介:面向自然语言处理学习者与研究者,这份资源是 NIPS 2017 经典论文《Attention is All You Need》的中文翻译文档,聚焦自注意力机制与 Transformer 架构,适合希望绕过英文原文、快速把握序列转导模型核心思想的读者。压缩包内共 1 个 docx 文件,约 856KB,完整呈现论文摘要、引言、背景、模型架构及各子层说明,并保留缩放点积注意力、多头注意力等关键公式与实验数据。译文覆盖 WMT 2014 英德、英法翻译任务中 28.4 与 41.0 BLEU 的结果对比,以及编码器-解码器堆栈、残差连接与层归一化等实现细节,便于对照原文精读、整理笔记或作为组会分享材料。目前已有 1189 人学习,适合作为入门 Transformer 与自注意力机制的第一手中文参考资料。
1. 到底什么是 Transformer:一个不用“排队”的翻译工厂
如果你最近在看 AI 相关的资料,大概率会被一个词反复砸中:Transformer。它听起来像个变形金刚,实际上是一篇论文提出的网络架构名字,这篇论文的标题就叫《Attention Is All You Need》。很多人第一次听到“自注意力”“多头注意力”这些词就懵了,觉得这是不是又一套玄学。其实你可以先记住一句话:Transformer 是一种完全靠“注意力”来理解句子、不再靠“一个字一个字往后读”的模型架构。
打个比方,传统的循环神经网络读句子像老式流水线,必须从第一个词开始,读完第一个才能读第二个,工人只能排队干活;而 Transformer 像把整句话摊在一张大桌子上,每个词都能同时看到其他所有词,自己判断该重点看谁。这个“同时看”的本事,就是 self-attention(自注意力)。它带来的直接好处是训练可以大规模并行,速度更快,长距离的依赖关系也更容易学到。搞懂它,你再看今天各种语言模型、翻译工具、文本生成,就不会一头雾水。
2. 为什么非要换掉循环网络:顺序计算这道坎
2.1 循环网络的老毛病:必须一步一步来
在 Transformer 出现之前,处理语言这类序列数据的主流做法是循环神经网络,尤其是 LSTM 和门控循环单元。它们的思路很直观:把句子当成一条时间线,读第 t 个词的时候,要依赖第 t-1 个词算出来的隐藏状态。这就像你读一本悬疑小说,必须按页码顺序读,不能跳着看,因为后面的情节依赖前面的线索。
问题也出在这里。这种“按顺序算”的机制天然排斥并行化。训练时,一个批次里的句子长度参差不齐,内存又有限,你没法把很多长句子同时塞进去算。序列越长,这个瓶颈越明显。论文里说得很直白:这种固有的顺序性质排除了训练示例中的并行化,在长序列上变得至关重要。虽然研究者用因子分解技巧、条件计算等方法提升过效率,但顺序计算这个根本限制还在。
2.2 卷积网络也不完美:距离一远就费劲
另一条路是用卷积神经网络做序列转导,比如 ByteNet、ConvS2S 这些模型。卷积的好处是能并行,所有位置一起算。但它有个代价:两个位置离得越远,要把它们关联起来需要的操作层数就越多。ConvS2S 是线性增长,ByteNet 是对数增长。通俗地说,句子开头的主语和结尾的动词隔了二十个词,卷积网络得叠很多层才能让它们“碰上面”,远距离依赖学起来就吃力。
论文里给了一张对比表,把自注意力、循环层、卷积层放在一起比。自注意力每层的计算复杂度是 O(n²·d),顺序操作数是 O(1),任意两个位置之间的最大路径长度也是 O(1)。循环层顺序操作数是 O(n),路径长度 O(n);卷积层路径长度是 O(logk(n))。这组数字翻译成人话就是:自注意力让任意两个词之间的“沟通路径”最短,一步到位,而循环和卷积都得绕路。
2.3 自注意力的核心:让每个词自己决定看谁
那自注意力到底怎么工作?论文里的定义是:把查询和一组键值对映射到输出,查询、键、值、输出都是向量。输出是值的加权和,权重由查询和对应键的兼容性算出来。听着抽象,举个例子:翻译“动物没有过马路,因为它太累了”这句话,模型在处理“它”的时候,需要判断“它”指动物还是马路。自注意力让“它”这个位置发出一个查询,去和句子里每个词的键做匹配,发现“动物”的匹配度更高,于是给“动物”的值更大的权重。这样“它”的表示里就融入了“动物”的信息。
具体计算用的是缩放点积注意力:查询矩阵 Q 和键矩阵 K 做点积,除以 √dk 防止数值过大,再经过 softmax 得到权重,最后乘上值矩阵 V。论文里还提出多头注意力,用 h=8 组不同的线性投影并行做注意力,每组关注不同的子空间。这就像八个专家同时读同一句话,有人盯语法,有人盯语义,最后把意见汇总。单头注意力容易把不同层面的信息平均掉,多头则保留了多样性。
提示:缩放点积里的 √dk 不是随便加的。dk 太大时点积结果会很大,softmax 会被推到梯度极小的区域,训练容易卡住,除以 √dk 就是把这个数值拉回正常范围。
3. Transformer 的内部构造:编码器、解码器和位置编码
3.1 编码器和解码器:六层堆叠的分工
Transformer 整体还是编码器-解码器结构。编码器负责把输入序列映射成连续表示,解码器根据这个表示一个元素一个元素地生成输出。论文里编码器和解码器各由 N=6 个相同的层堆叠而成。编码器每层有两个子层:第一个是多头自注意力,第二个是逐位置的全连接前馈网络。每个子层周围都有残差连接,后面接层归一化,输出维度统一是 dmodel=512。
解码器多了一个子层,用来对编码器的输出做多头注意力,这叫编码器-解码器注意力。另外解码器的自注意力子层做了掩蔽,防止某个位置关注到它后面的位置。这个掩蔽很关键,因为生成是自回归的,预测第 i 个词时只能看已经生成的词,不能偷看答案。掩蔽的做法是把非法连接对应的 softmax 输入设成负无穷,softmax 之后这些位置的权重就变成零。
3.2 前馈网络和嵌入层:看起来简单但有讲究
每个层里还有一个前馈网络,对每个位置单独且相同地应用。它包含两个线性变换,中间夹一个 ReLU 激活,公式是 FFN(x)=max(0, xW1+b1)W2+b2。输入输出维度是 512,内层维度是 2048。论文里说这等价于核大小为 1 的两个卷积。虽然不同位置用的是同一套变换,但不同层之间的参数是独立的。
嵌入层负责把输入标记和输出标记转成 512 维向量。论文里有个细节:两个嵌入层和 softmax 前的线性变换共享同一个权重矩阵,嵌入层的权重还要乘以 √dmodel。共享权重是为了减少参数、让输入输出空间对齐,乘以 √dmodel 则是为了在数值上和位置编码的量级匹配。
3.3 位置编码:没有顺序信息就补进去
Transformer 没有循环也没有卷积,天生不知道词的先后顺序。所以论文在输入嵌入上加了位置编码。位置编码和嵌入维度相同,可以直接相加。论文用的是不同频率的正弦和余弦函数:偶数维用 sin,奇数维用 cos,波长从 2π 到 10000·2π 形成几何级数。
为什么选正弦函数而不是直接学一个位置嵌入?论文的解释是,对于任何固定偏移 k,PE(pos+k) 可以表示成 PE(pos) 的线性函数,模型更容易学到相对位置关系。而且正弦版本可能让模型外推到比训练时更长的序列。论文也试过学习式位置嵌入,结果几乎一样,最后选了正弦版。
import numpy as np def positional_encoding(max_len, d_model): # 初始化位置编码矩阵,行是位置,列是维度 pe = np.zeros((max_len, d_model)) position = np.arange(0, max_len)[:, np.newaxis] # 形状 (max_len, 1) div_term = np.exp(np.arange(0, d_model, 2) * -(np.log(10000.0) / d_model)) pe[:, 0::2] = np.sin(position * div_term) # 偶数维用 sin pe[:, 1::2] = np.cos(position * div_term) # 奇数维用 cos return pe # 参数说明:max_len 是最大序列长度,d_model 是嵌入维度(论文里是 512) # 输出 pe 的形状是 (max_len, d_model),可以直接和词嵌入相加这段代码把论文里的公式落成了可运行的实现。div_term 控制不同维度的波长,位置越靠后的维度波长越长。实际使用时,位置编码不参与训练,是固定算出来的,和词嵌入相加后一起送进编码器。
4. 常见误区与易混概念:别把注意力当成万能钥匙
4.1 自注意力不等于普通的注意力机制
很多人把自注意力和注意力机制混为一谈。注意力机制早就有了,比如 Bahdanau 注意力用在编码器-解码器之间,让解码器在生成每个词时关注输入序列的不同部分。但那种注意力是“跨序列”的,查询来自解码器,键和值来自编码器。自注意力是“同序列”的,查询、键、值都来自同一个地方。论文强调 Transformer 是第一个完全依靠自注意力来计算输入和输出表示的转导模型,不靠序列对齐的循环或卷积。这个区别很关键:普通注意力是辅助模块,自注意力是主干。
4.2 多头注意力不是简单地把头加起来
初学者容易以为多头注意力就是把八个头的输出直接拼起来完事。实际上每个头有自己独立的线性投影矩阵,把查询、键、值投影到低维子空间,各自做注意力,最后把结果拼接再经过一次线性投影。论文里 h=8,每个头的 dk=dv=dmodel/h=64。因为每个头维度降低,总计算成本和全维单头注意力差不多。多头的作用是让模型同时关注不同位置的不同表示子空间,单头容易把这些信息平均掉。
4.3 位置编码不是可有可无的装饰
有人觉得位置编码只是锦上添花,去掉也能跑。实际上没有位置编码,Transformer 对词序完全不敏感,“狗咬人”和“人咬狗”在它眼里是一样的。论文用正弦函数是为了让模型学到相对位置,并且可能外推到更长序列。虽然后来也有学习式位置嵌入取得差不多效果,但位置信息本身是必需的,不是可选项。
4.4 BLEU 分数高不等于翻译完美
论文里报的 28.4 BLEU(英德)和 41.0 BLEU(英法)是机器翻译的自动评估指标,衡量生成译文和参考译文的 n-gram 重叠程度。BLEU 高说明整体质量好,但它不理解语义,也不代表每个句子都翻对了。论文自己也说,这些超参数是在开发集上实验后选的。看论文结果时要明白,BLEU 是统计指标,不是人工评测的替代品。
4.5 训练成本低是相对而言
论文说基础模型在 8 个 P100 上训练 12 小时,大模型训练 3.5 天,相比之前的最好结果训练成本只是一小部分。但这是相对当时的最先进模型说的,不是绝对意义上的“便宜”。Transformer 的优势在于可并行性,能把 GPU 吃满,而不是说随便一台机器就能训。理解这一点,才不会对“训练成本低”产生不切实际的期待。
5. 什么时候该用 Transformer 的思路,什么时候别硬套
5.1 适合的场景:长依赖、可并行、数据量够
Transformer 最擅长的场景是序列到序列的任务,尤其是句子较长、依赖关系跨度大的情况。机器翻译是论文的主战场,但它的思路后来被扩展到文本摘要、问答、语言建模等任务。判断要不要用,可以看三个信号:一是任务里存在长距离依赖,比如文档级翻译、长文本理解;二是训练数据量足够大,因为 Transformer 参数多,数据少容易过拟合;三是有并行计算资源,能发挥它训练快的优势。
论文里还提到一个细节:当序列长度 n 小于表示维度 d 时,自注意力层比循环层更快。机器翻译里常用的词块表示、字节对编码,句子表示维度通常大于序列长度,所以自注意力有优势。但如果你的任务序列特别长、维度又低,这个优势可能不明显。
5.2 不适合的场景:超长序列、小数据、强顺序约束
自注意力的计算复杂度是 O(n²·d),序列长度翻倍,计算量翻四倍。处理超长文档、高分辨率图像、长音频时,直接套全局自注意力会很吃力。论文自己也提到,可以把自注意力限制在大小为 r 的邻域内,把最大路径长度增加到 O(n/r),这是后来很多高效注意力变体的起点。所以遇到超长输入,别硬上全局注意力,得考虑局部化或稀疏化。
另外,数据量很小的任务要谨慎。Transformer 没有循环网络那种归纳偏置,它靠大量数据自己学出顺序和结构。数据少的时候,循环网络或卷积网络可能更稳。论文里做了消融实验,发现 dropout 对防止过拟合非常有帮助,基础模型用 Pdrop=0.1,大模型英法任务用 0.1 而不是 0.3。这些细节说明,Transformer 的效果很依赖正则化和数据规模。
5.3 一个具体判断例子
假设你要做一个中英术语翻译工具,句子平均长度 30 个词,训练语料有几十万句对,手头有几张 GPU。这种情况 Transformer 是合适的选择:序列不算超长,数据量够,并行训练能缩短周期。但如果你要做的是实时逐字输入的法条匹配,输入可能长达几千字,而且要求低延迟,那就得掂量全局自注意力的开销,考虑滑动窗口或分层结构。
我自己的习惯是,每次遇到一个新序列任务,先问三个问题:序列多长、数据多少、有没有并行资源。三个答案都偏向“中等长度、数据充足、有 GPU”,才优先考虑 Transformer 架构;只要有一个明显不满足,就先回到循环网络或卷积方案做基线,再决定要不要换。这套判断不是绝对的,但能避免一上来就套最热架构然后翻车的尴尬。
注意:论文里的超参数(N=6、dmodel=512、h=8、dff=2048、warmup_steps=4000)是针对当时机器翻译任务调出来的,不是放之四海皆准的默认值。换任务时这些数要重新实验,别直接照搬。
这份中文翻译版本把论文的模型架构、训练细节、消融实验和结果对比都保留了下来,适合想快速读懂原论文又不想被英文长句卡住的人。如果你正在补 NLP 的基础,或者想搞清楚 self-attention 到底怎么算、多头注意力为什么有效、位置编码为什么用正弦函数,这份资料能让你少走不少弯路。希望帮到你。
本文还有配套的精品资源,点击获取