【Transformer论文精读系列】(一)如何理解Transformer里的注意力机制?

论文:Attention Is All You Need

 

参考李沐老师的讲解视频:

 Transformer论文逐段精读【论文精读】_哔哩哔哩_bilibili

其他参考:

超强动画,一步一步深入浅出解释Transformer原理!_哔哩哔哩_bilibili

Transformer论文逐段精读【论文精读】 - 哔哩哔哩 (bilibili.com)icon-default.png?t=N7T8https://www.bilibili.com/read/cv14405845/?jump_opus=1(李沐老师讲解视频的文案)

1. 介绍

博客大纲

在接下来的博客中,我们将深入研究 Transformer 模型,从它的原论文出发,了解自注意力机制的工作方式,然后探讨编码器和解码器的结构,学习前馈神经网络的知识,分析实验部分。计划通过3篇左右的博客把这篇论文搞明白,本篇先展示论文的背景和自注意力机制的内容。

写在前边

2017年,一篇题为《Attention Is All You Need》的论文在自然语言处理领域掀起了一场革命。这篇论文由 Vaswani 等人(谷歌的团队)提出,介绍了一种全新的模型架构,被称为 Transformer。作者提出的时候主要是用于翻译问题,后续人们发现其在其他方面也表现十分优秀。这一模型架构的引入已经彻底改变了我们处理序列数据的方式,它不仅在自然语言处理中获得了巨大成功,还在计算机视觉、强化学习和其他领域展现出了巨大潜力。本博客将带您深入了解 Transformer 论文,揭示Transformer技术的原理、应用和未来趋势。

论文摘要部分

2. 背景

背景技术:从序列到自然语言处理

在过去,自然语言处理任务,如机器翻译、文本生成和情感分析,一直是计算机科学领域中的难题。传统方法通常依赖于手工设计的特征和规则,这使得模型的性能受到了限制。

然而,随着深度学习的崛起,我们开始看到了巨大的变化。深度学习模型,特别是循环神经网络(RNN)和卷积神经网络(CNN),在自然语言处理中取得了显著的进展。但是,这些模型仍然存在一些局限性,如处理长距离依赖性和训练复杂度。

相关工作

这里,涉及到了几个基本概念:

  • 序列转录模型(sequence transduction models),就是给模型一个序列,让模型来生成另外一个序列。(例如,输入一个英文序列,让其输出中文序列,以实现翻译工作)
  • 时序模型:需要处理时间序列数据的任务。

(以下文字摘取总结自原论文)

主流的序列转录模型主要基于CNN、RNN,包含编码器(encoder)和解码器(decoder)的部分。最好的模型是通过注意力机制来连接encoder和decoder。

时序模型中,当前常用的是RNN,包括LSTM、GRU

⭐ 本文提出的transformer

     1. 完全依赖于注意力机制,不需要循环和卷积,以绘制输入和输出之间的全局依赖关系

     2. 并行度高,在更短的时间内达到很好的效果

关于RNN:

沿着序列,从左往右移一步一步地进行计算(假设序列是一个句子,就一个个词地往前看)。对第t个词,会计算一个输出h_{t}(隐藏状态):h_{t}由前一个词的输出 h_{t-1}和 当前词本身决定。

好处:可以综合到前边学到的历史信息通过h_{t-1}

缺点:1. 一步步的计算过程,并行度低
           2. 如果时序比较长,很早的时序信息,在后边可能会被丢掉,或者导致h_{t}很大,导致内存开销也会很大

Attention在RNN上的应用:attention 已经被成功地应用在encoder-decoder中,主要是用在,怎么样把encoder的东西有效地传给decoder。但是,除了少数情况下,Attention都是在和RNN结合使用的。

现有的工作里,有人使用CNN替换掉RNN,可以减少时序的计算,如:Extended Neural GPU,ByteNet和ConvS2S。

关于CNN:

缺点:对于比较长的序列,难以建模。用卷积做计算的时候,每次看一个比较小的窗口,如果两个像素隔得比较远,需要用很多层卷积才能融合起来。

💡 作者可能是由此想到:可以使用Attention机制,每次能看到所有像素,一层就可以把所有序列看到。

