探秘Transformer系列之(1):注意力机制

news/2025/2/9 11:17:49/文章来源:https://www.cnblogs.com/rossiXYZ/p/18705809

探秘Transformer系列之(1):注意力机制

0x00 概述

因为各种事情,好久没有写博客了,之前写得一些草稿也没有时间整理(都没有时间登录博客和微信,导致最近才发现好多未读消息和私信,在这里和各位朋友说下万分抱歉)。现在恢复更新,是因为最近有些从非AI领域转过来的新同学来找我询问是否有比较好的学习资料,他们希望在短期内迅速上手 Transformer。我在网上找了下,但是没有找到非常合适的系统的学习资料,于是就萌发了自己写一个系列的想法,遂有此系列。在整理过程中,我也发现了自己很多似是而非的错误理解,因此这个系列也是自己一个整理、学习和提高的过程。

本系列试图从零开始解析Transformer,目标是

  • 解析Transformer如何运作,以及为何如此运作,让新同学可以入门Transformer。

  • 力争融入一些比较新的或者有特色的论文或者理念,让老鸟也可以通过阅读本系列来了解一些新观点,有所收获。

几点说明:

  • 本系列是对论文、博客和代码的学习和解读,借鉴了很多网上朋友的文章,在此表示感谢,并且会在参考中列出。因为本系列参考文章太多,可能有漏给出处的现象。如果原作者发现,还请指出,我在参考文献中进行增补。
  • 本系列有些内容是个人梳理和思考的结果(反推或者猜测),可能和原始论文作者的思路或者与实际历史发展轨迹不尽相同。这么写是因为这样推导让我觉得可以给出直观且合理的解释。如果理解有误,还请各位读者指出。
  • 对于某些领域,这里会融入目前一些较新的或者有特色的解释,因为笔者的时间和精力有限,难以阅读大量文献。如果有遗漏的精品文献,也请各位读者指出。

本文为系列第一篇,主要目的是引入Transformer概念和其相关背景。在2017年,Google Brain的Vaswani等人在论文”Attention is All You Need“中发布了Transformer。原始论文中给出Transformer的定义如下:

Transformer is the first transduction model relying entirely on self-attention to compute representations of its input and output without using sequence aligned RNNs or convolution。

其中提到了sequence,RNN,convolution,self-attention等概念,所以我们接下来就从这些概念入手进行分析。我们先开始从Seq2Seq介绍,然后逐渐切换到注意力机制,最后再导出Transformer模型架构。

0x01 背景知识

本节我们将介绍一些背景知识和概念。

1.1 seq2seq

seq2seq(Sequence to Sequence/序列到序列)概念最早由Bengio在2014年的论文“Learning Phrase Representations using RNN Encoder–Decoder for Statistical Machine Translation”中提出,其代表从一个源序列生成一个目标序列的操作。因为机器翻译是大家较熟悉且容易理解的领域,因此后续我们主要使用机器翻译来进行讲解,避免引入过多概念。

1.2 文本生成机制

机器翻译其实就是文本生成。语言模型将文本看作是时间序列。在此视角下,每个单词都和它之前的单词相关,通过学习前面单词序列的统计规律就可以预测下一个单词。因此,机器翻译会从概率角度对语言建模,让新预测的单词和之前单词连成整个句子后最合理,即原有句子加上新预测单词后,成为整个句子的概率最大。这就涉及到自回归模型。

1.3 自回归模型

自回归(Autoregressive)模型是一种生成模型,其语言建模目标是根据给定的上下文来预测下一个单词。遵循因果原则(当前单词只受到其前面单词的影响),自回归模型的核心思想是利用一个变量的历史值来预测其未来的值,其将"序列数据的生成"建模为一个逐步预测每个新元素的条件概率的过程。在每个时间步,模型根据之前生成的元素预测当前元素的概率分布。

下图给出了自回归模型的示例。模型每次推理只会预测输出一个 token,当前轮输出token 与历史输入 token 拼接,作为下一轮的输入 token,这样逐次生成后面的预测token,直到新输出一个结束符号或者句子长度达到预设的最大阈值。就下图来说,模型执行序列如下:

  • 第一轮模型的输入是“You should”。

  • 第一轮模型推理输出“wear”。

  • 将预测出的第一个单词“wear”结合原输入一起提供给模型,即第二次模型的输入是“You should wear”。

  • 第二次模型推理输出“shoes”。

  • 将预测出的第二个单词“shoes”结合原输入一起提供给模型,即第三次模型的输入是“You should wear shoes”。

  • 第三次推理输出结束符号,本次预测结束。

该过程中的每一步预测都需要依赖上一步预测的结果,且从第二轮开始,前后两轮的输入只相差一个 token。

自回归模式有几个弊端:

  • 容易累积错误,导致训练效果不佳,因为后面的推理对之前推理的输出会有依赖。在训练初期,模型尚不成熟,几次随机输出会导致随后的训练很难学到任何东西。“一步错,步步错”,训练会变得极不稳定,很难收敛,浪费训练资源。
  • 只能以串行方式进行,这意味着很难以并行化的方式开展训练、提升效率。

1.4 隐变量自回归模型

隐变量模型是一种引入隐变量来表示过去信息的模型。自回归模型在预测时会把过去观测到的信息总结起来记作\(h_t\),并且更新预测\(x_t\)。即总结\(h_t = g(h_{t-1}, x_{t-1})\),然后基于\(x_t = P(x_t \mid h_{t})\)来估计\(x_t\)。由于\(h_t\)从未被观测到,因此\(h_t\)就是隐变量,这类模型也被称为隐变量自回归模型(latent autoregressive models)。

有了\(ℎ_t\)之后,其实预测变换为两个子问题。一个问题是如何根据之前的隐变量 \(ℎ_{t−1}\) 和之前的输入信息\(x_{t-1}\)得到现在的隐变量\(ℎ_t\),另一个问题是如何根据当前的隐变量\(ℎ_t\)和之前的输入\(x_{t-1}\)得到当前的\(x_t\) 。其实,这就是编码器-解码器模型要面对的问题。

1.5 编码器-解码器模型

目前,处理序列转换的神经网络模型大多是编码器-解码器(Encoder-Decoder)模型。传统的RNN架构仅适用于输入和输出等长的任务。然而,大多数情况下,机器翻译的输出和输入都不是等长的,因此,对于输入输出都是变长的序列,研究人员决定使用一个定长的状态机来作为输入和输出之间的桥梁。于是人们使用了一种新的架构:前半部分的RNN只有输入,后半部分的RNN只有输出(上一轮的输出会当作下一轮的输入以补充信息),两个部分通过一个隐状态(hidden state)来传递信息。把隐状态看成对输入信息的一种编码的话,前半部分可以叫做编码器(Encoder),后半部分可以叫做解码器(Decoder)。这种架构因而被称为编码器-解码器架构,所用到的模型就是编码器-解码器模型,具体如下图所示,图中编码器和解码器通过一个中间隐状态C来完成信息交互。

编码器和解码器的作用分别如下:

  • 编码器把输入句子的所有语义信息压缩成一个固定长度的中间语义向量(也称为上下文向量或隐向量或隐状态),该向量包含了可供计算与学习的、代表句子语言特点和含义的特征信息,是输入的浓缩摘要。具体逻辑为:
    • 编码器会对输入句子 \(X = (x_1, ..., x_n)\) 的每个词进行处理,处理每个词之后会产生一个隐状态。
    • 从输入的第二个词开始,编码器每个时刻的输入是上一个时刻的隐状态和输入的新单词。
    • 编码器输出的最后一个时刻的隐状态就是编码了整个句子语义的语义上下文(context),这是一个固定长度的高维特征向量\(C = (z_1, ..., z_n)\),输入句子每个时间步的信息都包含在了这个上下文中。
  • 解码器会把这个中间语义上下文向量\(C\)解码成输出句子\(Y = (y_1, ..., y_m)\),即解码器将编码器学习到的特征信息再转化为相应的句子。具体逻辑为:
    • 在每个时刻,解码器都是自回归的,即上一个时刻的输出(产生的字符\(y_{t-1}\))作为下当前时刻\(t\)的输入之一,生成当前时刻的字符\(y_t\)
    • 解码器最初的输入是中间语义上下文向量\(C\),解码器依据\(C\)计算出第一个输出词和新的隐状态,即解码器的每个预测都受到先前输出词和隐状态的微妙影响。
    • 解码器接着用新的隐状态和第一个输出词作为联合输入来计算第二个输出词,以此类推,直到解码器产生一个 EOS(End Of Service/序列结束)标记或者达到预定序列长度的边界。

