第二季 · 第 59 章 不必记住全部,只需找到重要的部分标记本章已读大字阅读打印本章回到上次阅读位置《算法的故事》第二季 · 第六篇:会学习的算法——从机器翻译的软对齐,到2017年Transformer注意力机制的诞生第59章配图2014年9月1日。欧洲不来梅的一位研究者,与加拿大蒙特利尔的两位合作者,向arXiv提交了一篇论文。题目是:Neural Machine Translation by Jointly Learning to Align and Translate《通过联合学习对齐与翻译实现神经机器翻译》。作者是:德兹米特里·巴赫达瑙(Dzmitry Bahdanau)。曹京贤(Kyunghyun Cho)。约书亚·本吉奥(Yoshua Bengio)。这篇研究后来作为会议论文发表于2015年的ICLR。 [arXiv][Yoshua Bengio]他们面对的是一项已经困扰神经机器翻译研究者的问题。计算机能够读取一句英文。将它转换成一个向量。然后利用这个向量,尝试生成法文。但是,如果句子越来越长呢?如果一句话有五个单词,编码器也许能够保存大部分相关信息。如果有五十个单词?如果有一百个单词?一份固定长度的内部表示,是否足以支持解码器在每一个位置都获得所需的信息?设想输入是一句话:The little cat is sleeping on the sofa.如果模型准备翻译“猫”,它真正需要仔细查看的,是不是与cat相关的源语言位置?而如果它下一步准备翻译“沙发”,那么它又是否应该将更多注意力分配给sofa?这些不同的输出位置,为什么一定要使用一模一样的、固定的句子摘要?巴赫达瑙和合作者提出了一种新的神经机器翻译结构。编码器不再只提供一个最终的固定向量。而是为源句中不同位置产生一系列表示。解码器在生成每个目标词时,根据当前需要,对源语言的不同位置计算一组权重。再用这些权重形成当前的上下文向量。这样,模型就可以在翻译过程中改变自己关注的源语言位置。他们把这种过程描述为:Soft Search(软搜索)。或者:Soft Alignment(软对齐)。“软”并不是指算法不精确。而是指:它不必在每一步强制选择唯一一个源词。它可以为许多源语言位置分配不同大小的连续权重。所有权重相加为1。模型利用加权后的信息,预测当前目标词。而这些权重也能够通过反向传播,与整套翻译网络一起训练。这篇论文最重要的思想之一,可以概括成一句话:不必把所有源语言信息,永久压缩进同一个固定长度的句子向量;可以在需要时,重新计算哪些位置值得关注。原始论文并没有声称,这种结构能够无限制处理任意长的文本,也没有证明注意力权重一定对应真实的语言学词语对齐。但在其英语—法语翻译实验中,研究者观察到注意力模型的翻译质量改善,而且模型学到的一些对齐模式与人类直觉相符。 [Stanford CS224d]2014年,这还是一项解决机器翻译瓶颈的研究。三年后,另一组研究者将提出更加激进的想法。如果注意力已经能够帮助我们跨位置获取信息,那么:我们是否还需要让整个序列计算,始终沿着循环网络一个时间步、一个时间步地前进?2017年,一篇新论文给出了自己的回答。Attention Is All You Need《注意力就是你所需要的一切》。它提出了:Transformer。这项研究使用注意力机制作为网络的核心,构建不依赖传统循环结构的序列转换模型,并在当时的机器翻译实验中展示了训练并行性和翻译质量方面的优势。 [Google Research]但要理解这个发展过程,我们不能直接从那条著名公式开始。Attention(Q,K,V)=softmax(QK⊤dk)V\operatorname{Attention}(Q,K,V) = \operatorname{softmax} \left(\frac{QK^\top}{\sqrt{d_k}}\right)VAttention(Q,K,V)=softmax(dkQK⊤)V因为它不是凭空出现的。它背后有十多年甚至更早的对齐、序列学习与可微信息选择研究。我们首先要回到一个极其普通的问题。一句话翻译成另一种语言时,谁应该对应谁?第一幕:翻译不是逐字替换——为什么“对齐”是一项独立的计算问题?第59章配图假设输入:text复制代码The black cat sleeps.我们希望得到法文:text复制代码Le chat noir dort.为了便于观察,可以把对应关系大致表示为:text复制代码The → Le black → noir cat → chat sleeps → dort注意这里:英文是:text复制代码black cat而法文是:text复制代码chat noir词序发生了改变。因此,如果我们强制要求:输入的第1个词只对应输出的第1个词。输入的第2个词只对应输出的第2个词。就会得到错误的关系。真正的问题是寻找对应结构设源语言词序列为:x1,x2,…,xTx_1,x_2,\ldots,x_Tx1,x2,…,xT目标语言词序列为:y1,y2,…,yMy_1,y_2,\ldots,y_My1,y2,…,yM我们希望知道:在生成目标词:yty_tyt时,源语言的哪些位置:xjx_jxj提供了重要信息?例如,目标词:text复制代码noir与源语言:text复制代码black关系密切。但它们的位置不必相同。1990年代,统计机器翻译已经在研究对齐神经网络注意力出现之前,研究者已经使用统计模型研究双语句子之间的词语对应关系。1993年,Peter F. Brown等人发表:The Mathematics of Statistical Machine Translation: Parameter Estimation《统计机器翻译的数学:参数估计》。发表于《Computational Linguistics》第19卷第2期,第263—311页。其研究系统讨论了根据双语语料估计翻译和对齐模型参数的方法。这些研究后来与IBM Models等统计机器翻译方法紧密联系。这里必须区分两件事。1993年的统计对齐模型,不等于2014年的神经注意力机制。它们的训练目标、参数化方式和计算结构存在重要区别。但二者面对的核心语言问题具有联系:两种语言的词语并不总是一一对应,也不总是按照相同顺序出现。为什么不能只对齐一个词?因为真实语言中还存在:一对多翻译。多对一翻译。短语整体翻译。以及某些没有直接逐词对应的语法成分。例如:text复制代码I am hungry.和:text复制代码J'ai faim.它们表达相近的意思,但内部词语与语法结构并不逐项一致。因此,机器翻译中的对齐更适合被看作:一种用于组织和推断跨语言对应关系的统计结构。而不是对每个词都强行指定唯一、永远正确的译词。为什么神经网络需要重新研究这件事?因为上一章的编码器—解码器将输入句子变成向量。这使网络有机会端到端地学习翻译。但是,如果解码器只能依赖一个固定的句子摘要,它就很难显式区分:当前输出需要关注哪个源语言位置?于是,神经注意力将传统翻译中的“对齐问题”,改写成:在神经网络内部,怎样根据当前解码状态,计算可微的源位置权重?这项重新表示问题的方式,正是接下来的关键。第二幕:2013年,机器在写字时,也需要知道自己正在看句子的哪一部分第59章配图注意力机制的历史,不能只从2014年巴赫达瑙的论文开始。在此前的神经网络研究中,已经存在与可微信息定位有关的重要思想。一个很有代表性的例子,来自:亚历克斯·格雷夫斯(Alex Graves)。2013年8月4日,他提交:Generating Sequences With Recurrent Neural Networks《使用循环神经网络生成序列》。这篇研究包括:文本预测。在线手写轨迹建模。以及根据文字生成手写笔迹的实验。[arXiv]手写生成为什么需要“关注位置”?假设系统希望将:text复制代码hello变成一段连续手写轨迹。它不能只在开始时读到整个单词,然后不再关心当前写到了哪个字母。因为它需要知道:当前正在写h?还是e?是否已经写完l?是否应该继续移动到o?这种任务具有明确的顺序对应关系。Graves使用了窗口机制在其条件手写生成研究中,模型可以根据当前状态,形成一个对输入字符位置的平滑窗口。例如:当正在写第一个字母时,窗口集中在:text复制代码h后来逐渐转移到:text复制代码e以及后续字符。这使系统能够在逐点生成笔迹时,将当前运动与相应文字位置联系起来。这类方法,与后来的神经注意力共享重要思想:根据当前生成状态,对输入序列的不同位置分配连续权重。但不能把Graves的手写窗口与Bahdanau的神经翻译对齐模型说成完全相同的结构。它们的权重形式、训练任务与应用背景不同。这段历史说明了什么?注意力不是突然出现的一个名词。研究者长期需要解决:在大量输入信息中,当前计算应该使用哪一部分?手写生成希望知道当前应关注哪个字符。机器翻译希望知道当前目标词对应哪些源语言位置。图像描述希望知道当前词语对应哪些图像区域。这些任务逐渐汇聚到一种共同的数学思想:用可以学习的权重,把多个候选信息位置转换成当前需要的上下文表示。第三幕:2014年,Bahdanau究竟改变了编码器—解码器的哪一个部分?第59章配图现在,我们重新回到2014年。在前一章,我们已经认识一种经典的序列到序列结构。首先,编码器逐步读取源语言序列:x1,x2,…,xTx_1,x_2,\ldots,x_Tx1,x2,…,xT每读取一个词,更新内部状态:ht=f(ht−1,xt)h_t=f(h_{t-1},x_t)ht=f(ht−1,xt)最后得到一个向量:v=hTv=h_Tv=hT解码器再利用这份向量,逐步生成目标语言。固定向量可能成为瓶颈假设源句只有:text复制代码I am here.它的信息量相对较少。但如果源句非常长,而且包含多个从句、人物、地点和事件,那么,将全部信息压缩进一份固定维度表示,可能成为明显的限制。这里需要澄清:固定长度向量并不意味着它完全没有表达能力。连续向量可以表示复杂信息。问题在于:当输入长度和所需保留的细节不断增加时,依赖单一固定大小的压缩表示,可能使训练和信息提取变得困难。Bahdanau、Cho与Bengio在原始论文中,明确将这项固定向量瓶颈作为研究动机。[Stanford CS224d]不再只保留最后一个隐藏状态他们让编码器为源序列的每个位置,提供一个表示:h1,h2,…,hTh_1,h_2,\ldots,h_Th1,h2,…,hT而且,原始研究使用了:Bidirectional RNN(双向循环网络)。这意味着每个位置的表示可以结合:它前面的源语言信息。以及:它后面的源语言信息。因此:hjh_jhj并不是源词:xjx_jxj的简单词典编码。它是一份带有上下文信息的表示。论文将这些位置表示称作:Annotations(注释向量或位置表示)。解码器每次生成一个词,都重新选择上下文假设正在生成目标语言中的:yty_tyt解码器拥有前一时刻状态:st−1s_{t-1}st−1这时,注意力模块会比较:st−1s_{t-1}st−1与所有源语言位置表示:hjh_jhj计算每个位置的匹配分数:et,j=a(st−1,hj)\boxed{ e_{t,j}=a(s_{t-1},h_j) }et,j=a(st−1,hj)其中:aaa是一个具有可训练参数的评分函数。在Bahdanau等人的模型中,它由一个小型前馈神经网络实现。接着,利用Softmax将分数归一化为注意力权重:αt,j=exp(et,j)∑k=1Texp(et,k)\boxed{ \alpha_{t,j} = \frac{\exp(e_{t,j})} {\sum_{k=1}^{T}\exp(e_{t,k})} }αt,j=∑k=1Texp(et,k)exp(et,j)因此:αt,j>0\alpha_{t,j}>0αt,j>0而且:∑j=1Tαt,j=1\boxed{ \sum_{j=1}^{T}\alpha_{t,j}=1 }j=1∑Tαt,j=1最后,计算当前上下文向量:ct=∑j=1Tαt,jhj\boxed{ c_t=\sum_{j=1}^{T}\alpha_{t,j}h_j }ct=j=1∑Tαt,jhj这三个公式,就是2014年神经翻译软对齐机制最重要的数学结构。[Stanford CS224d]为什么每个输出位置都有不同的上下文?因为:et,je_{t,j}et,j取决于当前解码过程的状态。如果解码器准备生成:text复制代码猫可能得到一组分数。而如果准备生成:text复制代码睡觉就可能得到另一组分数。因此:αt,j\alpha_{t,j}αt,j与:ctc_tct都会随目标语言生成位置改变。图59-1:固定向量与动态注意力的区别固定向量v统一摘要源序列被编码为一份固定大小的向量。动态注意力cₜ逐步选择不同源位置按当前需求,贡献不同权重。为什么这项机制能够使用反向传播训练?因为从匹配分数到上下文向量的过程包含:指数运算。加法。除法。以及加权求和。这些计算在正常定义域内都是可微的。因此,解码器的翻译损失,不仅可以调整解码器参数,也能通过:ctc_tct反向传播到:注意力评分网络。以及:源语言编码器。这就是论文标题中:Jointly Learning(联合学习)的重要含义。研究者不需要先为每一句训练语料标注所有词对齐关系,才能让这套机制学习。它可以在翻译目标的训练过程中,学习一些有助于翻译的软对齐权重。但必须注意:这些权重是为改善整个翻译目标而学习的内部数值。它们不一定等于语言学意义上唯一正确的人工词语对齐标签。第四幕:Softmax——怎样让五个互不相同的分数变成一组注意力权重?第59章配图现在,先不考虑复杂的神经网络。只研究注意力公式中最重要的一步:Softmax。假设模型对三个源语言位置,计算出匹配分数:e1=0e_1=0e1=0e2=1e_2=1e2=1e3=2e_3=2e3=2我们希望把它们转成:非负。可比较。总和为1。的权重。为什么不能直接除以分数总和?如果直接使用:αi=ei∑jej\alpha_i=\frac{e_i}{\sum_j e_j}αi=∑jejei就可能遇到问题。例如:某些分数为负。甚至全部分数的和为0。而Softmax通过指数函数,将有限的实数分数转为正数。公式:αi=eei∑jeej\boxed{ \alpha_i= \frac{e^{e_i}}{\sum_j e^{e_j}} }αi=∑jeejeei注意,指数函数中的字母:eee是自然常数。而:eie_iei是第i个匹配分数。两者不是同一个量。第一步:计算指数e0=1e^0=1e0=1e1≈2.7183e^1\approx2.7183e1≈2.7183e2≈7.3891e^2\approx7.3891e2≈7.3891总和:Z≈11.1074Z\approx11.1074Z≈11.1074第二步:归一化α1=1Z≈0.0900\alpha_1=\frac1Z\approx0.0900α1=Z1≈0.0900α2=2.7183Z≈0.2447\alpha_2=\frac{2.7183}{Z}\approx0.2447α2=Z2.7183≈0.2447α3=7.3891Z≈0.6652\alpha_3=\frac{7.3891}{Z}\approx0.6652α3=Z7.3891≈0.6652因此:α≈(0.0900, 0.2447, 0.6652)\boxed{ \boldsymbol\alpha\approx (0.0900,\ 0.2447,\ 0.6652) }α≈(0.0900, 0.2447, 0.6652)三个权重相加:≈1\approx1≈1最大的匹配分数,得到了最大的注意力权重。但另外两个位置,并没有被完全丢弃。第三步:计算加权上下文假设三个位置对应的Value,是三个简单的标量:v1=1,v2=3,v3=5v_1=1,\quad v_2=3,\quad v_3=5v1=1,v2=3,v3=5那么:c=α1v1+α2v2+α3v3c=\alpha_1v_1+\alpha_2v_2+\alpha_3v_3c=α1v1+α2v2+α3v3代入:c≈0.0900×1+0.2447×3+0.6652×5c\approx 0.0900\times1+ 0.2447\times3+ 0.6652\times5c≈0.0900×1+0.2447×3+0.6652×5得到:c≈4.151\boxed{c\approx4.151}c≈4.151这个结果是:三个Value按照注意力权重形成的加权平均。对于向量Value,也完全采用同样思想,只是各向量分量分别相加。为什么最大分数没有得到100%的权重?因为Softmax不是硬选择。它将所有有限分数映射成严格正的权重。当一个分数远大于其他分数时,它对应的权重可以非常接近1。但只要其他分数仍然是有限值,它们的权重通常也大于0。这就是软注意力。与之相对:Hard Attention(硬注意力)可以涉及离散选择某个位置或区域,可能需要不同的训练估计方法。2015年Xu等人的视觉注意力研究,就明确比较了可微的软注意力与随机硬注意力训练路线。[Proceedings of Machine Learning Research]Softmax还有一项数值技巧如果匹配分数特别大:e1=1000e_1=1000e1=1000直接计算:exp(1000)\exp(1000)exp(1000)可能发生浮点溢出。所以,实际程序通常先减去所有分数中的最大值:m=maxieim=\max_i e_im=maxiei再计算:αi=exp(ei−m)∑jexp(ej−m)\boxed{ \alpha_i= \frac{\exp(e_i-m)} {\sum_j\exp(e_j-m)} }αi=∑jexp(ej−m)exp(ei−m)因为所有指数的分子分母都同时乘上:e−me^{-m}e−m所以,这项变化不会改变Softmax的数学结果。却可以显著改善数值稳定性。这将在后面的Python实战中成为一项必需的实现细节。第五幕:注意力不是“选出一个词”,而是计算一份随时变化的信息摘要第59章配图我们现在可以将注意力机制拆成三个步骤。先根据当前任务,计算每个候选位置的匹配分数。再使用Softmax形成权重。最后,将候选位置的信息做加权求和。看起来非常简单。但这里存在一项容易误解的区别。位置匹配得分高,并不意味着那个位置的Value就是我们最终希望输出的文本。源语言位置拥有自己的内部向量假设:text复制代码The little cat sleeps.编码器为每个词产生一个向量:h1,h2,h3,h4h_1,h_2,h_3,h_4h1,h2,h3,h4这些向量可能包含:词汇信息。周围上下文信息。语法关系。以及网络在训练过程中形成的其他特征。它们并不等于:text复制代码The=某个数字 little=某个数字 cat=某个数字这样简单的词典编号。注意力形成的是上下文表示对于当前目标位置t:ct=αt,1h1+αt,2h2+αt,3h3+αt,4h4\boxed{ c_t= \alpha_{t,1}h_1+ \alpha_{t,2}h_2+ \alpha_{t,3}h_3+ \alpha_{t,4}h_4 }ct=αt,1h1+αt,2h2+αt,3h3+αt,4h4即使:αt,3\alpha_{t,3}αt,3最大,也不意味着上下文向量就是:h3h_3h3因为其他位置通常仍然具有非零权重。例如:模型在生成“猫”时,可能同时利用:cat对应的表示。little提供的修饰信息。以及整句语法结构。这意味着:注意力并非简单地从数据库中返回一个唯一匹配结果。它更像是一项:根据当前查询,对候选信息执行动态加权汇总的可微运算。2014年的模型为什么仍然需要RNN?因为Bahdanau的原始研究不是Transformer。它仍然使用循环神经网络作为编码器和解码器。注意力机制只是改变了:解码器怎样从源语言位置表示中获取当前所需的上下文。编码器依然需要沿时间处理序列。解码器也依然具有顺序生成过程。因此,2014年的注意力研究虽然十分重要,却没有消除全部循环计算依赖。真正把:“注意力能不能成为序列模型的主要结构?”推向另一个阶段的,是2017年的Transformer研究。但在这之前,2015年还有两项非常重要的发展。第六幕:2015年,Luong提出两种不同的关注方式——看完整句,还是只看附近?第59章配图2015年9月。《EMNLP 2015》会议在葡萄牙里斯本举行。研究者:明胜梁(Minh-Thang Luong)。Hieu Pham。克里斯托弗·曼宁(Christopher D. Manning)。发表:Effective Approaches to Attention-based Neural Machine Translation《基于注意力的神经机器翻译有效方法》。论文第1412—1421页。[ACL Anthology]他们面对的问题是:注意力机制已经能够改善神经机器翻译。但是,究竟怎样设计注意力结构,才能使它计算有效并获得更好的翻译结果?Global Attention:观察全部源位置一种方法是:Global Attention(全局注意力)。生成某个目标词时,计算它与全部源语言位置之间的匹配程度。然后形成上下文向量。例如:text复制代码源句:The little cat is sleeping on the sofa.当生成目标词:text复制代码猫时,模型可以对全部源词计算分数。虽然cat可能最相关,但其他词语也参与候选比较。Local Attention:只处理附近的窗口另一种方法是:Local Attention(局部注意力)。模型先估计一个相关的源语言位置。然后,主要关注该位置附近的一段窗口。例如,在一段很长的源句里:text复制代码... The little cat is sleeping ...如果预计当前目标词主要对应:text复制代码cat那么,就可以围绕这一位置形成较小的注意力窗口。这可能减少需要逐个比较的位置数量。但也带来限制。如果真正需要的信息位于窗口之外,就可能被遗漏。原论文做了哪些比较?Luong等人的研究比较了:全局注意力。局部注意力。以及不同的匹配评分函数。其中包括:点积型评分。一般化双线性评分。以及拼接后通过神经网络评分等形式。论文在当时的英语—德语机器翻译任务中,报告了注意力方法带来的性能改进,并分析了不同注意力设计的影响。[APICe]这项工作很有意义,因为它说明:注意力不是单一、不可修改的固定公式。研究者可以改变:候选位置范围。匹配评分方式。上下文与解码状态的组合方式。以及位置预测机制。这些不同设计会改变:计算成本。训练性质。和模型表现。Bahdanau Attention与Luong Attention完全一样吗?不一样。二者都是神经机器翻译中的经典注意力方法,但它们使用的解码流程与常见评分公式存在区别。例如,Bahdanau式加性评分常写成:et,j=va⊤tanh(Wast−1+Uahj)e_{t,j} = v_a^\top\tanh(W_as_{t-1}+U_ah_j)et,j=va⊤tanh(Wast−1+Uahj)而Luong式点积评分可以写成:et,j=st⊤hje_{t,j}=s_t^\top h_jet,j=st⊤hj但这个直接点积要求两个向量的相关维度一致。如果使用一般化形式,则可以加入可训练矩阵:et,j=st⊤Whje_{t,j}=s_t^\top Wh_jet,j=st⊤Whj这些区别不仅涉及公式形式,还涉及:何时计算解码状态。以及怎样将上下文引入输出。因此,不能把任何采用Softmax加权求和的结构,都机械地称作完全相同的Bahdanau Attention。但它们共享一项核心思想。根据当前计算状态,为候选信息位置生成可学习的权重。第七幕:2015年,机器在描述照片时,也开始“看向”不同的区域第59章配图2015年7月。第32届国际机器学习大会(ICML)举行。研究者Kelvin Xu、Jimmy Ba、Ryan Kiros、Kyunghyun Cho等人发表:Show, Attend and Tell: Neural Image Caption Generation with Visual Attention《展示、关注并讲述:利用视觉注意力生成图像描述》。论文发表于《Proceedings of Machine Learning Research》第37卷,第2048—2057页。[Proceedings of Machine Learning Research]这项研究将注意力从语言翻译,进一步拓展到:图像描述生成。为什么描述一张图,也需要动态关注?想象一张照片。画面里有:一只鸟。一根树枝。一片树叶。以及远处的天空。模型希望生成:text复制代码A small bird is sitting on a branch.在生成:text复制代码bird时,与鸟身体有关的图像区域可能特别重要。而生成:text复制代码branch时,模型则可能更加依赖树枝对应的区域特征。如果每生成一个词,都只能使用同一份完整图像的固定向量摘要,那么,某些局部信息可能难以被充分利用。视觉注意力怎样工作?模型首先从图像提取一组空间特征。例如:a1,a2,…,aNa_1,a_2,\ldots,a_Na1,a2,…,aN其中每个:aja_jaj对应图像中某个空间区域的特征表示。然后,生成某个词时,计算对各区域的注意力权重:αt,1,…,αt,N\alpha_{t,1},\ldots,\alpha_{t,N}αt,1,…,αt,N形成视觉上下文:ct=∑jαt,jaj\boxed{ c_t=\sum_j\alpha_{t,j}a_j }ct=j∑αt,jaj这与机器翻译中的源词注意力具有相似的数学结构。区别在于:候选信息不再是单词位置。而是图像中的区域特征。论文为什么叫Show, Attend and Tell?因为它强调:看见图像。对相关区域分配注意力。然后生成描述。研究者还将注意力权重绘制成图像上的热力图,展示模型生成不同词语时,对图像不同区域的关注变化。但热力图只是对内部计算的一种可视化。不能因为某片区域颜色最亮,就断言模型的整个判断过程只依靠那片区域。软注意力与硬注意力再次出现论文研究了两类视觉注意力方法。一种是确定性的软注意力。通过对各区域特征加权求和,形成可微的上下文表示。另一种是随机的硬注意力,涉及选择或采样特定区域,并使用相应的随机训练目标。这说明:注意力机制不仅能够应用于语言。它还能够处理:空间位置。序列位置。以及其他带有可比较候选信息单元的结构。但不同任务里,注意力所表示的“位置”,可能有完全不同的物理或语义含义。从2014年到2015年,发生了什么重要变化?2014年的经典神经机器翻译注意力,主要解决:解码时如何选择相关源词表示。2015年的视觉注意力展示:同一种信息选择框架,也可以在图像区域上运作。由此,一项更一般的数学概念逐渐清晰。注意力并不依赖输入必须是文本。它依赖的是:我们拥有若干候选信息表示,并能够计算当前查询与它们之间的关联权重。而这个更一般的表述,将帮助我们理解2017年的Q、K、V结构。第八幕:Query、Key、Value——为什么2017年的注意力开始像一次可微的信息检索?第59章配图现在,我们来到整章最重要的概念转变。2017年的Transformer论文,将一种注意力计算概括为:输入一个Query。以及一组Key–Value对。通过Query与Key之间的匹配度,决定各个Value应该贡献多少权重。这就是:Query–Key–Value Attention。 [NeurIPS Papers]一个不涉及神经网络的比喻假设你来到图书馆。你希望寻找:text复制代码关于猫的书籍这是你的查询需求:Query。每本书拥有:书名。分类。索引标签。这些信息帮助你判断它与当前需求是否相关。它们相当于:Key。而真正需要取出的,是:书籍的内容。或者它的某种信息表示。这相当于:Value。因此:Query告诉我们当前希望寻找什么。Key帮助计算候选信息是否匹配。Value则是通过权重被汇总的实际信息。当然,这只是理解QKV的一种类比。真实Transformer中的Q、K、V,通常是训练得到的连续向量。不是人工写好的数据库字段。Q、K、V从哪里来?假设我们拥有一个位置表示矩阵:XXX那么,在自注意力中,可以通过三组可训练矩阵得到:Q=XWQ\boxed{Q=XW_Q}Q=XWQK=XWK\boxed{K=XW_K}K=XWKV=XWV\boxed{V=XW_V}V=XWV其中:WQ,WK,WVW_Q,W_K,W_VWQ,WK,WV是模型参数。如果:X∈RT×dmodelX\in\mathbb R^{T\times d_{\text{model}}}X∈RT×dmodel则一个注意力头通常有:Q∈RT×dkQ\in\mathbb R^{T\times d_k}Q∈RT×dkK∈RT×dkK\in\mathbb R^{T\times d_k}K∈RT×dkV∈RT×dvV\in\mathbb R^{T\times d_v}V∈RT×dvQuery与Key需要具有能够进行点积的相同最后维度:dkd_kdk而Value的维度:dvd_vdv不必等于:dkd_kdk为什么Query与Key要计算点积?对于一个Query:qqq和某个Key:kjk_jkj可以计算:sj=q⊤kj\boxed{s_j=q^\top k_j}sj=q⊤kj点积能够形成一种相容性评分。当两个向量在某些方向上具有较强的数值对应关系时,点积可能较大。但这里必须谨慎。点积不是无条件的语义相似度。它受到向量长度和方向共同影响。而Q、K本身又来自可训练投影。因此,它的意义最终取决于训练出来的参数及上下文。然后发生什么?我们得到一组分数:s1,s2,…,sTs_1,s_2,\ldots,s_Ts1,s2,…,sT然后使用Softmax:αj=esj∑kesk\boxed{ \alpha_j= \frac{e^{s_j}}{\sum_ke^{s_k}} }αj=∑keskesj最后,形成加权Value:o=∑jαjvj\boxed{ o=\sum_j\alpha_jv_j }o=j∑αjvj如果把所有Query同时组合成矩阵,就可以使用矩阵乘法并行计算。于是,注意力从:逐个目标词计算软对齐。进一步发展成:通过矩阵运算,对大量位置的查询和候选信息进行并行匹配与加权汇总。为什么Key与Value要分开?这是QKV设计中最值得理解的一点。一个位置应该:怎样被找到?与:被找到以后提供什么信息?不必使用完全相同的向量。Key承担匹配评分的职责。Value承担信息汇总的职责。通过不同的学习矩阵,模型可以分别学习:哪些特征适合判断相关性。哪些特征适合传递给后续计算。这比直接规定:“用一个向量同时完成全部任务。”拥有更灵活的表示方式。第九幕:手算QKV——三个向量怎样得到一份新的上下文?第59章配图现在,我们终于要亲手计算那条著名公式。Attention(Q,K,V)=softmax(QK⊤dk)V\boxed{ \operatorname{Attention}(Q,K,V) = \operatorname{softmax} \left( \frac{QK^\top}{\sqrt{d_k}} \right)V }Attention(Q,K,V)=softmax(dkQK⊤)V为了让所有数字都可以手工复核,我们将向量维度设成2。这里只有一个Query、三个Key和三个标量Value。这不是完整语言模型,而是标准注意力公式的最小计算实验。第一步:准备Query令:q=(2,0)\boxed{q=(\sqrt2,0)}q=(2,0)因为它有两个分量,所以:dk=2d_k=2dk=2第二步:准备三个Keyk1=(0,0)k_1=(0,0)k1=(0,0)k2=(1,0)k_2=(1,0)k2=(1,0)k3=(2,0)k_3=(2,0)k3=(2,0)第三步:计算点积分数对第一个Key:q⊤k1=0q^\top k_1=0q⊤k1=0对第二个Key:q⊤k2=2q^\top k_2=\sqrt2q⊤k2=2对第三个Key:q⊤k3=22q^\top k_3=2\sqrt2q⊤k3=22所以未缩放分数为:(0,2,22)(0,\sqrt2,2\sqrt2)(0,2,22)第四步:除以缩放因子因为:dk=2\sqrt{d_k}=\sqrt2dk=2所以:q⊤kjdk\frac{q^\top k_j}{\sqrt{d_k}}dkq⊤kj得到:(0,1,2)\boxed{(0,1,2)}(0,1,2)这正好与第四幕使用的Softmax例子相同。第五步:计算Softmax所以:α≈(0.0900, 0.2447, 0.6652)\boxed{ \boldsymbol\alpha \approx (0.0900,\ 0.2447,\ 0.6652) }α≈(0.0900, 0.2447, 0.6652)第六步:准备Value我们令:v1=1v_1=1v1=1v2=3v_2=3v2=3v3=5v_3=5v3=5最后:o=0.0900×1+0.2447×3+0.6652×5o= 0.0900\times1+ 0.2447\times3+ 0.6652\times5o=0.0900×1+0.2447×3+0.6652×5得到:o≈4.1504\boxed{o\approx4.1504}o≈4.1504图59-2:一次完整的Scaled Dot-Product Attention位置Key缩放分数权重Value1(0, 0)00.090012(1, 0)10.244733(2, 0)20.66525加权输出4.1504为什么要除以 dk\sqrt{d_k}dk?这是2017年Transformer论文中非常重要的设计细节。假设Query与Key的各个分量,在一个简化的随机模型中:均值为0。方差为1。各分量之间独立。那么:q⊤k=∑i=1dkqikiq^\top k=\sum_{i=1}^{d_k}q_ik_iq⊤k=∑i=1dkqiki其方差会随:dkd_kdk增长。在这些假设下:Var(q⊤k)=dk\operatorname{Var}(q^\top k)=d_kVar(q⊤k)=dk所以,点积的典型量级可能随维度变大。如果分数绝对值很大,Softmax可能变得非常尖锐。例如:(0,1,2)(0,1,2)(0,1,2)与:(0,10,20)(0,10,20)(0,10,20)经过Softmax以后,后者的最大分数会占据几乎全部权重。在某些区域,Softmax的导数也可能非常小,不利于训练。因此,Transformer使用:1dk\boxed{\frac1{\sqrt{d_k}}}dk1缩放点积分数。它帮助控制分数的量级,使训练更稳定。但这不是说缩放后每个分数都一定处于某个固定范围内。对于真实训练后的向量,实际分数大小仍受参数与输入影响。原始Transformer论文在第3.2.1节明确解释了这项设计,并给出了与维度相关的方差直觉。[NeurIPS Papers]第十幕:互动实验室——让模型决定每个词应该关注哪里现在,我们制作两套实验。第一套重现2014年神经翻译软对齐的核心思想。第二套则直接操作2017年的QKV计算。实验A:词语之间的软对齐热力图假设源句为:text复制代码The little cat is sleeping教学目标译文是:text复制代码这只 小 猫 正在 睡觉为了让实验可控,我们人为给每个目标词设置一组匹配分数。例如,当目标词为“猫”时,让源词cat获得较高分数。然后通过Softmax计算注意力权重。请注意:这不是一个经过训练的翻译模型。 分数是为了演示数学机制人为构造的,不能将生成的热力图当成真实Bahdanau网络学习出来的语言对齐结果。图59-3:手工匹配分数生成的双语对齐热力图行表示当前要生成的中文词,列表示可供参考的英文源词。单元格越深,Softmax权重越高。选择当前目标词这只小猫正在睡觉Softmax温度 τ1.0目标Thelittlecatissleeping这只86%5%3%3%3%小4%84%6%3%3%猫3%5%86%3%3%正在3%3%4%84%6%睡觉2%3%3%4%88%当前目标:猫The2.6%little5.3%cat86.4%is2.9%sleeping2.9%最高权重的位置cat全部权重的和1人工标量Value的加权上下文1.8429恢复初始实验Softmax温度τ越小,较大分数通常越占优势;τ越大,权重越平缓。温度是本教学实验的额外控制参数,不表示Bahdanau原论文使用了这个交互滑块。人工Value只是用于展示加权计算的数值特征,不会直接输出中文译词。观察一:不同目标词,会重新分配注意力先选择:“猫”。你会看到:cat对应的权重较高。然后选择:“睡觉”。较高权重转移到:sleeping。注意力不是对整句话永久分配一次权重。它可以随目标位置变化。观察二:调整Softmax温度一般化的温度Softmax写成:αj=exp(ej/τ)∑kexp(ek/τ)\boxed{ \alpha_j= \frac{\exp(e_j/\tau)} {\sum_k\exp(e_k/\tau)} }αj=∑kexp(ek/τ)exp(ej/τ)其中:τ>0\tau>0τ>0当:τ\tauτ变小时,较大的分数通常获得更高的相对权重。当:τ\tauτ增大时,权重分布通常更加平缓。但温度并不会自动改变原始分数的排序。对于固定分数,最大的分数仍然对应最大的权重。观察三:高权重并不意味着真正“理解了这个词”在这个实验中,我们已经手工决定:哪个中文词应该对应哪个英文词。所以热力图能够呈现非常整齐的关系。真实注意力模型却没有这项人工预设的保证。它需要依靠训练数据与目标函数,学习各位置之间的关系。因此,教学热力图展示的是:Softmax加权机制如何工作。不是:机器已经真正学会了这段语言的全部语法与语义。第十一幕:第二个互动实验——真正操作Query、Key和Value现在,词语对齐的思想已经清楚。但我们还需要一个与2017年Transformer计算公式完全对应的实验。我们准备四个候选位置。每个位置拥有一个二维Key。同时拥有一个标量Value。你可以改变Query的两个分量。观察:哪个Key的点积更大?Softmax权重怎样重新分配?最终加权Value的结果又怎样变化?我们还可以对比:使用:1/dk1/\sqrt{d_k}1/dk缩放。与不缩放。有什么区别。图59-4:二维Query与四个Key的注意力计算改变Query的位置,观察匹配分数、Softmax权重和加权Value怎样同步变化。这里所有向量均为教学设定,并非真实词向量。Query的第一个分量2.0Query的第二个分量0.5使用 dk=2\sqrt{d_k}=\sqrt2dk=2 缩放点积分数猫小睡觉桌子Qxy箭头方向与长度代表二维向量。红色虚线是当前Query,其他箭头是候选Key。点积同时受到方向与模长影响。本次计算位置Key分数权重Value猫(1, 0)1.4146.3%4小(0.6, 0.8)1.1334.9%2睡觉(0, 1)0.3516.0%8桌子(-1, 0)-1.412.7%6注意力分布猫46.3%小34.9%睡觉16.0%桌子2.7%加权Value的最终输出3.9981输出 = 0.463×4 + 0.349×2 + 0.160×8 + 0.027×6关注“猫”关注“睡觉”关注“桌子”零Query实验一:Query指向“猫”选择:“关注‘猫’”。此时:q=(2,0)q=(2,0)q=(2,0)对应:k猫=(1,0)k_{\text{猫}}=(1,0)k猫=(1,0)两者点积为:222而:k桌子=(−1,0)k_{\text{桌子}}=(-1,0)k桌子=(−1,0)与Query的点积为:−2-2−2经过Softmax以后,“猫”对应的权重通常明显高于“桌子”。实验二:改变Query方向选择:“关注‘睡觉’”。此时:q=(0,2)q=(0,2)q=(0,2)Query转向纵轴。而“睡觉”的Key是:(0,1)(0,1)(0,1)所以,它获得更大的点积分数。因此:即使候选信息本身没有变化,只要Query发生变化,注意力分布也会改变。这就是动态注意力的基本特征。实验三:使用零Query选择:“零Query”。此时:q=(0,0)q=(0,0)q=(0,0)因此:q⊤kj=0q^\top k_j=0q⊤kj=0对于所有Key都成立。所以,所有缩放分数相同。Softmax得到均匀权重:αj=14\boxed{ \alpha_j=\frac14 }αj=41最终输出就是四个Value的简单平均:4+2+8+64=5\frac{4+2+8+6}{4}=544+2+8+6=5这说明:如果匹配分数无法区分候选位置,注意力就不会凭空产生选择性。实验四:关闭缩放取消:“使用 dk\sqrt{d_k}dk 缩放点积分数”。你会看到,分数的绝对差异通常变大。注意力分布也可能更尖锐。但这里Key维度只有2。因此,这个微型例子不能充分再现真实高维网络中,点积方差随维度增加的统计问题。它只能帮助理解:缩放怎样改变分数进入Softmax时的尺度。第十二幕:2017年6月12日,Transformer真的把循环从核心架构中移走了第59章配图2017年6月12日。八位研究者向arXiv提交了一篇预印本:Attention Is All You Need他们是:Ashish Vaswani。Noam Shazeer。Niki Parmar。Jakob Uszkoreit。Llion Jones。Aidan N. Gomez。Łukasz Kaiser。Illia Polosukhin。该研究随后发表于2017年的NeurIPS会议。[数字对象标识符][Google Research]论文提出:Transformer。研究动机之一是:传统循环网络在沿序列处理时,存在前后时间步的计算依赖。例如:ht=f(ht−1,xt)h_t=f(h_{t-1},x_t)ht=f(ht−1,xt)这意味着,在通常的RNN计算方式下,为了得到:hth_tht必须先得到:ht−1h_{t-1}ht−1因此,同一序列中相邻位置的隐藏状态计算,难以完全并行。Transformer怎样改变这个结构?它让多个序列位置,通过注意力矩阵相互交换信息。对于输入序列矩阵:XXX一次自注意力计算可以同时产生:全部位置的Query。全部位置的Key。全部位置的Value。然后计算:S=QK⊤dk\boxed{ S=\frac{QK^\top}{\sqrt{d_k}} }S=dkQK⊤其中:SSS是位置之间的匹配分数矩阵。如果序列有:TTT个位置,那么:S∈RT×TS\in\mathbb R^{T\times T}S∈RT×T每一行代表:某个Query位置,对全部Key位置的分数。这意味着什么?假设输入句子有五个词。那么:QQQ有五行。KKK也有五行。因此:QK⊤QK^\topQK⊤会产生一个:5×55\times55×5的匹配矩阵。矩阵中的第:(i,j)(i,j)(i,j)项,表示:第i个位置的Query与第j个位置的Key之间的匹配分数。接着:A=softmax(S)A=\operatorname{softmax}(S)A=softmax(S)这里的Softmax是:对矩阵的每一行分别进行归一化。所以:∑jAij=1\sum_j A_{ij}=1∑jAij=1最后:O=AV\boxed{O=AV}O=AV于是,每个输入位置都获得了由其他候选位置Value加权形成的新表示。为什么叫作Self-Attention?因为在自注意力里:Query。Key。Value。通常都来自:同一组序列位置表示。虽然经过不同的投影矩阵,它们仍然以同一段输入为来源。因此,模型可以学习:某个词与句子中其他词之间的关系。但Transformer不是只有Self-Attention原始2017年Transformer是编码器—解码器架构。它包含三种重要的注意力使用方式。图59-5:Transformer中的三类注意力编码器自注意力Q、K、V都来自编码器当前层所处理的源序列表示。各源位置可以根据模型设计相互交换信息。解码器带因果遮罩的自注意力Q、K、V都来自解码端表示,但生成当前位置时,不允许直接访问未来尚不可用的目标词。编码器—解码器交叉注意力Q来自解码器,K与V来自编码器输出。解码器能够根据当前需求,访问源语言各位置的信息。这三者使用相似的QKV数学形式。但它们的数据来源与可见范围不同。不能把:Self-Attention。Cross-Attention。以及:Masked Self-Attention。当成完全相同的计算角色。原始论文第3.2.3节明确区分了它们。[NeurIPS Papers]原始Transformer到底包含什么?2017年论文的基础模型,使用:编码器6层。解码器6层。模型维度:dmodel=512d_{\text{model}}=512dmodel=512多头注意力:h=8h=8h=8每头Key与Value维度:dk=dv=64d_k=d_v=64dk=dv=64每个主要模块还包括残差连接与层归一化,以及逐位置前馈网络。因此:Transformer不是仅仅将一个Softmax公式重复六次。注意力是它的核心信息交互机制。但实际模型还需要:表示投影。位置编码。多头机制。逐位置非线性计算。残差路径。归一化。以及训练和生成所需的其他结构。这才构成一个完整的序列模型。第十三幕:为什么一个注意力头不够?——Multi-Head Attention第59章配图2017年的Transformer并没有只使用一个注意力头。基础模型使用:h=8\boxed{h=8}h=8个注意力头。其中每个头,都具有自己的:Query投影。Key投影。Value投影。为什么要使用不同的投影?假设句子是:text复制代码The little cat sleeps on the sofa.某个词与其他词之间,可能存在多种不同关系。例如:主语与谓语。名词与修饰语。位置与时间。指代与所指对象。如果只有一组注意力权重,模型会将不同需求共同压缩进同一次信息加权。而多头注意力提供一种机制,使不同投影空间可以学习不同的信息关联模式。但必须谨慎。并不是每个注意力头都会自动变成一种可以人工命名的语法关系。有些头可能表现出明显的位置规律。有些可能关注较为局部的词语。有些可能形成分散权重。也可能存在功能重叠。真正学到什么,取决于训练结果。多头注意力的数学结构对于第i个头:Qi=QWiQQ_i=QW_i^QQi=QWiQKi=KWiKK_i=KW_i^KKi=KWiKVi=VWiVV_i=VW_i^VVi=VWiV计算:headi=Attention(Qi,Ki,Vi)\boxed{ \operatorname{head}_i = \operatorname{Attention}(Q_i,K_i,V_i) }headi=Attention(Qi,Ki,Vi)然后,将所有头的输出拼接:Concat(head1,…,headh)\operatorname{Concat}( \operatorname{head}_1,\ldots,\operatorname{head}_h )Concat(head1,…,headh)最后进行输出投影:MultiHead(Q,K,V)=Concat(head1,…,headh)WO\boxed{ \operatorname{MultiHead}(Q,K,V) = \operatorname{Concat}( \operatorname{head}_1,\ldots,\operatorname{head}_h )W^O }MultiHead(Q,K,V)=Concat(head1,…,headh)WO这就是原始Transformer论文的多头注意力公式。[NeurIPS Papers]八个头会不会让计算量变成八倍?不能只根据头数判断。原始基础模型的:dmodel=512d_{\text{model}}=512dmodel=512每头的:dk=dv=64d_k=d_v=64dk=dv=64八个头的输出拼接后:8×64=5128\times64=5128×64=512因此,多个头使用了较低的每头维度。原始论文指出,在对应的参数设置下,多头机制的总体计算成本,与使用整个模型维度的单头注意力具有相近的数量级。但这并不表示多头注意力在任何硬件或任意形状下,都不会产生额外开销。因为:投影矩阵。内存布局。中间结果。以及硬件实现。都会影响实际性能。多头最重要的价值它允许模型使用多种不同的可学习匹配空间。而不是要求所有信息关系,都由一组Key与Query定义。这种结构对神经网络表示能力的影响,需要与训练任务和实验结果一起评估。在2017年的原始研究中,作者也通过不同头数的消融实验,观察到模型质量随头数变化,并不是无限增加头数就一定更好。[NeurIPS Papers]第十四幕:如果所有词同时计算,Transformer怎样知道词语顺序?第59章配图现在,我们又遇到一项看起来很简单、却极其重要的问题。考虑两句话:text复制代码Dog bites man.以及:text复制代码Man bites dog.它们包含相同的三个词。但词序不同。意思也发生了很大变化。普通自注意力是否天然理解顺序?如果模型仅使用:相同的词向量。相同的线性投影。以及没有任何位置差别的自注意力计算。那么,单独改变输入词语的排列顺序,会相应地排列输出表示。这种运算对排列具有等变性。它本身不能仅凭相同词向量的集合,区分序列中谁先谁后。因此,Transformer需要引入位置信息。2017年的位置编码原始Transformer研究在输入Embedding中加入:Positional Encoding(位置编码)。其中一种设计是:利用不同频率的正弦与余弦函数。公式为:PE(pos,2i)=sin(pos100002i/dmodel)\boxed{ PE(pos,2i) = \sin\left( \frac{pos}{10000^{2i/d_{\text{model}}}} \right) }PE(pos,2i)=sin(100002i/dmodelpos)PE(pos,2i+1)=cos(pos100002i/dmodel)\boxed{ PE(pos,2i+1) = \cos\left( \frac{pos}{10000^{2i/d_{\text{model}}}} \right) }PE(pos,2i+1)=cos(100002i/dmodelpos)其中:pospospos表示位置。iii表示一组正弦和余弦维度的编号。这使不同位置获得不同的数值表示。由于不同维度使用不同频率,位置编码能够携带多尺度的位置信息。论文还比较了可学习的位置Embedding与固定正弦位置编码,在其实验设置下取得了相近的性能。[NeurIPS Papers]位置编码怎样与词向量结合?在原始Transformer基础模型中,可以简化表示为:Xinput=Embedding(tokens)+PE\boxed{ X_{\mathrm{input}} = \operatorname{Embedding}(tokens)+PE }Xinput=Embedding(tokens)+PE需要补充的是,原论文在Embedding层还使用了特定的尺度处理。所以,上式是为了突出位置编码作用而写的结构简化。位置编码一定要使用Sin和Cos吗?不一定。它只是2017年原始论文采用的一项设计。后来还有:学习式绝对位置Embedding。相对位置表示。旋转位置编码。以及其他位置机制。但它们都围绕一项共同需求。模型需要获得足够的位置信息,才能在序列任务中区分相同元素的不同排列。这和LSTM最大的区别是什么?普通RNN通过:ht=f(ht−1,xt)h_t=f(h_{t-1},x_t)ht=f(ht−1,xt)天然按照时间顺序更新状态。顺序嵌入在递推过程里。而Transformer在同一层中可以并行处理多个位置。因此,需要通过位置表示等机制,让模型知道输入中的序列结构。这是一项不同的信息处理方式。第十五幕:如果模型预测下一个词,为什么绝对不能偷看未来?第59章配图现在,我们知道:普通自注意力允许一个位置从其他位置获取信息。但如果模型正在执行:预测下一个词的任务,就会出现一个非常严重的问题。假设训练文本是:text复制代码今天天气很好模型需要在某个位置预测:text复制代码天如果它在计算预测时,直接访问了真实答案所在的未来位置,那就相当于考试时提前看到答案。训练结果可能很好看。但这不代表模型真正学会了根据已知上下文预测未知内容。Causal Mask:因果遮罩为避免这种信息泄漏,自回归Transformer通常采用:Causal Mask(因果遮罩)。对于第i个位置:只允许关注第i个位置及其之前的信息。不允许直接关注:j>ij>ij>i的位置。数学上,可以对注意力分数矩阵加入:Mij={0,j≤i−∞,j>iM_{ij} = \begin{cases} 0,&j\le i\\ -\infty,&j>i \end{cases}Mij={0,−∞,j≤ij>i然后计算:A=softmax(QK⊤dk+M)\boxed{ A= \operatorname{softmax} \left( \frac{QK^\top}{\sqrt{d_k}}+M \right) }A=softmax(dkQK⊤+M)由于:exp(−∞)=0\exp(-\infty)=0exp(−∞)=0所以被禁止的位置,其Softmax权重为0。图59-6:五个位置的因果注意力遮罩Q\K123451✓××××2✓✓×××3✓✓✓××4✓✓✓✓×5✓✓✓✓✓绿色表示允许关注的位置,灰色表示被遮罩的位置。这里仅显示可见关系,而不是实际学到的注意力权重。为什么允许当前位置关注自己?因为训练时通常会采用:将目标序列整体右移一位的输入安排。例如,让第i个解码输入位置携带已经知道的历史符号,并预测下一个目标符号。因此,当前位置在当前表示中的内容,不一定就是尚未生成的目标答案。这种移位与因果遮罩需要配合,才能避免未来目标信息泄漏。原始Transformer论文明确说明了这一点。[NeurIPS Papers]Padding Mask与Causal Mask不是同一个东西如果我们把不同长度的句子组合成一个批次,可能需要在较短句子后面补齐特殊位置。这些位置并不代表真实的输入词语。因此,模型通常还需要:Padding Mask(填充遮罩)。它用于避免把人为补齐的无效位置当作正常信息参与注意力。而因果遮罩用于:阻止访问不该提前看到的未来位置。两者解决的是不同问题。它们也可以在实际计算中组合。所有Transformer都必须使用因果遮罩吗?不需要。例如,双向编码器可以允许各位置互相访问完整输入。因为其任务可能是对一段已经完整提供的文本进行表示或分析。而自回归生成模型则需要遵守生成时的信息可用性约束。因此:注意力是否允许看未来,取决于任务定义与模型架构。不是Softmax公式本身天然决定的。第十六幕:Python实战——只用标准库,手写完整的Scaled Dot-Product Attention第59章配图现在,我们真正实现2017年Transformer里的核心注意力运算。本节不使用:PyTorch。TensorFlow。NumPy。也不需要GPU。只使用Python标准库。我们将完整实现:Softmax的数值稳定处理。Query与Key的点积。dk\sqrt{d_k}dk 缩放。注意力权重矩阵。Value的加权求和。因果遮罩。最后,还会验证注意力权重对Query的梯度。第一部分:稳定的Softmaxpython复制代码 import math def softmax(logits, allowed=None): """ 数值稳定的Softmax。 logits: 一组实数匹配分数 allowed: 对应位置是否允许被关注的布尔列表 返回: 权重列表。被遮罩位置的权重严格为0。 """ if not logits: raise ValueError("Softmax输入不能为空") if allowed is None: allowed = [True] * len(logits) if len(allowed) != len(logits): raise ValueError("Mask长度错误") valid_logits = [ score for score, ok in zip(logits, allowed) if ok ] if not valid_logits: raise ValueError("一行不能全部被遮罩") # 为避免指数溢出,减去最大合法分数 maximum = max(valid_logits) exp_scores = [ math.exp(score - maximum) if ok else 0.0 for score, ok in zip(logits, allowed) ] total = sum(exp_scores) return [ value / total for value in exp_scores ] weights = softmax([0.0, 1.0, 2.0]) print(weights) print("总和:", sum(weights)) assert abs(sum(weights) - 1) < 1e-12 assert weights[2] > weights[1] > weights[0] 预期:text复制代码[0.09003057, 0.24472847, 0.66524096] 总和: 1.0这与本章第四幕手算结果一致。第二部分:计算向量点积python复制代码 def dot(a, b): if len(a) != len(b): raise ValueError("点积向量维度不一致") return sum( x*y for x, y in zip(a, b) ) assert dot([1, 2], [3, 4]) == 11 向量点积就是:a⊤b=∑iaibia^\top b=\sum_i a_ib_ia⊤b=∑iaibi整个Scaled Dot-Product Attention,会反复使用这项运算。第三部分:实现注意力python复制代码 def scaled_dot_product_attention( queries, keys, values, allowed=None, ): """ 完整的Scaled Dot-Product Attention。 queries: [n_query, d_key] keys: [n_key, d_key] values: [n_key, d_value] allowed: 可选的布尔矩阵 形状为[n_query, n_key] 返回: outputs: [n_query, d_value] weights: [n_query, n_key] """ if not queries or not keys or not values: raise ValueError("Q、K、V不能为空") n_query = len(queries) n_key = len(keys) if len(values) != n_key: raise ValueError("Key与Value数量不一致") d_key = len(keys[0]) d_value = len(values[0]) if d_key == 0 or d_value == 0: raise ValueError("向量维度必须大于0") if any(len(q) != d_key for q in queries): raise ValueError("Query维度不一致") if any(len(k) != d_key for k in keys): raise ValueError("Key维度不一致") if any(len(v) != d_value for v in values): raise ValueError("Value维度不一致") if allowed is not None: if len(allowed) != n_query: raise ValueError("Mask行数错误") if any(len(row) != n_key for row in allowed): raise ValueError("Mask列数错误") scale = math.sqrt(d_key) outputs = [] all_weights = [] for i, query in enumerate(queries): # 1. QK^T / sqrt(d_key) logits = [ dot(query, key) / scale for key in keys ] # 2. Softmax,可选因果或其他遮罩 mask_row = ( None if allowed is None else allowed[i] ) weights = softmax( logits, allowed=mask_row, ) # 3. 注意力加权求和 output = [ sum( weights[j] * values[j][d] for j in range(n_key) ) for d in range(d_value) ] outputs.append(output) all_weights.append(weights) return outputs, all_weights 这段函数的核心流程,正对应:O=softmax(QK⊤dk)V\boxed{ O=\operatorname{softmax} \left( \frac{QK^\top}{\sqrt{d_k}} \right)V }O=softmax(dkQK⊤)V虽然没有使用矩阵库,但数学结构完全一致。第四部分:重现第九幕的手算结果python复制代码 queries = [ [math.sqrt(2), 0.0], ] keys = [ [0.0, 0.0], [1.0, 0.0], [2.0, 0.0], ] values = [ [1.0], [3.0], [5.0], ] outputs, weights = scaled_dot_product_attention( queries, keys, values, ) print("注意力权重:", weights[0]) print("最终输出:", outputs[0][0]) assert abs( outputs[0][0] - 4.1504207652 ) < 1e-8 print("QKV手算结果验证成功") 这项测试非常重要。它说明:即使没有任何大型神经网络框架,我们也能够清晰地实现Transformer核心注意力运算。第五部分:同时处理多个Query现在,我们不只处理一个Query。而是让两个Query同时访问相同的Key–Value集合。python复制代码 queries = [ [math.sqrt(2), 0.0], [0.0, math.sqrt(2)], ] outputs, weights = scaled_dot_product_attention( queries, keys, values, ) for i in range(len(queries)): print( "Query", i, "权重:", weights[i], "输出:", outputs[i], ) 第一个Query与此前完全相同。得到:≈4.1504\approx4.1504≈4.1504第二个Query是:q2=(0,2)q_2=(0,\sqrt2)q2=(0,2)而全部Key的第二个分量都是0。所以,三个匹配分数相同:0, 0, 00,\ 0,\ 00, 0, 0Softmax给出:(13,13,13)\left(\frac13,\frac13,\frac13\right)(31,31,31)最终输出:1+3+53=3\frac{1+3+5}{3}=331+3+5=3因此,两个Query分别获得:4.1504\boxed{4.1504}4.1504和:3\boxed33的输出。这是因为:不同Query面对同一组候选Key–Value时,可能形成不同的权重分布。第六部分:真正实现Causal Mask假设我们有三个时间位置。我们希望:第1个位置只能看第1个位置。第2个位置可以看第1和第2个位置。第3个位置可以看第1、第2和第3个位置。那么:python复制代码 def causal_mask(length): return [ [ j <= i for j in range(length) ] for i in range(length) ] tokens = [ [1.0, 0.0], [0.0, 1.0], [1.0, 1.0], ] mask = causal_mask(len(tokens)) outputs, weights = scaled_dot_product_attention( queries=tokens, keys=tokens, values=tokens, allowed=mask, ) print("因果遮罩:") for row in mask: print(row) print("因果注意力权重:") for row in weights: print([round(x, 4) for x in row]) assert weights[0] == [1.0, 0.0, 0.0] assert weights[1][2] == 0.0 print("因果遮罩测试通过") 这项测试验证了:被禁止访问的未来位置,注意力权重严格等于0。还要注意:不能简单地把被遮罩位置的匹配分数设置为0,就认为它们已经被屏蔽。因为:e0=1e^0=1e0=1它们仍然可能得到非零Softmax权重。正确做法是:确保无效位置在归一化后的权重为0,例如对其分数施加负无穷遮罩,或者像本教学代码这样在Softmax中显式排除这些位置。第十七幕:注意力权重为什么可以被训练?——再从反向传播看一遍第59章配图上一章,我们已经学习:链式法则。反向模式自动微分。以及共享计算路径的梯度累加。现在,注意力机制又提出了一项问题。Softmax权重是怎样学到的?如果模型正在生成一个错误的翻译结果,能否利用这项误差,调整Query和Key,使下一次注意力分配更加合理?答案是:在适当的可微结构中,可以。先研究只有一个Query的简化模型假设:sj=q⊤kjdks_j=\frac{q^\top k_j}{\sqrt{d_k}}sj=dkq⊤kj然后:αj=softmax(s)j\alpha_j=\operatorname{softmax}(s)_jαj=softmax(s)j最后,用标量Value形成输出:o=∑jαjvj\boxed{ o=\sum_j\alpha_jv_j }o=j∑αjvj现在,我们希望知道:∂o∂sj\frac{\partial o}{\partial s_j}∂sj∂o也就是说:稍微提高某个位置的匹配分数,最终加权结果会怎样变化?Softmax的导数Softmax具有如下导数:∂αi∂sj=αi(δij−αj)\boxed{ \frac{\partial\alpha_i}{\partial s_j} = \alpha_i(\delta_{ij}-\alpha_j) }∂sj∂αi=αi(δij−αj)其中:δij\delta_{ij}δij是Kronecker Delta。当:i=ji=ji=j时为1。否则为0。这是一个值得记住的重要公式。它表明:提高某个位置的分数,不只会改变那个位置自己的权重。由于全部权重必须归一化,总和保持为1,因此其他位置的权重也会发生变化。对加权结果求导由于:o=∑iαivio=\sum_i\alpha_iv_io=∑iαivi所以:∂o∂sj=∑ivi∂αi∂sj\frac{\partial o}{\partial s_j} = \sum_i v_i \frac{\partial\alpha_i}{\partial s_j}∂sj∂o=∑ivi∂sj∂αi代入Softmax导数:=∑iviαi(δij−αj)= \sum_i v_i\alpha_i(\delta_{ij}-\alpha_j)=∑iviαi(δij−αj)整理得:∂o∂sj=αj(vj−o)\boxed{ \frac{\partial o}{\partial s_j} = \alpha_j(v_j-o) }∂sj∂o=αj(vj−o)这个结果非常漂亮。它告诉我们:如果某个Value大于当前加权输出,那么,适度提高该位置的匹配分数,可能使输出增大。如果某个Value小于当前加权输出,那么,提高该位置的分数可能使输出减小。因此:注意力权重变化对输出的影响,可以被数学地计算出来。进一步求Query的梯度由于:sj=q⊤kjdks_j=\frac{q^\top k_j}{\sqrt{d_k}}sj=dkq⊤kj所以:∂sj∂q=kjdk\frac{\partial s_j}{\partial q} = \frac{k_j}{\sqrt{d_k}}∂q∂sj=dkkj结合链式法则:∇qo=∑jαj(vj−o)kjdk\boxed{ \nabla_qo = \sum_j \alpha_j(v_j-o) \frac{k_j}{\sqrt{d_k}} }∇qo=j∑αj(vj−o)dkkj于是:Query的梯度,可以直接由注意力权重、Key和Value计算得到。这就是注意力可以参与端到端训练的数学基础之一。真实Transformer里还有:矩阵Value。多个Query。多头投影。残差连接。损失函数。以及其他复杂运算。但它们依然利用同样的链式求导原则。使用Python检查Query梯度下面,继续沿用前面已经定义的:scaled_dot_product_attention函数。python复制代码 def analytic_query_gradient(query, keys, values): """ 一个Query、标量Value输出时, 对Query计算解析梯度。 要求values每行只有一个数。 """ outputs, weights = scaled_dot_product_attention( [query], keys, values ) output = outputs[0][0] alpha = weights[0] dimension = len(query) scale = math.sqrt(dimension) grad = [0.0] * dimension for j, key in enumerate(keys): coefficient = ( alpha[j] * (values[j][0] - output) / scale ) for d in range(dimension): grad[d] += coefficient * key[d] return grad def numerical_query_gradient( query, keys, values, eps=1e-6 ): grads = [] for d in range(len(query)): plus = query[:] minus = query[:] plus[d] += eps minus[d] -= eps y_plus, _ = scaled_dot_product_attention( [plus], keys, values ) y_minus, _ = scaled_dot_product_attention( [minus], keys, values ) grad = ( y_plus[0][0] - y_minus[0][0] ) / (2*eps) grads.append(grad) return grads q = [1.0, 0.5] keys = [ [1.0, 0.0], [0.0, 1.0], [-1.0, 0.0], ] values = [ [2.0], [5.0], [8.0], ] analytic = analytic_query_gradient( q, keys, values ) numeric = numerical_query_gradient( q, keys, values ) print("解析梯度:", analytic) print("数值梯度:", numeric) for a, b in zip(analytic, numeric): assert abs(a-b) < 1e-6 print("注意力Query梯度检查通过") 这项测试完整说明:注意力不只是一个能够进行前向加权的函数。它还能够让最终目标,对匹配分数与Query产生可计算的梯度。因此,Query与Key的投影矩阵可以通过反向传播训练。这正是2014年软对齐注意力与2017年Transformer能够使用梯度优化的重要共同基础。第十八幕:论文里的数字——注意力究竟改善了多少翻译质量?第59章配图在研究算法历史时,还有一项重要原则。不能因为某项方法后来变得非常流行,就忽略它最初究竟解决了什么问题。也不能用今天大型语言模型的能力,反过来夸大2014年的神经机器翻译实验。因此,我们回到原始论文。2014—2015年:Bahdanau论文的实验结果在WMT 2014英语—法语翻译任务上,作者比较了:不使用动态注意力的编码器—解码器。与:采用软对齐注意力的模型。其中,一个重要的对照是:模型实验说明全测试集BLEURNNencdec-50固定向量编码器—解码器17.82RNNsearch-50使用动态注意力26.75两者差距:26.75−17.82=8.9326.75-17.82=8.9326.75−17.82=8.93也就是:8.93 BLEU点\boxed{8.93\ \text{BLEU点}}8.93 BLEU点这些数字来自论文第7页的Table 1。[Stanford CS224d]这是不是意味着翻译准确率提高了8.93%?不是。BLEU是一项机器翻译评价指标。它主要比较模型输出与参考译文之间的n-gram匹配等统计关系,并包含长度相关的修正。它不是:“100个词里有多少个正确翻译”的直接百分比。因此,提升8.93 BLEU点,不能直接解释成:词语准确率提升8.93个百分点。也不能直接解释成:所有翻译任务都提高同样幅度。原论文还有另一组分数论文还报告,一个训练更久的注意力模型,在其测试设置下取得:28.4528.4528.45的全测试集BLEU分数。而论文同时报告了统计机器翻译系统Moses的对照结果。但是,如果要比较不同模型,必须看清:是否使用同一份测试数据?是否排除了未知词?模型训练时间是否相同?是否使用了集成系统?以及评测设置是否一致?例如,论文还专门提供了:不包含未知词的测试子集。在不同测试集筛选条件下得到的BLEU分数,不能不加说明地混为一谈。这也是为什么,本章选择了原始论文中较为清楚的一组同条件模型比较。2017年Transformer的实验结果三年后,Transformer论文报告:在WMT 2014英语—德语机器翻译任务上,其最佳模型取得:28.4 BLEU\boxed{28.4\ \text{BLEU}}28.4 BLEU在当时的同类模型比较中,论文展示了翻译质量和训练并行性方面的优势。原始研究还报告了英语—法语任务的结果,以及相应的训练硬件成本。[NeurIPS Papers]但我们不能将:Bahdanau论文的英语—法语BLEU。与:Transformer论文的英语—德语BLEU。直接相减,得出两种算法之间的性能增长。因为:语言方向不同。数据和预处理不同。模型及评测设置也不相同。算法研究中,实验数字只有放在明确的任务与评价条件下,才具有可以解释的意义。为什么长句实验尤其重要?Bahdanau论文的主要研究动机之一,就是固定长度向量可能限制长句翻译。原论文还按照源句长度,分析不同模型的BLEU变化。作者观察到:固定向量编码器—解码器的表现,随源句长度增加出现明显下降。而注意力模型在其实验范围内,对较长句子表现出更好的稳健性。[Stanford CS224d]这与研究假设形成了直接联系。注意力的早期价值,不只是创造了一张有趣的热力图,而是改善了解码器从较长输入序列中提取相关信息的能力。第十九幕:2019年,研究者提出质疑——注意力权重高,就代表模型真的依赖那里吗?第59章配图现在,我们已经知道:注意力权重可以计算。可以学习。还能画成热力图。因此,很容易产生一种直觉。如果某个位置获得:70%70\%70%的注意力权重。是不是说明:模型70%的判断理由,都来自那个位置?这项解释很有吸引力。但它未必成立。2019年:Attention is not Explanation2019年6月,Sarthak Jain与Byron C. Wallace在NAACL发表:Attention is not Explanation《注意力不等于解释》。研究者分析了神经自然语言处理模型中的注意力权重与预测结果之间的关系。他们指出,在所研究的多种模型与任务上,注意力权重并不总能可靠表示输入特征的因果重要性。例如,不同的注意力分布,有时能够产生非常相似的模型输出。[ACL Anthology]为什么会这样?我们只要回到最简单的公式,就能理解其中一部分原因。o=∑jαjvjo=\sum_j\alpha_jv_jo=∑jαjvj假设两个Value完全相同:v1=v2=5v_1=v_2=5v1=v2=5那么:第一组权重:(α1,α2)=(0.9,0.1)(\alpha_1,\alpha_2)=(0.9,0.1)(α1,α2)=(0.9,0.1)得到:o=0.9×5+0.1×5=5o=0.9\times5+0.1\times5=5o=0.9×5+0.1×5=5另一组权重:(α1,α2)=(0.1,0.9)(\alpha_1,\alpha_2)=(0.1,0.9)(α1,α2)=(0.1,0.9)仍然得到:o=0.1×5+0.9×5=5o=0.1\times5+0.9\times5=5o=0.1×5+0.9×5=5因此:o=5\boxed{o=5}o=5虽然注意力权重几乎完全互换,最终输出却没有任何变化。这是因为:权重变化的重要性,还取决于相应Value承载什么信息。如果两个Value相同,仅改变它们之间的权重,并不改变加权结果。真实神经网络的情况更加复杂。不同头的输出会组合。注意力层后面还有其他非线性计算与残差路径。因此,仅凭一张注意力热力图,不一定能完整说明模型为什么作出某个判断。但研究者之间也存在不同观点同样在2019年,Sarah Wiegreffe与Yuval Pinter发表:Attention is not not Explanation《注意力也并非完全不能作为解释》。他们指出,注意力能否提供有意义的解释,取决于解释的定义,以及怎样设计评价实验。他们提出了多种诊断方法,主张不能仅凭某些对抗性权重分布的结果,就断言所有注意力信息都没有解释价值。[ACL Anthology]我们应该怎样理解这场讨论?不能简单地站在某一边,然后说:“注意力权重永远是解释。”或者:“注意力权重永远毫无解释价值。”更加严谨的结论是:注意力权重展示了模型内部一项具体的加权信息交互过程,但它本身不自动构成对模型全部预测行为的充分因果解释。如果研究者希望将注意力图作为解释依据,还需要检查:改变注意力权重是否真的改变预测?相关Value是否包含重复信息?模型是否还能通过其他路径获得同一信息?不同训练初始化是否得到稳定的模式?以及解释方法与实际任务是否相符?因此,在科学研究中,注意力热力图更适合被当作:一项值得进一步分析的模型内部证据。而不是:模型已经自动生成的全部决策理由。第二十幕:Transformer让远距离信息更容易连接,却带来了新的计算代价第59章配图到这里,我们已经理解2017年Transformer的重要优势。在一层完整自注意力中:某个位置可以直接与其他允许访问的位置建立匹配关系。不必像普通RNN那样,让信息在同一层中逐步经过许多时间状态才能到达。而且,训练时多个位置的QKV计算,可以组织成并行矩阵运算。但这项能力并非没有成本。完整注意力矩阵有多大?假设序列长度为:TTT那么:QK⊤QK^\topQK⊤得到:T×TT\times TT×T的矩阵。共有:T2T^2T2个位置对分数。例如:序列长度T一头完整注意力的分数元素数10010,0001,0001,000,00010,000100,000,000100,00010,000,000,000当:TTT增长10倍,完整分数矩阵元素数量增长100倍。因此,在直接显式计算和保存全部注意力分数的朴素实现中,计算与存储需求可能快速增加。注意力的复杂度是什么?假设:Key维度为:dkd_kdkValue维度为:dvd_vdv计算:QK⊤QK^\topQK⊤大致需要:O(T2dk)O(T^2d_k)O(T2dk)的运算量。然后:AVAVAV大致需要:O(T2dv)O(T^2d_v)O(T2dv)所以,完整注意力的主要成对位置计算成本可以写成:O(T2(dk+dv))\boxed{ O(T^2(d_k+d_v)) }O(T2(dk+dv))如果:dk,dvd_k,d_vdk,dv都与:ddd同阶,则经常简写为:O(T2d)\boxed{O(T^2d)}O(T2d)这里暂时不包含Q、K、V投影和其他Transformer层的全部成本。但现代实现一定要保存完整的T×T矩阵吗?不一定。后来的研究发展了更加高效的注意力计算实现。例如,通过分块、融合算子和重新组织Softmax计算,可以减少中间注意力矩阵需要实际写入高带宽显存的数量。此外,还存在局部注意力、稀疏注意力及其他限制或改变连接模式的方法。因此,不能将:标准注意力数学上具有:T2T^2T2个潜在位置对。简单等同为:所有现代实现都会在显存中完整存储一份:T×TT\times TT×T注意力矩阵。算法的数学结构,与某项具体硬件实现的实际内存布局,是两个不同层次的问题。这与第58章RNN的复杂度怎样比较?普通RNN的跨时间依赖具有顺序性。但它每步只更新固定维度状态。完整自注意力更容易在序列位置之间进行并行交互。却可能需要处理数量随序列长度平方增长的位置关系。因此:两种模型在:并行能力。长距离信息交互。状态规模。以及长序列计算成本。方面,作出了不同的设计权衡。2017年Transformer原始论文就专门比较了:计算复杂度。所需顺序操作数。以及任意两个位置之间的最大信息路径长度。[NeurIPS Papers]这也使我们重新认识一个重要事实。注意力机制的出现,并没有消灭全部计算困难,而是改变了信息交互的结构以及计算资源的分配方式。尾声:机器不需要把所有信息平均对待1993年。统计机器翻译研究者正在研究,双语句子中的词语究竟怎样相互对应。不同语言的词序可能不同。一个词可能对应多个词。而有些语法成分,甚至没有简单的一对一对应关系。因此,翻译不仅要选择目标词。还需要推断源语言与目标语言之间的关系。2013年。Graves研究条件手写生成。当神经网络逐笔生成文字时,它需要知道自己目前正在处理输入文本的哪一部分。于是,可微的位置窗口成为帮助序列生成的一项方法。2014年。Bahdanau、Cho与Bengio研究神经机器翻译。他们发现,依赖一份固定的句子向量,可能使长句中的信息难以被有效提取。于是,他们让解码器在生成不同目标词时,动态计算源语言位置的匹配权重。这些权重能够被Softmax归一化。再通过加权求和,形成当前需要的上下文向量。2015年。Luong、Pham与Manning研究全局与局部注意力,以及不同匹配函数的设计。同一年,Xu等人将视觉注意力用于图像描述。机器在生成不同词语时,可以使用不同图像区域的特征。到了2017年。Vaswani等八位研究者提出Transformer。他们将Query、Key和Value的匹配与加权操作,组织成高效的矩阵计算。多头注意力使不同的可学习投影空间能够同时参与信息交互。位置编码补充了序列的顺序信息。因果遮罩确保生成任务不会直接看到不该使用的未来词语。整个架构不再依赖传统RNN的逐步隐藏状态更新,便可以在训练中更充分地并行计算不同序列位置。但这项变化并没有终结算法研究。完整注意力面对长序列时,会产生大量位置对关系。注意力热力图也未必能够完整解释模型的判断过程。因此,后来的研究仍然需要解决:如何降低长序列计算成本?如何提高信息检索效率?如何使模型更准确地利用外部知识?如何判断模型是否真正遵守训练目标?以及,应该怎样评价一项注意力机制的实际贡献?2014年,注意力主要是一种改善神经机器翻译的方法。2017年,它成为一种能够支撑完整序列模型的核心计算结构。而这条发展道路的最重要启示,不在于某个公式本身有多复杂。它在于重新回答了一项基本的信息处理问题:当我们拥有大量信息,却只需要其中一部分时,怎样让当前计算动态找到最相关的内容?本章最值得记住的六个公式1. Bahdanau式加性注意力评分et,j=va⊤tanh(Wast−1+Uahj)\boxed{ e_{t,j} = v_a^\top\tanh(W_as_{t-1}+U_ah_j) }et,j=va⊤tanh(Wast−1+Uahj)2. Softmax注意力权重αt,j=eet,j∑keet,k\boxed{ \alpha_{t,j} = \frac{e^{e_{t,j}}} {\sum_ke^{e_{t,k}}} }αt,j=∑keet,keet,j3. 动态上下文向量ct=∑jαt,jhj\boxed{ c_t=\sum_j\alpha_{t,j}h_j }ct=j∑αt,jhj4. Transformer的缩放点积注意力Attention(Q,K,V)=softmax(QK⊤dk)V\boxed{ \operatorname{Attention}(Q,K,V) = \operatorname{softmax} \left(\frac{QK^\top}{\sqrt{d_k}}\right)V }Attention(Q,K,V)=softmax(dkQK⊤)V5. 多头注意力MultiHead=Concat(head1,…,headh)WO\boxed{ \operatorname{MultiHead} = \operatorname{Concat}(head_1,\ldots,head_h)W^O }MultiHead=Concat(head1,…,headh)WO6. 注意力输出对匹配分数的梯度(标量Value)∂o∂sj=αj(vj−o)\boxed{ \frac{\partial o}{\partial s_j} = \alpha_j(v_j-o) }∂sj∂o=αj(vj−o)它们分别解决不同层次的问题。第一:怎样评价当前查询与候选信息的相关程度?第二:怎样将匹配分数转换成可比较的权重?第三:怎样将相关信息组合起来?第四:怎样使用高效矩阵运算同时处理多个查询?第五:怎样让模型在不同投影空间中进行信息交互?第六:怎样让注意力的匹配方式,通过梯度下降学习?将这些问题连接起来,就能够理解现代许多注意力网络最重要的计算基础。第六篇前四章:从修改参数,到选择信息第二季 · 第六篇《会学习的算法》 · 第56—59章第56章沿着山坡寻找最低点:梯度下降根据梯度修改参数,理解学习率、动量与随机优化。第57章错误怎样穿越一层层神经元:反向传播利用计算图与链式法则,高效计算大量参数的梯度。第58章让机器记住昨天:循环网络与长短期记忆让状态跨越时间,研究BPTT、长期梯度以及LSTM的门控记忆。第59章不必记住全部,只需找到重要的部分:注意力机制从神经翻译软对齐出发,理解QKV、自注意力、多头机制与Transformer。四章共同形成了一条重要的研究路线。第56章,我们让机器知道:怎样调整参数。第57章,我们让机器知道:每个参数对误差的影响究竟有多大。第58章,我们让机器能够:利用过去的状态处理连续信息。第59章,我们进一步让模型能够:根据当前需求,对候选信息进行动态选择与加权。这四项能力共同构成了现代可微神经网络中非常重要的计算基础。但到了这里,另一项问题也开始显现。我们正在训练越来越强大的学习系统。我们使用越来越大的数据集。模型可能接触:人类编写的文章。真实用户的行为记录。复杂的医疗与金融数据。以及其他可能包含个人信息的资料。那么,即使模型能够成功学习数据中的规律,我们是否应该允许它无限制地保留和泄露个体信息?机器能够从数据中学到多少,与它应该暴露多少个人信息,并不是同一个问题。这将成为第六篇最后一章的主题。历史档案:从统计对齐到Transformer年份研究者与成果历史意义1993年Brown、Della Pietra等,统计机器翻译参数估计系统研究双语词语对齐与翻译概率模型2013年8月4日Alex Graves,循环网络序列生成在条件手写生成中使用可微的位置窗口2014年9月1日Bahdanau、Cho、Bengio提交注意力翻译预印本提出可训练的源语言软对齐和动态上下文2015年5月Bahdanau等研究发表于ICLR神经机器翻译注意力的重要正式会议成果2015年7月Xu等,Show, Attend and Tell将神经注意力用于图像描述生成2015年9月Luong、Pham、Manning系统比较全局、局部及不同评分的翻译注意力2017年6月12日Vaswani等提交Transformer预印本提出以注意力为核心、移除循环的序列模型2017年12月Transformer研究发表于NeurIPS发表机器翻译质量及并行训练实验2019年6月Jain、Wallace,Attention is not Explanation质疑直接将注意力权重当作预测解释2019年11月Wiegreffe、Pinter,Attention is not not Explanation对注意力解释的定义和评价方法提出不同观点主要参考文献与历史依据◇1993年 · 统计机器翻译与对齐Brown等 — The Mathematics of Statistical Machine Translation: Parameter Estimation《Computational Linguistics》第19卷第2期,第263—311页。用于核查神经注意力出现之前的统计词语对齐研究。◇2013年 · 条件手写生成中的窗口机制Alex Graves — Generating Sequences With Recurrent Neural Networks包含文本预测与条件手写生成研究,为注意力式信息定位提供更早的历史背景。◇2014—2015年 · 本章最重要的早期神经翻译论文Bahdanau、Cho、Bengio — Neural Machine Translation by Jointly Learning to Align and TranslateICLR 2015正式论文PDF重点阅读第3.1节的软对齐公式、第5节的BLEU实验,以及源语言—目标语言位置权重的可视化。◇2015年 · 图像描述与视觉注意力Xu等 — Show, Attend and Tell: Neural Image Caption Generation with Visual AttentionICML 2015,PMLR第37卷,第2048—2057页。讨论图像区域注意力、软注意力和随机硬注意力。◇2015年 · Global与Local AttentionLuong、Pham、Manning — Effective Approaches to Attention-based Neural Machine TranslationEMNLP 2015,第1412—1421页。重点关注不同评分函数以及全局与局部注意力的实验比较。◇2017年 · 本章Transformer核心原始论文Vaswani等 — Attention Is All You Need(arXiv)NeurIPS 2017正式论文PDF重点阅读第3.2节的Scaled Dot-Product Attention、多头机制及注意力应用方式,第3.5节的位置编码,以及第4节的计算复杂度分析。◇2019年 · 注意力是否能够解释模型行为?Jain & Wallace — Attention is not ExplanationWiegreffe & Pinter — Attention is not not Explanation两篇论文展示了注意力可解释性研究中的不同论点,有助于理解内部权重可视化与因果解释之间的区别。**史实与教学重构说明:**1993年统计机器翻译对齐、2013年条件手写生成、2014年Bahdanau等人的神经翻译软对齐、2015年Luong和Xu等人的研究,以及2017年Transformer,均有对应的一手论文。本文没有将所有注意力相关思想归功于2014年某一篇论文,也没有将2014年的循环式神经翻译注意力与2017年的Transformer结构混为一谈。本章所有中文—英文小句、QKV二维向量、Key及Value数值、Softmax热力图和Python代码,都是教学构造。交互实验中直接设置的匹配分数,并不是经过训练的真实语言模型权重;注意力的加权输出,也不等于某个词语已经获得了确定的语义解释。Python程序完整实现了缩放点积注意力、遮罩和Query的梯度检查,但尚未实现Transformer的全部层、训练过程或文本生成系统。下一章预告 · 第二季 第60章 · 第六篇终章《知道很多,却不泄露任何人:差分隐私的数学承诺》第59章配图2006年,美国。四位研究者正在思考一个与机器学习能力同样重要的问题。如果我们拥有一份包含大量个人记录的数据库。我们希望从中计算统计信息。例如:某个城市居民的平均收入。某项医疗研究中的疾病比例。或者某种用户行为的总体趋势。我们希望公开这些统计结果。却不希望别人通过反复查询,推断某个具体的人是否出现在数据库里。但是,直接隐藏姓名真的足够吗?如果一个人加入或退出数据库,会使某项统计结果发生可观察的变化,是否就可能泄露其个人信息?2006年,Cynthia Dwork、Frank McSherry、Kobbi Nissim与Adam Smith发表:Calibrating Noise to Sensitivity in Private Data Analysis《在隐私数据分析中根据敏感度校准噪声》。研究者讨论怎样根据统计查询的敏感度,精心选择随机噪声的规模,使数据分析结果能够提供有用信息,同时获得明确的隐私保证。 [Microsoft Research]随后,差分隐私逐渐成为隐私保护数据分析中的重要数学框架。它研究一项极其严格的问题。如果数据库里改变了某一个人的记录,那么,观察者能够从输出结果的概率分布中获得多少有关这项变化的信息?其经典形式之一,可以写成:Pr[M(D)∈S]≤eεPr[M(D′)∈S]\boxed{ \Pr[M(D)\in S] \le e^\varepsilon \Pr[M(D')\in S] }Pr[M(D)∈S]≤eεPr[M(D′)∈S]其中,D与D'是按照指定邻接关系仅相差一条个人记录的数据库。M是一项随机化分析机制。而:ε\varepsilonε则控制隐私保证的强度。这项公式背后,还隐藏着一个十分微妙的权衡。如果噪声太小,个人隐私可能受到威胁;如果噪声太大,数据分析结果又可能失去实际价值。下一章,我们将从2006年的原始研究出发,详细推导敏感度、拉普拉斯机制与隐私预算,亲手比较不同隐私强度下的统计误差,并讨论为什么“删除姓名”不等于获得了可证明的隐私保护。第59章,机器学习怎样有选择地使用信息;第60章,我们将研究,机器即使能够利用这些信息,应该怎样通过数学机制限制个人信息的泄露。——《算法的故事》第二季 · 第六篇《会学习的算法》 · 第59章 完上一章下一章