好处:可以做多个输出通道,一个输出通道可以认为是它可以去识别不一样的模式。

💡 本文借鉴了多通道的思路,采用了多头注意力机制(Multi-head Attention)

Transformer的成功案例:BERT和预训练模型

Transformer 引入了自注意力机制,允许模型在处理序列数据时动态地捕获长距离的依赖关系,无需使用传统的递归或卷积操作。这个思想的革新性质,使 Transformer 迅速成为自然语言处理领域的翘楚。

Transformer 不仅改变了自然语言处理的方式,还催生了众多基于它的模型变体。其中最著名的之一是 BERT(Bidirectional Encoder Representations from Transformers),它在多项自然语言处理任务中取得了显著的性能提升。BERT 模型的成功启发了许多后续的研究,开辟了预训练模型的时代,这些模型在各种领域都表现出巨大的潜力。

论文结论部分

3. 模型架构

(以下文字摘取自论文源文,3 Model Architecture 第一段)

大多数序列转录模型具有编码器-解码器结构。这里,编码器将符号表示(x1,...,xn)转换为连续表示序列 z =(z1,...,zn)。给定z解码器然后生成输出序列(y1,...,ym)的符号一次一个元素。在每一步,模型都是自回归(autp-regressive)的,在生成下一个符号时,消耗先前生成的符号作为额外的输入。

Transformer遵循这种整体架构,编码器和解码器均使用堆叠的自注意和point-wise全连接层。

关于encoder-decoder架构的详细内容,会在下篇博客里介绍。

这里先占个坑。

第四章,会重点介绍以下,transformer里很重要的注意力机制的部分。

4. 自注意力机制(self-Attention)

自注意力机制是 Transformer 模型的核心组成部分,它为该模型带来了巨大的突破,允许模型动态地捕获输入序列中不同位置的信息,将单个序列的不同位置关联起来,以便计算序列的表示

可以应用于各种任务:阅读理解、抽象概括、文本蕴含、学习任务无关的句子表征等。

4.1 注意力机制基本概念

先来看看注意力机制(Attention Mechanism),这是一种通用的机制/技术,最初被应用于序列到序列(Sequence-to-Sequence,Seq2Seq)模型中,可以用于提供模型在处理序列数据时的关注机制

注意力机制允许解码器在生成每个输出的时候,动态地关注编码器输出序列中不同位置的信息,以便更好地决定输出的下一个元素。这种关注机制使得模型能够对输入序列中不同部分的信息赋予不同的重要性

Seq2Seq 模型中,编码器 将输入序列编码为固定长度的上下文向量,然后解码器使用这个上下文向量来生成输出序列。注意力机制可以帮助解码器更好地“关注”编码器输出中与当前解码步骤相关的部分。这样,解码器不会仅仅依赖于编码器整体的表示,而是可以针对性地根据输入的序列的不同部分调整其生成输出序列的过程。

比较抽象,举个🌰,以机器翻译为例:

  1. 编码器:将输入句子(例如法语)中的每个单词转换为对应的向量表示,并且编码整个输入句子的语义信息。

  2. 解码器:根据编码器输出的语义信息,逐步生成目标句子(例如英语)。在每个生成的单词或字符时,解码器可以使用注意力机制来查看编码器输出中与当前生成位置相关的部分,以帮助确定生成的单词或字符。(就相当于,让解码器,更关注于当前这个词(query)应该是什么value)

刚刚的感觉就是大概的 Attention 是用来干嘛的,接下来,来看一下attention 的基本概念,他到底是怎么实现的,先看transformer论文里的一段话:

上边这段话的大致意思就是:

attention function的作用query (查询)和一组 key-value对(键值对) 映射到输出 output,其中querykeyvalue输出都是向量。

计算方法
        每个value的权重 =  (query与对应key)的相似度函数  计算得到
        output = value加权和

(因为output其实是value的加权和,所以输出的维度与value 的维度是一样的。 对于每一个value的权重,它是value对应的key和查询的query的相似度(compatibility)算来的。虽然key-value没有变,但是随着query的改变,因为权重的分配不一样,所以输出的不一样)