从宏观角度看,序列建模的核心就是研究如何把长序列的上下文压缩到一个较小的状态中。

1.6 如何压缩

如何压缩?人们很容易想到马尔可夫假设,即系统的未来状态只与当前状态有关。这也被称为近因效应:从文本生成角度看,就是当前词只与距离它比较近的个词更加相关。如果考虑前面n个单词,这就得到了N-gram模型,即当前单词的概率取决于前n个单词。但是基于马尔科夫假设的模型难以处理句子中的长距离依赖关系(某个单词依赖句子中很早的单词),也没有考虑深层语义关系。而且N-gram模型的大小几乎是n的指数倍,如果n数目太大,则n个单词组合数可能性太多,对资源消耗过大,因此需要新的模型。新模型应该不仅仅简单的关注单词的频率和顺序,还可以考虑更长距离的依赖关系,却又不必显式考虑那么多单词组合可能性,于是人们想到使用神经网络来拟合。

MLP 是最基本的神经网络模型之一,它可以将词向量序列映射到一个固定长度的向量表示,然后将这个向量输入到一个softmax层中,计算出下一个词的概率分布。MLP虽然理论上没有距离长依赖问题,但是很难训练好。CNN/RNN/Transformer等网络结构都可以看作是在MLP上添加的约束条件。通过这些先验约束,同等参数量下的优化难度被降低,模型更容易找到最优解。前面提到的“使用神经网络来拟合”就是使用CNN,RNN或者Transformer来实现编码器和解码器。

因为我们本系列介绍的主角是Transformer,就说明Transformer在实现编码器和解码器上是存在优势的,因此我们先来看看CNN和RNN方案的问题所在。

0x02 CNN和RNN方案

注:本节只是从普遍意义或者说是在典型问题上进行阐释,并非定论。因为CNN和RNN方案也是在不停的发展,其某一个阶段的方案可能解决(或者缓解)了下面提到的问题。

2.1 技术挑战

当面临冗长且信息密集的输入序列时,编码器-解码器模型在整个解码过程中保持相关性的能力可能会减弱。为了更好的说明,我们先看看序列转换面对的主要技术挑战:对齐问题和长依赖问题(或者说是遗忘问题)。

对齐

我们来看看为什么要对齐。首先,在某些领域(比如语音识别)中,虽然输入与输出的顺序相同,但是没有一一对应的关系。其次,在某些领域(比如机器翻译)中,在处理完整个输入序列后,模型的输出序列可能和输入序列的顺序不一致。以机器翻译为例,假如我们要让模型将英语 "how are you" 翻译为中文 "你好吗",或者将“Where are you”翻译成“你在哪里”,我们会发现翻译结果中的语序和原来句子的语序并不相同,同时,一些翻译结果并不能与英语中的词汇一一对应到。

不对齐问题带来的最大困境是:在时间序列的 t 时刻,我们并不能确定此时的模型是否已经获得了输出正确结果所需要的所有信息。因此,人们往往先把所有输入编码到一个隐状态,然后逐步对这个隐状态进行解码,这样才能确保在解码过程中模型一定收到了所需的全部信息。虽然此方案可以保证输入信息的完整性,但却有一个明显缺陷,即在解码过程中,无法确定贡献度。比如,当把”I love you"翻译成“我爱你”时,“我”应该与“I”对齐(因为其贡献最大),但是该方案中,"I","love","you"这三个词对“我”的贡献都是一致的。

长依赖

我们以下面句子为例来进行分析。“秋蝉的衰弱的残声,更是北国的特产,因为北平处处全长着树,屋子又低,所以无论在什么地方,都听得见它们的啼唱。”

将例句从英文翻译成中文时,英文和中文明显是有对齐关系的,因此需要知道哪个英文单词对应到哪个中文。比如将”它们“翻译成”They“,但是“它们”代表什么呢?是“树”?“屋子“?还是”秋蝉“?通过”啼唱“和知识,我们知道“秋蝉”和“它们”指代是同一个对象,但是如果把”听得见它们的啼唱“ 修改为“看见它们的树荫”,则“它们”指代的就是“树”了。

人类可以很容易的同时看到“秋蝉”和“它们”这两个词然后把这两个词关联起来,即人们知道“它们”和“秋蝉”有长距离的依赖关系,从而理解整个句子。但是对于计算机或者对于模型来说,”秋蝉“和”它们“在例句中的距离太长了,很容易被两个词中间的其它词干扰。为了准确给出最终的答案,神经网络需要对前面”秋蝉的衰弱的残声“和”它们“之间的交互关系进行建模。然而,某些神经网络很难处理长距离依赖关系,因为处理这种依赖关系的关键因素之一是信号在网络中穿越路径的长度,两个位置之间路径越短,神经网络就越容易学习到这种长距离依赖关系,两个位置之间距离越远,建模难度就越大。如果模型无法处理长距离依赖,则会出现长时信息丢失,也就是产生了遗忘问题。

我们接下来看看CNN方案和RNN方案如何应对这两个技术挑战。

2.2 CNN方案

CNN的本质是学习空间数据中的局部依赖关系。CNN的卷积操作可以提取重要特征,但是因为单个卷积核的长度一般比较小,所以CNN的卷积感受视野是局部的,提取的是局部特征,进行局部信息计算。即CNN对相对位置敏感,对绝对位置不敏感,难以提取序列的长距离依赖关系。

为了让CNN可以处理长序列,人们一般会堆叠更多的卷积,通过叠加多层卷积区去把局部感受野进行扩大,让卷积网络依靠深度来弥补全局信息的缺失,从而捕捉长距离依赖。在这种方案中,不同卷积层会提供不同层次的特征,进而在上层完成长距离信息依赖计算,把长序列的信息压缩到一个卷积窗口内部,以此来让模型有机会捕捉到长距离依赖和复杂的结构关系。

比如下图所示,最下层CNN使用滑动窗口作用于这个文本序列,每个窗口都对其中的数据进行处理。A1窗口获取到了“秋蝉”这个信息,A3窗口获取到了“它们”这个信息。但是,因为“秋蝉”和“它们”距离太远,所以没有一个单一窗口可以把这两个词建立起依赖关系,即没有单一窗口可以同时看到这两个词。因此,模型只能持续堆叠卷积网络,不断加深整个网络,这样C1这个窗口才可以同时包含“秋蝉”和“它们”的信息。

但是深度就代表间接,间接就代表着流失。在CNN方案中,因为信息被“逐级加工,层层抽象”,而且信息传递过程不够透明,信息会在过深的网络传播过程之后只有部分保留,导致模型性能下降。所以CNN一般在长依赖关系建模场景使用较少,更适合短文本计算。

2.3 RNN方案

从表象上看,RNN是时序结构,后面的时刻天然就依赖于前面时刻的输出。从本质上来说,RNN是一种连接主义模型,具有选择性地在序列步骤间传递信息的能力,可以对序列上下文信息以及不同范围元素间的局部依赖关系进行捕捉。RNN的独到之处在于引入了“记忆”功能,让网络能记住之前输入的信息。随着数据在RNN中的流动,之前时间步的记忆会作为输入参与到当前数据的处理中,让模型能够动态地融合时间上下文和序列的历史信息。因为可以有效地处理变长的序列数据,理论上,RNN可以预测无限长句子,利用前面所有信息,所以非常适合翻译场景。

思路

事实上,在Transformer出现之前,编码器和解码器通常是由RNN或其变体(如 LSTM 或 GRU)组成的。我们先看看如何用RNN实现编码器。以下图为例,编码器需要把“北国的特产”这个句子编码成隐状态。图中的每个方块都是一个简单的RNN单元。每个RNN单元接收两个输入(输入词和隐状态),输出一个隐状态。

模型在第一步得到输入h0和“北”,调用函数f()进行计算,得到输出h1=f(h0, 北)。h0是第一个隐状态(通常内容是数值0或者随机值)。模型在第二步得到输入h1和“国”,同样调用函数f()进行计算,得到h2。以此类推,模型最终输出h5。在计算过程的每一步t,前面所有节点得到的信息都保存在上一步计算出来的中间隐状态ht中,因此,后一个词的计算都会用到前面所有词的输出结果。

可以把隐藏状态ht看作是信息循环的载体,其承载的信息可以跨时间步在RNN中进行传递。随着数据在RNN中的流动,之前时间步的激活状态会作为输入参与到当前数据的处理中,让模型能够动态地融合时间上下文和序列的历史信息。因此从理论上来说,RNN可以通过隐状态得到任意两个词的依赖,无论这两个词距离多远,它们的信息一定会在某一步计算之中汇聚。

我们再给出编码器-解码器的结构图,其中si是解码器在时刻\(i\)的隐状态。编码器读入输入的token xi,并对每个token xi生成一个隐状态hi。从第一个h1到最后一个hm,这些隐状态不断将前面信息积累。最后的携带整个输入序列信息的hm会作为解码器的输入s0。

优点

RNN的优点如下:

  • 适合处理序列数据。RNN天然地适合处理具有时间序列或序列结构的数据,如文本、语音和视频等。RNN可以灵活地处理不同长度的输入序列,并捕捉序列中的依赖关系。
  • 捕捉长期依赖。RNN任意步的隐状态都包含了当前时间步之前所有时间步的几乎所有信息,因此RNN可以捕捉序列中的长期依赖关系,从而克服了马尔可夫模型的主要局限性,这对许多序列学习任务至关重要。
  • 权重共享。RNN在处理序列时采用了权重共享的策略,即不同时间步使用相同的权重。这可以减少模型参数数量,降低过拟合的风险。
  • 速度快。每个输入仅仅依赖于对应的h,因此所有token推理的消耗基本相同。整体推理速度和上下文长长度线性相关。

缺点

RNN的缺点同样鲜明。在RNN方案中,在每个时间步,RNN都会将序列中之前的所有信息压缩到一个固定长度的隐向量,最终编码器和解码器之间只通过这个固定长度的隐状态来传递信息。固定长度的隐状态或者说有限的记忆能力在处理长序列时会导致接下来的几个问题,比如信息遗失、信息瓶颈等。

表达能力缺失

RNN的特点会带来表达能力的缺失,体现在如下几点:

  • 既然隐向量长度固定,那么这个压缩过程就是有损压缩,会导致隐向量保存上下文的能力在本质上是有限的。我们以文本摘要为例,如果几百字的散文,隐向量还可以存储散文的全部语义信息,但是面对几万字的小说,隐向量将力有不逮。
  • RNN是个偏序结构。虽然语言本身的词序和语法也构成了一个偏序结构,但是通常又有定语后置,补语和各种从句等附加方式,这导致整个语序并不完全满足偏序结构,因此RNN在处理长距离关联的复杂语法结构时力不从心。
  • 解码器解码时,每个事件步的隐状态都基于编码器生成的同一个隐向量来构建,这是不合理的,因为不同位置的单词可能需要不同程度和不同方面的信息。而权重共享也导致会对输入中的每个单词都赋予同样权重,无法对单词的重要程度进行区分。
信息遗失

因为RNN的表达能力缺失,所以会带来信息遗失问题。

  • 信息遗失或者混淆。而且当新输入进入时,原有信息可能被新信息覆盖或者被稀释,这样模型会更加关注靠近尾部的输入,序列早期部分的记忆会随着随着距离的增加产生传播衰减。越往前的输入,信息衰减得越多,如果关键信息出现在序列头部,就容易被忽略。
  • 难以捕捉长距离依赖关系。以上图为例,h4中包含最多信息的是当前的输入“特”,最开始的“北”所携带的信息会被忽略,很难有效构建两者的依赖关系。
难以并行

RNN需要对序列内容进行逐步处理, 每一步的输出取决于先前的隐藏状态和当前的输入。RNN这种串行计算在本质上是一种递归,其阻碍了训练时的并行计算,导致训练效率较低,训练时间过长。

难以训练

RNN的网络结构特点导致难以训练。RNN 用于信息传输通路只有一条,并且该通路上的计算包含多次非线性激活操作,当 RNN 处理长序列时,因为时间步增加带来的多层激活函数的嵌套会导致梯度反传时指数级地衰减(消失)或增长(爆炸),这就是梯度消失问题或者梯度爆炸问题。当梯度消失时,前面的梯度信息无法有效地传递 到后面,也就导致词之间距离越远,前面对后面的影响越弱,所以RNN网络难以学习远距离依赖关系。当梯度爆炸时,网络的权重会变得极大,导致网络不稳定。而且当面对长序列时,RNN需要大量内存来维持长序列的隐状态,比如需要完整理解整个句子乃至整篇文章才能做出判断,这些内存负担对训练也造成了很大挑战。

2.4 当前问题

我们总结CNN和RNN这两个方案的主要问题如下:

  • 对齐问题。CNN和RNN都难以在源序列和目标序列之间做到完美对齐。
  • 隐状态长度固定。这个问题点主要存在于RNN,因为其隐向量大小固定,所以推理效果受限于信息压缩的能力,导致信息遗失。
  • 关系距离问题。此问题在RNN和CNN中都存在。序列中两个词之间的关系距离不同,当词之间距离过长时,两个方案都难以确定词之间的依赖关系。使得当面临冗长且信息密集的输入序列时,模型在整个解码过程中保持相关性的能力可能会减弱。

我们再仔细看看”关系距离问题“。对于CNN方案,序列的第一个词和最后一个词要通过多层卷积后才可以建立联系。下图中的粗线为CNN结构中两个词建立关系所需的最长距离。

而RNN方案需要对序列“从头看到尾”才能确定给这两个词建立关系所需的距离。下图中的粗线是RNN结构中两个词建立关系所需的最长距离。

因此我们要面对的问题是:如何把大量的token压缩到一个隐藏状态中,而且该状态还可以有效的捕捉它们的底层结构和关系。如果想从根本上解决问题,我们有如下几步可以选择:

  • 可以通过拓展隐状态的长度,或者增加新影响力因子(该因子可以反应输入序列各个位置对于解码器当前输出的影响力)来增加信息含量。
  • 让序列中两个词之间的关系距离更近,或者让各个词直接建立联系。比如对于RNN来说,需要让隐状态和时序无关,从而打破这个顺序结构。
  • 平等看待序列中每个单词,避免像RNN那样更容易注意到靠后的内容,而忽略靠前的输入。
  • 对于序列进行”划重点“,这样可以区别不同元素所携带的信息量,对于不同的元素给予不同的关注度。
  • 虽然大多数实时因果数据只知道过去的状态并期望影响未来的决策,但是对于某些功能(比如翻译),我们希望可以做到同时向前预测和向后回顾。

我们接下来介绍的注意力机制就可以在一定程度上解决上述问题。

0x03 注意力机制

注意力(Attention)机制由Bengio团队2015年在论文“NEURAL MACHINE TRANSLATION BY JOINTLY LEARNING TO ALIGN AND TRANSLATE”中提出,其主要思路为通过模仿人类观察事物的行为来降低算法复杂度、提高性能。人类在感知、认知和行为决策过程中会选择性地关注和处理相关信息,从而提高认知效率和精度,比如人类可以依据兴趣和需求选择关注某些信息而忽略或抑制其它信息,并且可以在多任务上分配注意力从而达到同时处理多个信息的目的。大家最熟悉的例子就是,当一个人看图片时,他会先快速通览,然后对重点区域进行特殊关注。而在文本生成的每个阶段,并非输入上下文的所有片段都同样重要。比如在机器翻译中,句子“A boy is eating the banana”中的“boy”一词并不需要了解整个句子的上下文之后,再来进行准确翻译。

3.1 原理

注意力机制可以从不同角度进行理解,人们也做出了很多精彩论断,比如:

  • 注意力机制的本质是上下文决定一切。
  • 注意力机制是一种资源分配方案。
  • 注意力机制是信息交换,或者说是是“全局信息查询”。

这些角度彼此联系又各有特色,我们逐一进行分析。

上下文决定一切

注意力机制的本质可以用一句话来总结:上下文决定一切(context is everything)。一个字 / 词在一篇文本中表达的意思通常与它的上下文有关。比如下面两个句子中都有“transformer”这个单词,但是第一个“transformer”应该翻译成“变压器”,第二个“Transformer”最好不做翻译。

  • Several distributor transformers had fallen from the poles, and secondary wires were down.
  • Transformer models have emerged as the most widely used architecture in applications such as natural language processing and image classification.

如何才能对“transformer”这个多义词进行语义区分?我们必须考虑单词的上下文才能更好的把单词的语义识别出来,即不仅仅要考虑到词本身,还要考虑其他词对这个词的影响,也就是语境的影响。比如第一个句子的“pole”、”fallen”和“wires”这几个邻近单词暗示了此处的“transformer”和真实物理环境相关。第二个句子的“model”和“natural language processing and image classification”则直接告诉我们此处的“Transformer”是深度学习相关概念。最终我们通过上下文语境可以推断出“Transformer”的准确含义,从而把这两个英文句子翻译成如下:

  • 几个变压器从电线杆上摔下来,副线也垂下来。
  • Transformer模型已成为自然语言处理和图像分类等应用中使用最广泛的架构。

这就是注意力机制的作用:将每个词与序列中的其他词联系起来,通过句子中的其它词对我们关注词的语义进行推断。