query, key, value究竟是什么?

这些概念来自检索系统,比如,当你在某个平台搜索某种视频时,搜索引擎会将你的查询语句(query)映射到一组键(例如,视频标题、描述等),数据库中 有键值对,也就是(key)与其候选视频(value)是相关联的。然后通过看 query 与 key 的相似度,来给相关联的value分配权重,再展示最佳匹配视频(output,输出)。

看到一个讲的很好的视频,晕晕的同学,可以看看:

Attention之QKV_哔哩哔哩_bilibili

4.2 自注意力机制基本概念

自注意力机制是注意力机制的一种特殊形式,它不同于传统的注意力机制,因为它是在单个输入序列内部进行注意力计算的。它专注于单个输入序列内部的元素之间的交互。在自注意力中,Query、Key 和 Value 都是从同一个序列中提取出来的。

核心思想是让模型能够为输入序列中的每个元素分配不同的权重,以便根据上下文中的相关性来动态地加权。

自注意力的主要优势在于它的全连接性和能够处理长距离的依赖关系。相较于传统的递归和卷积操作,自注意力允许模型直接关注任意位置的信息,使其在处理序列数据时表现出色。

上边的话看不懂没关系,具体的过程跟注意力机制的是基本一样的,这里先结合一个例子,具体看一下每个步骤,再去看上边的文字。

1. Query, Key, Value的计算

当使用自注意力机制来处理一个简单的输入序列,比如说:“I”, “love”, “natural”, “language”, “processing”时,我们需要计算每个单词的 Query(查询)、Key(键)和Value(值)向量。

① 假设我们使用词嵌入来表示每个单词,并且每个单词的词嵌入维度为4。这意味着每个单词都会有一个4维的向量表示。假设我们有以下词嵌入向量:(这些词嵌入向量即为我们的输入序列的原始表示)

  • “I”:[0.2, 0.4, -0.1, 0.8]
  • “love”:[0.1, 0.9, 0.5, -0.3]
  • “natural”:[0.5, -0.2, 0.7, 0.6]
  • “language”:[0.3, -0.5, 0.2, 0.4]
  • “processing”:[0.6, 0.1, -0.7, 0.9]

② 假设有三个权重矩阵,每个矩阵的大小是4x4。(权重矩阵通常是模型的可学习参数,它们是在训练过程中通过梯度下降或其他优化方法学习到的。在自注意力机制中,这些权重矩阵用于将输入的词嵌入或特征向量转换为 Query、Key 和 Value 向量。这些权重矩阵的初始化可能采用不同的策略,例如随机初始化、Xavier 初始化、He 初始化等。然后,随着训练的进行,模型会不断调整这些权重矩阵的值,以适应训练数据的特征和模式,从而使模型更好地完成所需的任务。)

        

通过对每个词嵌入分别与这三个权重矩阵进行相应的线性变换,我们得到了每个单词的 Query、Key 和 Value 向量。

假设我们得到的线性变换结果是:

  • 对于每个单词的 Q 向量:

    • “I”:[0.62, 0.63, 0.79, 0.53]
    • “love”:[0.53, 0.76, 0.57, 0.34]
    • “natural”:[0.72, 0.64, 1.00, 0.62]
    • “language”:[0.66, 0.18, 0.76, 0.40]
    • “processing”:[1.09, 0.60, 1.57, 0.35]
  • 对于每个单词的 K 向量:

    • “I”:[0.39, 0.44, 0.60, 0.37]
    • “love”:[0.61, 0.68, 0.67, 0.31]
    • “natural”:[0.71, 0.78, 0.56, 0.38]
    • “language”:[0.23, 0.17, 0.38, 0.09]
    • “processing”:[1.02, 1.07, 1.04, 0.44]
  • 对于每个单词的 V 向量:

    • “I”:[0.08, 0.20, -0.26, 0.22]
    • “love”:[-0.47, -0.01, 0.03, -0.33]
    • “natural”:[0.29, 0.09, 0.51, 0.35]
    • “language”:[0.34, -0.29, 0.00, 0.21]
    • “processing”:[0.87, 0.65, 0.89, 0.45]