资源分配

注意力机制也是一种资源分配方式。目前我们知道了上下文的重要性,但是这还不够,因为一个单词的上下文包括很多其它单词,不同单词对目标单词的影响力往往不同。以翻译为例,因为输入语句是一个连贯的整体,所以每个输入词\(X_i\)都会给每个输出词\(Y_i\)造成影响。因此在考虑单词上下文时候,也需要考虑出上下文中每一个元素应该考虑多少。比如第二个英文句子中,“model”对“Transformer”的影响力必然是最大的。所以我们需要一种机制来依据不同的上下文聚焦于不同的信息,这样,一来可以使得序列中的重要元素被投射以较高注意力,重要信息不会被淹没;二来可以将有限的计算资源用来处理更重要的信息,从而做到提纲挈领。

注意力机制就是这种资源分配机制。其在学习的过程中自适应的给予输入的不同词赋予不同的注意力权重,从而区分输入的不同部分对输出的影响,自适应的学习应该关注的重点位置,做出准确判断,即注意力赋予了模型分辨的能力。

其实,论文“Recurrent Models of Visual Attention”中有一段话就深刻的印证了资源分配这个角度。具体如下:人类感知的一个重要特性是,人们不会一次处理整个场景。相反,人类有选择地将注意力集中在视觉空间的某些部分上,以在需要的时间和地点获取信息,并随着时间的推移将不同注视点的信息结合起来,建立场景的内部表示,指导未来的眼球运动和决策。将计算资源集中在场景的各个部分可以节省“带宽”,因为需要处理的“像素”更少。但它也大大降低了任务的复杂性,因为感兴趣的对象可以放置在注视的中心,而注视区域外的视觉环境的无关特征(“杂乱”)自然会被忽略。其英文原文如下:

信息交换

确定了资源分配的原则之后就可以进行信息交换。注意力机制计算过程就是序列中元素交换信息的过程。注意力机制的输入是一个序列或者集合,注意力机制会从输入中选择性提取信息,据此计算出一组权重。这组权重代表了各个信息的重要程度,使用这种权重与原始信息相乘就得到了注意力处理后的加权信息。

信息交换在一定程度上起到了RNN中记忆力模块的作用,使得注意力编码器也能像RNN一样对一个复杂的语句或者场景进行理解和解析,比如:

  • 将注意力机制应用在序列转换的源序列和目标序列之间,可以让两个序列互相交换信息,起到信息对齐的目的。

  • 将注意力机制应用在一个序列内部(这就是人们经常提到的自注意力机制),可以让序列中每个词都和序列中其他词关联起来,这样序列中每一个元素都有机会根据自身特征,有选择性地依据词之间的相关性来吸取整个序列中每一个其他元素的信息,对本身进行动态调整。这使得模型能够捕捉长距离依赖关系,不受距离的影响。考虑以下两个句子,第一句中的“it”就指代猫,因此“it”更多吸收了“cat”的信息。第二个句子的“it”指代牛奶,因此“it”更多吸收了“milk”的信息。

    • The cat drank the milk because it was hungry.
    • The cat drank the milk because it was sweet.
  • 自注意力机制的目的是为当前单词创建抽象的、丰富的表征。这个表征是本单词被相同序列中的其它单词所影响的结果。经过自注意力机制处理之后,现在每个新单词都融入了其它单词的部分信息,这是一种数据依赖的加权平均,这种表征更加丰富。如果非要将自注意力机制和之前的注意力机制进行对比的话:

    • 自注意力机制中的query相当于注意力机制中的解码器隐藏状态。
    • 自注意力机制中的key和value相当于注意力机制中的编码器隐藏状态。

3.2 通用结构

通过上面的原理分析,我们可以知道,注意力的核心思想就是帮助模型为输入的不同部分分配不同的权重,这样可以提取关键信息,让模型判断更精准,更加节省算力和存储。但是如何实现注意力机制?这就要解决两个问题:

  • 在哪里做注意力计算?
  • 如何做注意力计算?

我们接下来就继续学习。

任务模型

论文”A General Survey on Attention Mechanisms in Deep Learning“用下图总结了注意力模型的通用结构,论文作者把这种通用架构叫做任务模型。任务模型包含四个部分:

  • 特征模型。我们假设矩阵X为任务模型的输入,矩阵的列可能是句子之中的单词。任务模型使用特征模型把X转换为特征向量F。特征模型可能是RNN、CNN、嵌入层或者其他模型。
  • 查询模型。q是由查询模型所产生的查询向量,用来确定任务模型需要关注X中的哪些向量、提取哪些信息。或者说,q可以被解释为一个一般问题:哪个特征向量包含对q最重要的信息?
  • 注意力模型。特征向量F和查询向量q是注意力模型的输入,注意力模型的输出是上下文向量c。我们会在接下来详细论述注意力模型。
  • 输出模型。输出模型使用上下文向量c将各个部分组合成最终的高级特征向量\(\hat y\),例如输出模型可以是softmax层,它输出一个预测。

我们用一个句子“北国的特产”为例来解释下图。图上X就是“北国的特产”这个完整的句子,F是从“北国的特产”提取到的特征向量列表,Z是“特”,q是从“特”提取出来的特征向量,我们目的就是要获取特征向量列表中哪个特征向量包含对于”特“最重要的信息。

注意力模型

注意力模型的内部流程如下图所示,该模型的目标是生成V中向量的加权平均值,具体计算流程如下。

  • 标号1是输入(两个输入),从输入生成的特征向量F会进一步生成键矩阵K和值矩阵V。
  • 标号2使用矩阵K和查询向量q作为输入,通过相似度计算函数来计算注意力得分向量e。q表示对信息的请求,\(e_l\)表示矩阵K的第\(l\)列对于q的重要性。
  • 标号3通过对齐层(比如softmax函数)进一步处理注意力分数,进而得到注意力权重a。
  • 标号4利用注意力权重a和矩阵V进行计算,得到上下文向量c。

QKV

因为此处提到了Q、K、V这三个术语,我们先用文本翻译为例来做初步介绍,后续章节会对Q、K、V进行深入分析。从上文的分析可知,序列中的每个单词都需要了解序列中其它单词的信息,从而才能确定彼此间的相互关系。因此每个单词都要去询问其它单词:咱俩之间是否密切?其它单词回复关系密切与否。拿到相互关系后,每个单词会据此把其它单词的信息吸收进来做信息融合。上述操作其实是一种搜索+合并的运算,我们需要找到一个适合的机制将这种运算进行落地。而上图注意力模型中,有两个输入:q(正在处理的序列)和F(被关注的序列),F又分别转换为K和V,这三个变量综合起来使用就可以满足我们的需求。

  • Q(查询矩阵):目标序列的每个元素把自己的特征总结到一个向量query之中,可以理解为某个单词像其它单词发出询问。目标序列所有元素的query构成了查询矩阵Q。
  • K(键矩阵):源序列的每个元素都会把自己的特征总结到一个向量key之中。可以理解为某个单词的特征,或者说某个单词依据自己特征来回答其它单词的提问。目标序列所有元素的key构成了键矩阵K。
  • V(值矩阵):源序列的每个单词的实际值(最终提供的信息)是向量value。源序列所有元素的value构成了值矩阵V。

后续我们用 query、key、value 代表相关向量,用Q、K、V代表相关向量构成的矩阵。

从词典的角度来看也许可以促进理解。query是你要找的内容,key是字典的索引(字典里面有什么样的信息),value是对应的信息。普通的字典查找是精确匹配,即依据匹配的键来返回其对应的值。而注意力机制是向量化+模糊匹配+信息合并。注意力机制不仅查找最佳匹配,还要依据匹配程度做加权求和。源序列每个元素转化为<key,value>对,这就构成了源序列的字典。目标序列每个元素提出了query,这就是要查询的内容。在查找中,目标序列中每个元素会用自己的query去和目标序列每个元素的key计算得到对齐系数。这个对齐系数就是元素之间的相似度或者相关性。query和key越相似就代表value对query的影响力越大,query越需要吸收value的信息。随后query会根据两个词之间的亲密关系来决定从V中提取出多少信息出来融入到自身。

通过 query、key、value 这三个向量的相互作用,模型得以衡量每个单词对其他单词的关注度。最终,源序列的每个元素会把自己融合其它单词提供的信息之后得到的真实数据放到一个向量中。

我们假设源序列和目标序列为同一个序列,下图中给出了序列中”一个“和其它单词之间的相似度。虚线代表key与query的相关度,线条的粗细分布就叫做”注意力分布“。或者说,线条的粗细就是权重,线条越粗,表示key与query越相关,对理解query越重要,value的权重就越大。

3.3 计算流程

我们把注意力机制引入到seq2seq领域来详细看看它的计算流程。

思路

我们首先看看总体思路。自注意力层是一种和循环层和卷积层等效的计算单元。它们的目的都是把一个向量序列映射成另一个向量序列,比如说编码器把x映射成中间表示z。我们先回想翻译场景。如果是RNN方案,则最终编码器会生成一个隐向量,然后把这个隐向量传递给解码器进行解码。前面已经分析了这种方案的弊端,比如隐向量是固定的。为了克服这种弊端,我们应该在每一个时间步t都会产生一个隐向量\(h_t\),把这些\(h_t\) 保存起来。当产生新输出时,我们让模型回顾之前保存的所有隐状态,发现隐状态中的关键信息就用上,这样就摆脱了RNN中隐向量是固定长度的弊端。但是如何判断某个隐状态对当前生成词是否重要?这就需要模型采用某种机制进行学习,从而才能了解需要给这个隐状态多少注意力。总而言之,注意力机制的任务应该是找到解码器当前隐向量和编码器所有隐向量之间的相互关系。按照上述思路,注意力机制的计算总体可以分为两步:

  1. 在所有输入信息上计算注意力分布。编码器不只是传递最后一个隐藏状态,而是传入所有的隐藏状态到解码器。
  2. 根据注意力分布来计算输入信息的加权平均。需要注意,这是一种数据依赖的加权平均,是一种灵活、高效的全局池化操作。

具体我们又可以把这两步拆解为5个详细步骤,具体如下:

  1. 生成语义向量。将源序列依次输入编码器,编码器依次执行,将源序列的信息<X1,X2,X3,X4>编译成step_len个语义向量<C1,C2,C3,C4>,供后续解码器使用。即针对输入序列中的每个单词,编码器都会输出一个隐状态向量,表示该单词及其上下文信息的表示。
  2. 计算对齐系数a。对于解码器输出的每个词Yi,我们需要关注源序列的所有词和目标序列中当前词的相关性大小。因此会在解码器输出每一个预测值之前,会针对编码器输出的所有语义向量<C1,C2,C3,C4>来计算一些注意力分数(Attention Score)。我们可以把源序列认为是key,把目标系列认为是query,这样就和上面的”注意力模型的内部流程“图对应起来。
  3. 计算概率分布。将对齐系数进行汇总,使用softmax进行归一化,得到注意力权重w。对这些分数进行softmax操作的目的是放大高分隐藏状态,抑制低分隐藏状态。后续我们将没有做softmax归一化之前的对齐系数称为注意力分数,将注意力分数经过softmax归一化后的结果称为注意力权重。
  4. 计算当前上下文向量Context。使用注意力权重w作为权重,对编码器所有的向量<C1,C2,C3,C4>进行加权求和,得到解码器当前时刻的上下文语义向量Context。注意力权重表示每个输入单词对于当前输出单词的重要程度。上下文向量表示当前输出单词所需的源语言信息。
  5. 更新解码器状态隐状态Hi。
  6. 计算输出预测词。把解码器前一次的输出、解码器当前状态和解码器当前时刻的上下文语义向量Context这三者作为输入,调用函数f()计算得到解码器本次的输出。这个输出是一个概率分布,表示每个可能的目标语言单词作为当前输出单词的概率。然后做一个概率值到目标词表的映射(如果注意力机制时用于分类模型,那就是做一个到各个分类的映射),便可以得到下一个输出单词。

以上步骤对应下图中标号1~6。

我们以“我吃了一个苹果”为例,每次输出的上下文如下:

  • 输入“我",得到C1=(我 * 1)。
  • 输入”吃了“,得到C2=(我 * 0.5, 吃了 * 0.5)。
  • 输入”一个“,得到C3=(我 * 0.45, 吃了 * 0.45, 一个* 0.1)。
  • 输入”苹果“,得到C4=(我 * 0.3, 吃了 * 0.3, 一个* 0.1, 苹果 * 0.3)。

得到的注意力权重为 $$w_{3,1},w_{3,2},w_{3,3},w_{3,4}=softmax(g(Y2, C1, C2, C3, C4))$$。

我们接下来对几个关键概念再进行分析。

注意力分数

当模型需要决定给予序列中某个单词以多大的“注意力”时,它会计算该单词与其他单词之间的注意力分数。注意力分数是衡量序列中不同单词对当前单词的重要性程度的指标,或者说是目标单词和输入中某单词对齐的可能性大小。可能性越大就应该赋予更大的权重。大权重代表在生成输出时,当下预测单词应该更加关注源文本中其对应单词的信息。

注意力分数通过相似度计算函数得到。该函数一般接受key和value向量作为输入,输出key和value向量之间的相关性,即注意力分数。下图提供了这些函数的概述,其中\(q\)是查询向量,\(k_l\)是矩阵\(K\)的第\(l\)列。如果对应到seq2seq,则q可以认为是解码器输出的隐向量,k可以认为是编码器内部的隐向量。现实中,相似度计算函数是通过矩阵形式来计算,而非单独计算某一列。

注意力权重

得到注意力分数之后,模型会使用softmax操作将注意力分数进行归一化得到注意力权重,这样可以使得所有权重总和为1,确保所有源元素贡献的特征总量保持一定,也可以更加突出重要的权重。

加权求和

得到注意力权重之后,每个query都能从对应的key上获取相应的信息,此时,就需要由输出函数(Output Function)来将各个部分组合成最终的高级特征向量进行输出。在本阶段,注意力机制会以加权求和的模式对数据进行加工。这意味着每个单词在新的表示中不只是自身的信息,还包含了其他单词的信息,这帮助模型捕捉输入序列中的依赖关系。

\[w_i = \frac{f_{score}(K_i,Q)}{\sum f_{score}(K_i,Q)} \\Out = \sum f_{out}(w_i \cdot V_i) \]

小结

我们梳理下计算过程中的重点三步如下:

  • 计算分数(score function)。query和所有的key进行相似度计算,得到注意力分数。计算公式为\(s_i = a(q, k_i)\)
  • 归一化(alignment function)。使用softmax操作将权值进行归一化,计算公式为\(a = softmax(s_i)\)
  • 生成结果(context vector function)。使用a对value进行加权平均,可以理解为输出y是在value之间根据key-query的相似度进行内插值。计算公式为\(Attention\ Value=\sum_ia_iv_i\)

因此,注意力的思想可以改写为如下公式:通过计算相似性得出权重最后加权求和。

\[Attention(Target,Source)=Attention(Query,Source)=\sum^{Length_{Source}}_{i=1}Similarity(Query,Key_i)*Value_i \]

具体如下图所示。

3.4 问题解决

回忆下之前提到的RNN方案和CNN方案遇到的问题:对齐问题、信息遗失问题和长依赖问题。以及为了从根本上解决这些问题,我们提出的几种改进思路:

  • 通过拓展隐状态的长度,或者增加新影响力因子来增加信息含量。
  • 让序列中两个词之间的关系距离更近,或者让各个词直接建立联系。
  • 平等看待序列中每个单词的顺序,避免忽略靠前的输入。
  • 对于序列进行”划重点“以区别不同元素所携带的信息量。
  • 同时向前预测和向后回顾。

我们接下来就以自注意力机制为例,看看其如何通过自己的优点来解决之前提到的问题,顺便也和这两个方案做下对比分析。

增大信息含量

与RNN、CNN方案相比,自注意力机制可以增大信息含量,从而有效的解决RNN中的信息遗失问题。从某种程度上来看,所有的序列建模都在做如下操作:

  • 把历史上下文存储到一个隐藏状态。
  • 依据一定的更新规则对这个隐藏状态进行变换。

下图就展示了序列建模方式的特点和典型案例,这些典型案例都包括三个组件:初始状态、更新规则和输出规则。

RNN方案中,解码器把过去所有的上下文信息压缩到一个固定大小低维向量(隐状态)中。解码器的不同阶段都使用这个隐状态。该方案的优势是在长上下文中的线性(相对于二次)复杂性。但是在长上下文时,RNN受限于固定大小的隐状态(表达能力有限),很难利用额外的条件信息。

TTT(Test-Time Training)则把上下文压缩到模型的权重中,其优势是既能在时间上保持固定大小,又能大大增强表达能力。

自注意力机制使用一个列表(从后续文章中我们会知道这其实是KV Cache)作为隐状态。所有的上下文都存储在列表中,没有被压缩。列表中所有的上下文共同构成了统一的隐状态(每个阶段的隐状态是列表的一项),这样编码器可以将更多数据传递给解码器。