2. 计算相似度分数(Attention Scores)

接下来,我们计算每个Query向量与所有Key向量的相似度分数。这通常是通过点积或其他相似性度量完成的。(具体方法会在后续介绍)

3. 计算注意力权重(Attention Weights)

通过对相似度分数进行缩放和应用 softmax 函数,我们获得了注意力权重。这些权重决定了值向量在计算中的贡献。

4. 加权求和(Weighted Sum)

最后,我们使用注意力权重对值向量进行加权求和,以获得最终的自注意力表示。

4.3 Transformer中的自注意力机制 原理

Transformer 中使用的是自注意力机制,它允许模型在一个序列内部动态地关注不同位置的信息,捕捉长距离依赖关系,是实现并行计算的关键。他们称自己特殊的注意力机制为“Scaled Dot-Product Attention”(“点积注意力机制”)

重点来了,要上论文里的图和代码了!

4.3.1  Scaled Dot-Product Attention 缩放的点积注意力机制

        先看上边图的左边部分(右边的是多头注意力机制,会在3.2.2中讲解),我们来详细看看其处理过程。如图所示,自下往上,总共可以分为4+1步,其中:
         ①② 是4.2 中的第2步:计算Query 和Key的相似度。
        然后增加一个Mask 的步骤,是为了掩盖该时刻之后的值,方法就是将t时刻之后的值换成非常大的负数,这样在后续做softmax的时候,就会把算出来0作为权重,这样就可以掩盖掉后续的输出。
        ③就是4.2 中的第3步:计算注意力权重。 
        ④就是4.2中的第4步:加权求和。

        具体映射到公式上,如下图(标号与图片的步骤是对应的):

       再来详细看一下每一步:

① 做矩阵乘法:将Query矩阵与Key矩阵做内积

② Scale 缩放操作:再除以向量的长度\sqrt{d_{k}}

最常用的注意力函数,有两种:加法注意力,和点积注意力。本文的方法就是增加了Scale(缩放)点积注意力

加法注意力,additive attention:

        处理方法:使用具有单个隐藏层的前馈神经网络(feed-forward network)来计算相似度函数(compatibility function)。

        好处: 可以处理query和key不等长的情况

        

点积(乘法)注意力机制,dot-product (multiplicative) attention:

        处理方法:矩阵乘法

        好处:虽然两者在理论复杂度上相似,但点积注意力在实践中要快得多,空间效率更高,因为它可以使用高度优化的矩阵乘法代码来实现。(一次矩阵乘法,就直接算出来了所有 Q K的 相似度)

本文的Scaled Dot-Product Attention:

        💡虽然对于较小的dk值,上边的两种机制的表现相似,但在dk值较大的情况下,加法注意力优于点积注意力。Transformer的作者怀疑,对于较大的dk值(也就是俩向量很长),乘出来的点积值会很大,从而将softmax函数推到梯度非常小的区域。为了抵消这种影响,我们将点积缩放\frac{1}{\sqrt{d_{k}}}除以向量长度)。

        好处:对于dk较大的情况,点积让梯度更稳定

③ 做softmax: 对上述步骤得到的 n*m 的矩阵的每一行,用softmax得到权重。

        因为一个query会对m个key-value中的每个key做相似度,softmax的作用就是将每个 query的 m个值(也就是一行)变成非负的、加起来等于1的值,来作权重。

④ 再与V作矩阵乘法:将n * m 的 矩阵(n代表n个query,每一行,是一个key-value与该Q的权重)与V(Value组成的矩阵)相乘。得到每个query对应的输出。(这里的V的维度不一定与前边Q和K 的 一样,但是个数 是与Key一样的)

        

4.3.2 多头自注意力,Multi-Head Attention

Transformer 还引入了多头注意力机制

  • 做法输入序列分别用不同的权重进行自注意力计算,然后将它们拼接起来
  • 好处:这允许模型同时关注输入序列中的多个不同方面,从而提高了其表达能力,意味着模型可以学习多种不同类型的依赖关系。