因此,我们可以看到自注意力机制(Transformer)的优势:不只像RNN那样只传递一个编码器最终的隐状态,而是传入所有的隐藏状态(对应处理过的所有token)到解码器。这样新的token就可以和过去所有上下文进行交互。当然,随着上下文长度的增加,使用列表的成本也会越来越高,其处理时间随上下文长度急剧增长,列表的内存也急剧增加。

缩减单词间距

我们还是搬出之前的图来进行辅助解析。

自注意力机制中,当某单词获取其它单词信息时,其它单词和它的位置距离都是固定常数。这样,两个词之间的紧密程度仅取决于它们的真实相关性,而非取决于距离。或者说对绝对位置不敏感,任意两个词都可以直接建模。该特点可以解决长距离依赖问题。我们具体分析下。

首先,CNN虽然可以借助增加卷积层数来扩大视野,融合信息,但是信息在过深的网络传播过程之中容易丢失,导致模型性能下降。自注意力机制摒弃了 CNN 的局部假设,把感知域(perceptive field)调整到了整个序列。RNN方案因为无法弥补长距离依赖问题会导致梯度消失和梯度爆炸问题。在处理任何一个单词时,自注意力可以注意到整个句子的所有单词,这样可以将序列中的任意两个位置之间的距离缩小为一个常量,能在常数时间内有效地捕捉到它们之间的依赖关系,直接建立联系,从而消除了距离概念。因为此特点,自注意力机制的信息传播损失小。下图为三个方案构建词语之间关系所需距离的对比。

另外,常数距离特点也让自注意力机制没有“有序假设”。让自注意力机制在处理每个位置时,并非像RNN那样更容易注意到靠后的内容,忽略靠前的输入。而是平等看待序列中每个单词的顺序,这样能够有效得考虑到输入序列中的其他位置,可以更好的将对其他单词的“理解”融入到当前处理的单词中,信息融合效率高。

最后,常数距离特点让自注意力机制没有了递归的限制,像CNN一样可以在每一层内实现并行。

选择性处理信息

注意力机制可以选择性地关注和处理相关信息,这样即可以提纲挈领,又可以有效地解决对齐问题。

加权求和

加权求和可以分为加权和求和两方面来看,前者是对数据进行有差别的对待,而后者是做数据融合,综合在一起就是用提纲挈领(对于不同信息量的元素给予不同的关注度)的方式对数据进行加工。我们接下来从不同角度对加权求和与CNN、全连接层进行比对分析。

首先,注意力机制是动态产生权重。CNN或者全连接层的权重是静态权重,这些权重在训练时候固定下来,在推理时使用相同权重进行推理,并没有建立权重和输入实体本身的关系。注意力机制是动态权重,用输入的query、key通过相似度计算来得到注意力权重。注意力机制根据输入来计算出输出应该更关注哪些输入,权重的产生随着输入变化,这是一种自适应操作。

其次,从另一个角度来看,注意力机制是站在某个输入对象的立场上看待上下文和它之间的关系,并以此关系为权重来确定如何吸取其它对象的信息。因此,注意力机制是一种相对关系建模。而这种操作大多采用全局注意力以建模更广范围的依赖关系,是一种全局操作。

综上所述,加权求和以一种动态、相对、全局的关系更好的完成了对序列信息的处理。

对齐机制

将注意力应用在序列转换的源序列和目标序列之间就是对齐机制。在机器翻译中,源序列中的每个单词都可能会对输出造成影响,不仅仅是待翻译词之前的输入,其后续的输入也可能对输出产生影响,因此需要结合源序列和目标序列进行综合考虑。比如下面中译英的例子,当翻译到”一个“时,我们无法确定英文应该翻译成”a“还是”an“,必须往后看到”苹果“才能确定,因此需要在翻译时把”a or an“的操作和”苹果“进行对齐。

中文:我吃了一个苹果,然后吃了一个香蕉。

英文:I ate an apple and then a banana。

注意力允许依据输入序列和输出序列的不同部分进行相关度计算,这样就可以决定在输出某个单词时,模型将重点关注输入数据的哪些部分。从而在输入序列和输出序列进行对齐,更准确地学习序列之间的关系,提高模型的泛化能力和性能。下图中虚线代表key与query的相关度,线条越粗,表示越相关。我们可以看出来,“一个”和“苹果”等词对“an”的编码更重要(或更相关或更相似),应该承担更多的对“an”的预测,需要赋予更多的权重。因此,在模型生成“an“的时候,不但要从”一个“提取语义,也要从”苹果“提取语义,才能判断出来应该是”an“还是”a“。最终”一个“和”苹果“共同决定了对应的英文单词应该是"an"。

同时前瞻和回顾

编码器可以同时从左到右和从右到左读取输入序列,并将每个时间步的隐状态拼接起来作为输出。这样做的好处是,可以让编码器同时考虑输入序列中每个单词的前后上下文信息,从而生成更丰富和完整的表示。

3.5 优劣

综上所述,注意力机制确保每个解码步骤都由最相关的上下文片段提供信息,为长期存在的长距离依赖问题提供了稳健的解决方案,从而重新定义了序列建模的格局。而且,注意力机制的提出不仅是技术上的突破,也为机器学习领域开辟了新的视野,更反映了人类认知的深刻影响。正如 Andrej Karpathy 所评价的:“注意力是一种重大解锁,是神经网络架构设计的一次飞跃。”

注意力机制并非完美方案,其也存在若干缺点,最主要的问题就是计算速度慢和存储占用高。

  • 算力需求大。注意力机制需要计算序列中每个元素对其他每个元素的关系,因此随着输入序列长度的增加,计算量呈平方级增长。这在处理长序列时尤其成为问题,限制了大语言模型的最大序列长度N的大小,这就是在发展初期,大模型往往只支持2K或4K token输入的原因。 与之对应,RNN只要考虑之前的隐状态和当前输入。
  • 内存消耗大:与计算复杂度类似,注意力机制在处理长序列时,需要存储大量的中间结果,对内存的要求很高。

0x04 注意力发展历史

注意力机制只是一种思想,可以用到很多任务上。我们接下来看看几个经典的使用注意力机制对Encoder-Decoder进行改进的案例,也梳理一下历史上的重要节点。用范伟的话说:我们要知道Transformer是怎么来的。当然,我们也希望可以看到Transformer是怎么没的,毕竟如果有新方案取代了Transformer,那就说明AI领域将迎来新的历史性突破。

我们首先用一个图来展示下注意力发展历史。大家可以看到, Transformer是建立在很多巨人肩膀之上的集大成者。

此处参考了 "看图学大模型:Transformers 的前生今世(上)"。

4.1 RCTM

论文Recurrent Continuous Translation Models 被认为是神经网络机器翻译(NMT)的开篇之作,其特点如下:

  • 使用编码器-解码器框架。编码器用CNN实现,解码器用RNN实现。
  • 编码器将源文本转换成连续的上下文向量,解码器将上下文向量转换成目标语言。
  • 解码中的每一步都用到了编码器生成的上下文向量。
  • 端到端神经网络模型。

4.2 RNN 编码器-解码器

论文"Learning Phrase Representations using RNN Encoder–Decoder for Statistical Machine Translation"这篇是Bengio 团队的成果,其特点如下:

  • 明确了编码器和解码器的概念,且都用RNN来实现。

  • 解码的每一步都用到了编码器生成的隐向量。

  • 没有把编码器-解码器做成一个端到端的模型,只是把解码器的输出概率作为特征喂给了统计机器翻译(SMT)模型。

4.3 Sequence to Sequence Learning with Neural Networks

论文“Sequence to Sequence Learning with Neural Networks”也起到了重要作用,其特点如下:

  • 使用端到端结构。
  • 用RNN实现编码器和解码器。
  • 将编码器生成的上下文作为解码器的初始化参数。

4.4 Bahdanau Attention

论文“Neural Machine Translation by Learning to Jointly Align and Translate”提出的Bahdanau Attention是Attention的开创者之一。其特点如下:

  • 端到端模型。
  • 在编码器-解码器的基础上增加了注意力机制,即提出了注意力概念。
  • 编码器生成的上下文向量不再作为解码器每一步的输入。
  • 因为解码器依然是RNN,所以没有解决并行问题。

作者在论文中使用注意力机制解决了如何建模“与距离无关的依赖”,如何把编码器产生的信息更有效的传递给解码器的问题。这样注意力机制就和RNN一起配合,解决了遗忘和对齐问题。

  • 对齐问题。作者认为在翻译过程中,输入和输出两种语言中相同含义的词或者段落应该能对齐。但是目前没有做到,因此作者使用了一个网络来计算两种语言间不同单词的关联分数,即注意力分数。
  • 遗忘问题。作者使用注意力机制打破了传统RNN方案中依赖固定长度上下文信息的限制。
    • 作者认为该固定长度的上下文信息限制了模型性能,是瓶颈所在,需要编码器的上下文包括更多的有效信息。而且之前解码器每个时刻用到的语义向量都是编码器生成的同一个上下文信息,也就是最后一个时间步的隐藏层输出。作者认为不合理,因为通常一个词的语义更依赖与原句子中这个词附近的词的意思,而非最后一个时间步的输出。对于解码器来说,每个时刻的上下文向量都应不同。
    • 为了解决上述问题,作者构建的注意力机制把编码器所有的隐状态都利用起来。编码器每个时间步都考虑全部编码序列,由解码器来决定编码后的序列中哪个部分最重要,从而给予更高的权重,然后在全部编码序列基础上计算一个上下文向量。

!Andrej Karpathy分享了Dzmitry Bahdanau 的私人邮件,从中我们可以看到,为了克服编码器和解码器之间的瓶颈,Dzmitry Bahdanau的思路发展历程。

  • 最初的设计灵感来自“两个光标”的概念,即通过动态规划,让两个光标分别移动在源序列和目标序列中。然而,这种方法太复杂且实现困难。
  • Dzmitry Bahdanau退而求其次,尝试了一种“硬编码的对角线注意力”,尽管结果尚可,但仍显笨拙。
  • 真正的突破发生在Dzmitry Bahdanau的一次灵感闪现中:为什么不让解码器自主学习关注源序列中的相关部分?这一想法源自英语翻译练习。在翻译时,眼睛(注意力)会在源句和目标句之间反复移动。Dzmitry Bahdanau将这种软搜索设计为 softmax 操作,并结合双向 RNN 的状态进行加权平均。

可以看到,突破性的想法往往来自那些在实践中寻求解决问题的创新者,而非空想理论家。Dzmitry Bahdanau在邮件中说得非常好:

我的AI宏愿是启动更多像机器翻译项目那样的惊人应用项目。优秀的研发工作对基础技术的进步贡献远胜过那些我们常认为是“真正”AI研究的复杂理论。

4.5 Luong Attention

论文“Effective Approaches to Attention-based Neural Machine Translation”基于Bahdanau Attention对注意力机制的计算方式进行多样性探索。

  • 首先依据计算区域的大小将对齐函数分为局注意力(Global Attention)和局部注意力(Local Attention)两种机制。全局注意力模式在编码器每一步中都会基于所有词计算出隐状态。局部注意力模式则只计算部分子集的隐状态。
  • 其次依据所用信息把对齐函数分为基于内容的对齐和基于位置的对齐。前者同时考虑了编码器的隐状态 \(\tilde h_s\) 和解码器当前步的隐状态\(ℎ_t\)。后者只考虑了编码器当前步的隐状态 \(ℎ_t\)

下图是局部注意力。

下图呈现了全局注意力。

Luong Attention和Bahdanau Attention的具体区别如下:

  • 在生成语义向量时存在区别。

    • Luong Attention使用当前解码器的隐状态来计算对齐向量,而Bahdanau Attention使用先前的隐状态。
    • Luong使用多种对齐函数,而Bahdanau使用相加方式。
  • 在传递上下文向量进行预测时也有区别。

    • 基本模块不同。计算隐状态时,Luong Attention使用LSTM,Bahdanau Attention用的是双向RNN单元。
    • 解码器计算隐状态的流程不同。Luong模型里单独使用了一个隐状态\(\tilde s_t\)来计算输出\(y_t\)
    • 解码器的输入输出不同:
      • Bahdanau Attention的输入是\(c_t\)\(h_{t-1}\)拼接,然后计算得到\(h_t\),最终输出\(y_t\)
      • Luong Attention的输入是\(c_t\)\(h_t\)拼接,然后利用额外的网络结构计算得到\(\tilde h_t\),最终输出\(y_t\)

4.6 ResNet

ResNet是何凯明大神的经典之作,其可以有效解决梯度消失/爆炸问题,让神经网络层数的瓶颈得以突破。后面有文章详细讲解,这里不再赘述。

4.7 Self Attention

之前的注意力机制都关注不同序列之间的注意力,即交叉注意力。而论文Long Short-Term Memory-Networks for Machine Reading在交叉注意力的基础上提出了self-attenton(自注意力机制),或者叫 intra-attention。作者认为我们在顺序地阅读每个单词的时候,每个单词和前面单词的关联度是不一样的,因此使用了注意力机制来完成这个分析工作。

论文的动机如下。传统的LSTM在处理输入时把句子视为单词序列,并递归的将每个词与之前的记忆结合起来,直至得到整个句子的语义表示。这种方案面临两个问题:

  • 在递归过程中记忆存在压缩的问题,哪些部分在压缩中能被记忆是未知的。LSTM在循环压缩下的记忆序列能力存在疑问。LSTM的假设是:当前的状态能够汇总所有LSTM看到的token。传统的LSTM只有两个输出,一个是memory cell,另一个是hidden state。在时刻t,这两个输出分别代表t时刻前的所有memory和hidden state。在马尔科夫条件下,这个关系可以无限制的表示整个序列,但是在实际中这并不可行,即在序列足够长的时候,LSTM的假设无法成立。
  • 输入结构化存在问题。LSTM 按照序列顺序一个一个token来整合信息,但其没有明确的机制从结构中推理,即难以对token之间的关系进行建模。

此论文针对这两个问题进行处理。

  • 对于记忆压缩问题,论文设计了memory/hidden tape 来进行解决,每个token都对应一个隐藏状态向量和记忆向量。
  • 对于结构化输入的问题,论文引入intra-attention,利用通过hidden tape计算出某个词与其之前词之间的相关程度。事实上就是利用每个词的隐藏状态向量和记忆向量用来做注意力计算。

具体思路如下图。

在对两个序列的alignment(语义对齐)建模方面,此论文提出了两种方法。

  • 浅融合模型:将传统编码器-解码器中的LSTM替换为LSTMN,并用inter-attention进行对齐。
  • 深融合模型:结合inter-attention和intra-attention来更新状态,将序列内部的关系和序列之间的关系进行深度融合。

4.8 QKV-Attention

论文QKV-Attention: FRUSTRATINGLY SHORT ATTENTION SPANS IN NEURAL LANGUAGE MODELING这可能是最早提出QKV概念的论文。

作者认为目前注意力机制的隐向量承担了太多功能,这样会分身乏术,影响模型效果。因为同一个词,它在背景向量中的意义和它作为查询词时候代表的意义不同,所以要区分开来。因此该论文对每个时间步产生的输出向量进行分割成三个向量key, value, predict,各自有不同的分工。以下是修改逻辑和历程。

Attention for Neural Language Modeling

原始模型结构如下图所示,神经网络语言模型只有一个输出向量,同时用来计算注意力向量,编码历史上下文信息和预测下一个词的分布。

Key-Value Attention

论文作者将原始模型的输出划分成两部分:key和value,用key来计算注意力向量,用value来编码下一个词的分布和上下文信息。

但是value仍然同时被用来编码上下文信息和下一个词的分布表示(既要对查询的结果负责,又要对聚合的结果负责),一心二用容易出错。因此作者做了进一步改进。

Key-Value-Predict Attention

新模型结构如下图所示,作者对原始模型的输出做进一步划分为三部分:key,value和predict。用key来计算注意力向量,用value来编码上下文信息,用predict来编码下一个词的分布。

N-gram Recurrent Neural Network

作者又继续进行改进,将原始模型的输出划分成N-1部分,用前N-1个时间步的输出向量的一部分来计算下一个词的分布表示。模型结构如下图所示。

4.9 MultiHead Self Attention

论文Self Attention & MultiHead Attention : A STRUCTURED SELF-ATTENTIVE SENTENCE EMBEDDING 把注意力机制用到了文本表示学习中,让注意力机制完成多项工作。论文的注意力计算过程如下:

  • 输入为一个包含n个token的句子。
  • 使用双向LSTM处理句子,得到一个单独句子中邻接词的一些依赖,即隐向量。
  • 将隐向量拼接成H。
  • 使用自注意力机制把隐藏状态H进行转换,得到向量权重a。
  • 通过a提供的权重来求和LSTM隐藏状态H,得到一个输入句子的向量表示\(m\ \epsilon R^{1\times 2u}\)。多个m专注于句子的不同部分,借此来表示句子整体语义。
  • 进行多头自注意力计算。通过将矩阵A和LSTM隐藏状态H相乘得到句子嵌入。此处的矩阵乘AH和Transformer的注意力计算方式有些近似。

4.10 Multi-step Attention