又是比较抽象,不着急,我们先回顾一下,单头注意力机制是怎么做的:

  • 在单头注意力机制中,对每个 Query 向量都计算其与所有 Key 向量之间的相似度,得到注意力权重,然后将这些权重应用于对应的 Value 向量,最终得到加权求和后的输出

好像目前看起来也不是很麻烦,不就是矩阵嘛,两次矩阵乘法,有啥麻烦的。但是就像翻译工作,我们所关注的,可能是很多个特征空间/表示空间,比如:词序、语法结构等等,这些在代码中的就是通过让Q K Q 乘以特征矩阵来得到。

  • 如果是单头,就需要乘以一个巨大维度的QKV 特征矩阵来提取多方面信息。单头注意力机制涉及将输入的 Query、Key 和 Value 向量投影到同一个空间,并使用这些向量进行相似度计算和加权求和,计算复杂度较低,效率相对较高
  • 但是多头注意力机制,则是引入多组不同的 QKV 矩阵,允许模型在不同的子空间或表示空间上并行地学习和关注信息,增强了模型的表达能力,但也增加了一定的计算复杂度

具体来说,多头注意力机制就是引入了多个注意力头(通常是 h 个头),每个头都拥有自己的一组权重矩阵用于计算注意力权重。这些头是并行工作的,每个头都计算一组注意力权重,从而在不同的子空间或表示空间上独立地关注序列中的信息。

举个🌰:假设有一个输入序列,通过多头注意力机制,该序列会被映射到 h 个子空间中,每个子空间由一个注意力头负责关注。每个头都有自己的 Query、Key 和 Value 矩阵(WQ , WK, WV),对输入序列进行不同的线性变换,将序列投影到不同的特征空间中。然后,在每个头中,针对这些投影后的 Query、Key 和 Value 向量执行独立的注意力计算。这样,每个头都能够在不同的特征表示空间上计算序列中不同位置的注意力权重。

最后,将这些头计算得到的多个输出进行连接或拼接,并通过另一个线性变换来整合这些输出,形成最终的多头注意力机制的输出。这种方式使得模型能够同时关注不同子空间或表示空间中的信息,增强了模型的表征能力,有助于更好地捕捉序列内部的复杂关系。

 

        过程就如这张图的右半部分。

💡 与其做一个单个的注意力函数,用d_{model}l维的 Q K V,不如把整个query, key, value投影到一个低维,投影h次,再做h次的注意力函数,每个函数的输出并在一起,然后再投影回来,得到最终的输出

        然后,我们来看一下多头注意力的公式:

        维度的变化如下图所示:

注意,以下一些维度表示:

  1. d_model
    • d_model 是输入数据(例如序列中词的嵌入)的维度。在 Transformer 模型中,这个参数表示输入数据的特征维度。
    • 在自注意力机制中,输入的 Query、Key 和 Value 向量的维度都是 d_model
  2. d_k 和 d_v
    • d_kd_v 是用来控制注意力机制中 Query 和 Key 的维度以及 Value 的维度。
    • 通常情况下,d_kd_v 的值可以小于等于 d_model,并且通常是相等的。这样设计的目的是为了降低计算复杂度。
    • 例如,如果设定 d_k = d_v = d_model / h,其中 h 是注意力头的数量,那么就可以确保每个头的 Query 和 Key 的维度相等,而且每个头得到的 Value 的维度也相等。

还有些文章中,会:

  • 用 X 表示输入的矩阵,如词嵌入或者其他形式的向量表示。
  • W^Q, W^K, W^V 来表示各自的权重矩阵
  • 用Q, K, V 来表示,X与各自权重矩阵,乘完的结果,传入后续Attention函数
    • X 通过权重矩阵 WQ​ 映射为 Q(Query)向量。
    • X 通过权重矩阵 WK​ 映射为 K(Key)向量。
    • X 通过权重矩阵 WV​ 映射为 V(Value)向量。

看其他文章,会把n 和m 记为相同, d_k 和d_v 也记成相同的,但是实际上他们,可能是不一样的,所以,这里我用的各自的字母进行标识。

🍟写在后边

我一定努力把transformer的内容更新完,如果有写的不清楚,或者不正确的地方,欢迎讨论。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值