论文[Convolutional Sequence to Sequence Learning](Convolutional Sequence to Sequence Learning) 使用CNN模型结合注意力机制进行操作,从而解决RNN不能并行的问题。

与RNN相比,CNN存在一定的优势。一来CNN可以并行处理,因此训练速度快,二则RNN并不能很好地处理句子中的结构化信息。因此,作者使用CNN来做编码器和解码器,利用层次结构来捕获词之间远程的依赖关系,也可以更好地捕捉更复杂的关系。在解码过程中,每一个卷积层都会进行注意力操作,称为multi-step attention。

4.11 小结

我们可以看到,在上述的演进过程中,Transformer所包括或者说所需要的组件一步步的被实现出来。然而上述注意力方案中依然有RNN、CNN的存在,这拖了后腿。比如RNN无法并行训练,不利于大规模快速训练和部署,也不利于整个算法领域发展。

因此,Transformer作者彻底摒弃了RNN和CNN,构建了一个全新的序列转换架构。Transformer整个网络结构完全是由注意力机制组成,通过把序列元素两两直接比较,Transformer可以学习到输入序列里所有词的相关性,一步到位捕捉到全局的联系。同时,因为Transformer不是按顺序分析,这样它可以并行操作,也使得它比 RNN 具有更高的计算效率和可扩展性。最终,Transformer就是这样一个融汇贯通的集大成者。

当然我们也要看到,RNN和CNN一直没有放弃努力,各自的发展也是有声有色。尤其在强化学习领域,RNN更是在发挥巨大的作用。我们也期望未来会有更多创新的模型和方法来让Transformer在强化学习领域发挥更大的作用。

下一篇我们介绍Transformer的总体架构。

0xFF 参考

A General Survey on Attention Mechanisms in Deep Learning Gianni Brauwers and Flavius Frasincar
Andrej Karpathy 首次公开私人邮件:揭秘Transformer 注意力机制真相 AI寒武纪
Attention is All your Need
Bahdanau 和 Luong Attention 直观介绍 Honoria
[Convolutional Sequence to Sequence Learning](Convolutional Sequence to Sequence Learning)
Effective Approaches to Attention-based Neural Machine Translation
Learning Phrase Representations using RNN Encoder–Decoder for Statistical Machine Translation
Long Short-Term Memory-Networks for Machine Reading
NEURAL MACHINE TRANSLATION BY JOINTLY LEARNING TO ALIGN AND TRANSLATE
NEURAL MACHINE TRANSLATION BY JOINTLY LEARNING TO ALIGN AND TRANSLATE
QKV-Attention: FRUSTRATINGLY SHORT ATTENTION SPANS IN NEURAL LANGUAGE MODELING
Recurrent Continuous Translation Models
Recurrent Continuous Translation Models
Self Attention & MultiHead Attention : A STRUCTURED SELF-ATTENTIVE SENTENCE EMBEDDING
Self Attention & MultiHead Attention : A STRUCTURED SELF-ATTENTIVE SENTENCE EMBEDDING
Self Attention 1: Long Short-Term Memory-Networks for Machine Reading
seq2seq中的两种attention机制(图+公式) 胡文星
Sequence to Sequence Learning with Neural Networks
Thang Luong's Thesis on Neural Machine Translation Minh-Thang Luong
Transformer自下而上理解(4) Attention without RNN marsggbo
《FRUSTRATINGLY SHORT ATTENTION SPANS IN NEURAL LANGUAGE MODELING》阅读笔记 Simple
一文看懂 Bahdanau 和 Luong 两种 Attention 机制的区别 Flitter
注意力机制 OnlyInfo
理解Attention:从起源到MHA,MQA和GQA Linsight
看图学大模型:Transformers 的前生今世(上) 看图学
第四篇:一文搞懂Transformer架构的三种注意力机制 AIwithGary
综述:图像处理中的注意力机制 极市平台
非Transformer架构的进展与猜想 StormBlafe

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/881164.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows的MySQL数据库升级(解压包方式)

1、背景描述 原来的 MySQL 在安装时,是最新的稳定版本 5.7.33 。 经过一段时间后,在原来的 MySQL 版本中,发现存在漏洞。 因为 MySQL 的官方补丁,需要 Oracle 的 si 码(Support Identifier),不是免费的。 因此,只好将旧版本(5.7.33)升级到没有漏洞的新版本(5.7.44)…

【数据库架构】基于自主可控数据库实现两地三中心容灾的探索与实践

【摘要】金融行业作为第二批次信创试点单位,在大力推广国产软件的背景下,如何保障业务连续性、满足监管部门RPT及RTO指标是新形势下的重要技术挑战,本文作者结合所在单位案例实践,阐述基于OceanBase分布式数据库实现两地三中心容灾的解决方案,供同行参考。 【作者】陈明福…

小包搜题考试

安规考试懒人专用 一、在应用软件商店搜索小包搜题二、微信中找到题库,在微信中点击打开,点击右上角三个点,选择用其他应用打开三、选择小包搜题,进入之后会自动导入题库并给题库命名(随意起),导入成功之后退出小包搜题四、重新进入小包搜题,点击右上角的录屏搜题五、弹…

Qt监控设备离线检测/实时监测设备上下线/显示不同的状态图标/海康大华宇视华为监控系统

一、前言说明 监控系统中一般有很多设备,有些用户希望知道每个设备是否已经上线,最好有不同的状态图标提示,海康的做法是对设备节点的图标和颜色变暗处理,离线的话就变暗,有可能是加了透明度,而大华的处理是有个清晰的图标表示,上线图标右下角有个绿色指示灯,离线的右下…

VIP视频解析之小工具(免费自取)

我们通常会因为看电影但是需要vip却没有足够生活费去支持的困扰 我就在想有没有白嫖的方法呢(bushi 就在我苦恼的时候我发现了一个方法————就是被称为:解析 的技术这玩意就是最好的选择 但是可能部分人在刚刚接触的时候不会用的于是我就写了一个小软件来支持(只支持wind…

2025年值得推荐的 8 款 WPF UI 控件库

前言 今天大姚给大家分享 8 款开源、美观、功能强大、简单易用的WPF UI控件库,希望可以帮助到有需要的同学。 WPF介绍 WPF 是一个强大的桌面应用程序框架,用于构建具有丰富用户界面的 Windows 应用。它提供了灵活的布局、数据绑定、样式和模板、动画效果等功能,让开发者可以…

github官网运行加速方法

github官网打不开的原因 访问github官网时是直接访问域名即github.com,中间有个域名通过DNS解析的过程,将域名解析为对应的ip地址,其实主要时间都是花在了DNS解析上,导致了github有时候能打开,有时候打不开,有时候访问很慢。 解决方案 1、Windows系统打开cmd,输入下列命…

关于AI生成艺术、自动驾驶汽车和Nutella片

Foto di Barbara Zandoval su Unsplash前言:当前时代人们似乎仍然坚信AI没有人类这样的创造力的!那人类的创造力又是什么呢?不也是从开始拥有认识能力,然后逐渐进化到现在空前的创造力的吗?如果AI也自我进化,创造力又能意味着什么? 我是个万事通。作为一名自由职业的在线…

MathType 7.4下载与安装

《数学公式编辑器(MathType)》 [1]是一款专业的数学公式编辑工具,理科生专用的工具。mathtype公式编辑器能够帮助用户在各种文档中插入复杂的数学公式和符号。 数学公式编辑器工具可以轻松输入各种复杂的公式和符号,与Office文档完美结合,显示效果超好,比Office自带的公式编…

支付流程设计常见问题及最佳实践

在实际操作中,支付流程常常面临诸多问题。本文将深入探讨支付流程设计中的常见问题及其最佳实践,供大家参考。今天聊一下支付流程设计的一些常见总是及最佳实践,包括: 组合支付要不要拆支付流水,前端轮询查哪个域,查询要不要穿透到外部渠道,为什么要做同步受理异步处理,…

原 侧边栏公告

<!-- 配置项详情见 https://bndong.github.io/Cnblogs-Theme-SimpleMemory/v2/#/Docs/Customization/config --><script type="text/javascript"> window.cnblogsConfig = {info: {name: , //「待填内容」 用户名startDate: , //「待填内容」 入园时间,…

读算法简史:从美索不达米亚到人工智能时代11搜索网络

20世纪70年代小型计算机普及,苹果推出Apple和Macintosh;蒂姆伯纳斯-李提出万维网,改变了网络访问方式;亚马逊采用个性化推荐算法;谷歌开发PageRank算法,引领网络搜索和关键字广告。1. 小型计算机 1.1. 到了20世纪70年代,小型计算机已在科研院所、大学和大公司中广泛应用…