您现在的位置是:首页 >技术杂谈 >AutoCV番外:Transformer网站首页技术杂谈

AutoCV番外:Transformer

爱听歌的周童鞋 2024-06-17 10:22:10
简介AutoCV番外:Transformer

Transformer

前言

AutoCV 之后的课程中需要学习到 BEVFormer 先对 Transformer 做一个简单的了解

关于 Self-attention 和 Transformer 的内容均来自于李宏毅老师的视频讲解

视频链接:【机器学习2021】自注意力机制(Self-attention) 【机器学习2021】Transformer

在这里插入图片描述

1. Self-attention

聊 Transformer 之前需要聊聊 Self-attention。

以下内容均来自于李宏毅老师的 Self-attention 的视频讲解

视频链接:【机器学习2021】自注意力机制(self-attention)

1.1 前置知识

self-attention 解决的是输入的数目和序列长度不一致的问题,那在实际中有哪些应用会将一个向量集合 (Vector Set) 作为输入呢?
在这里插入图片描述

图1-1 复杂输入情形

图1-1 中对比了输入是简单 vector 和 复杂 vector set 两种情形。常见输入都是简单的 vector 应用有比如让你对 2023 年上海房价进行预测,比如给你一张图片需要你判断是那个动物等等。那也有输入是一个 vector set 形式,比如 chat Bot 聊天机器人,用户每次都会提供不同的问题,比如机器翻译,比如语言情感分析等等。

在文字处理方面,其输入常常是一句话或者一段话,比如当用户向 chatGPT 提问时,由于每次的问题都不一样,导致每次的输入都不同。self-attention 就是被用来处理这种问题的。

在正式介绍 self-attention 之前,我们需要了解到为了方便计算机的处理和计算,同时让计算机捕捉和理解词汇之间的语义关系,我们通常需要将一个词汇用一个向量表示。那么怎么把一个词汇描述为一个向量呢?

常见的有 one-hot encodingWord Embedding 方法,如 图1-2 所示

在这里插入图片描述

图1-2 词汇描述为向量方法

ont-hot encoding

  • 最先想到的可能就是 ont-hot 编码,考虑所有的词汇,比如常见的 3000 个单词,那么就编码为一个 3000 维的向量,每个词汇都在对应的位置设置为 1,其它设置为 0

  • 但是这种方法存在一个严重的问题:它假设所有词汇之间都是没有关系的,所以无法表达词汇之间的语义相似性,即从 One-hot Encoding 中你看不出来说 cat 和 dog 都是动物所有比较相像,cat 和 apple 一个动物一个植物所以比较不相像,这个向量里面是不存在任何语义信息,而且每个词汇向量的维度非常高,将会导致计算和存储的复杂性

Word Embedding

  • 词嵌入方法,它会分配给每一个词汇一个向量,那么一个句子就是一个长度不一的向量,具体的实现不是这里讲解的重点,可自行学习

  • 更多细节:https://www.youtube.com/watch?v=X7PH3NuYW0Q

知道了输入是一个 vector set,那么对应的输出也有以下几种可能,见 图1-3

  • Each vector has a label
    • 每个向量都有一个对应的标签,比如输入 4 个向量,输出 4 个标签
    • 比如在 Pos tagging 词性标注问题上,对于每个词汇给出对应的词性,例如 I saw a saw 其对应的输出为 N V DET N
  • The whole sequence has a label
    • 整个序列只有一个标签
    • 比如在 Sentiment analysis 情感分析问题上,对于一段话机器需要给出它是 positive 还是 negative
  • Model decides the number of labels itself
    • 模型自己决定输出标签的数量
    • sequence to sequence 任务,比如 chatGPT

在这里插入图片描述

图1-3 可能的输出

我们现在只考虑第一种情形,即每个向量都有一个标签,这个任务又叫做 Sequence Labeling,那么如何去解决这个问题呢?

在这里插入图片描述

图1-4 sequence labeling解决方法

比较容易想到的就是我们把每一个 vector 分别输入到全连接的网络里面,逐个击破,见 图1-4 但是这样会存在一个很大的问题。假如是词性标记问题,对 I saw a saw 进行标记,对全连接网络来说第一个 saw 和第二个 saw 完全一模一样呀,它们都是同一个词汇,因此网络没有理由会有不同的输出,而实际上你想要你第一个 saw 输出动词,第二个 saw 输出名词,而对于 FC 来说不可能做到。

那怎么办呢?有没有可能让 FC 考虑 contex 上下文信息呢?

是有可能的,我们将前后向量都串起来一起丢到 Fully-Connected Network 中就可以了,如 图1-5 所示

在这里插入图片描述

图1-5 sequence labeling解决方法优化

所以我们可以给 Fully-Connected Network 一整个 window 的信息,让它可以考虑一些上下文,考虑与目前向量相邻的其它向量的信息。

但是如果我们有一个任务,不是考虑一个 window 的 context 就可以解决,而是要考虑一整个 sequence 的 context 才能解决,那怎么办呢?

那有人可能会想说这个还不容易,我就把 window 开大一点嘛,大到可以覆盖整个 sequence,但是我们输入给 model 的 sequence 有长有短,每次都可能不一样,那么就可能需要统计下你的训练集,看下其中最长的 sequence 有多长,然后开一个比最长的 sequence 更大的 window,但是你开一个这么大的 window 意味着你的 Fully-connected Network 需要非常多的参数,不但计算量大,可能还容易 Overfitting

所以有没有更好的方法来考虑整个 input sequence 的信息呢?这就是接下来要介绍的 self-attention 这个技术

1.2 Self-attention机制

self-attention的运作方式就是吃一整个 sequence 的信息,然后你输入多少个 vector,它就输出多少个 vector

在这里插入图片描述

图1-6 self-attention运作方式

经过 self-attention 后的 4 个 vector 都是考虑了一整个 sequence 以后才得到的,再把这些考虑了整个句子的 vector 丢到 Fully-Connected Network 中得到最终的输出,如此一来,你的 Fully-Connected Network 它就不是只考虑一个非常小的范围或一个小的 window,而是考虑整个 sequence 的信息,再来决定现在应该要输出什么样的结果,这个就是 self-attention

当然你可以使用多次 self-attention,将 self-attention 和 Fully-Connected Network 交替使用,self-attention 来处理整个 sequence 的信息,而 Fully-Connected Network 专注于处理某一个位置的信息

在这里插入图片描述

图1-7 self-attention和Fully-Connected Network交替使用

有关于 self-attention 最知名的相关文章就是 Attention is all you need,在这篇文章中,Google 提出了我们熟知的 Transformer 这样的 Network 架构,Transformer 里面最重要的一个 Module 就是 self-attention。

讲了这么久,那 self-attention 到底是怎么运作的呢?

self-attention 的 input 就是一串 vector,而这个 vector 可能是你整个 Network 的 input,也有可能是某个 hidden layer 的 output,用 a oldsymbol a a 来表示而不是用 x oldsymbol x x 来表示,代表说它有可能前面已经做过一些处理,input 一排 a oldsymbol a a 向量之后,self-attention 需要 output 另外一排 b oldsymbol b b 向量,每个 b oldsymbol b b 都是考虑了所有的 a oldsymbol a a 生成出来的

在这里插入图片描述

图1-8 self-attention内部实现

接下来就是来说明怎么产生 b 1 oldsymbol b^{oldsymbol 1} b1 这个向量,知道怎么产生 b 1 oldsymbol b^{oldsymbol 1} b1 向量以后, b 2 oldsymbol b^{oldsymbol 2} b2 b 3 oldsymbol b^{oldsymbol 3} b3 b 4 oldsymbol b^{oldsymbol 4} b4 的产生你也就知道了,那么怎么产生 b 1 oldsymbol b^{oldsymbol 1} b1 呢?

首先根据 a 1 oldsymbol a^{oldsymbol 1} a1 找到 sequence 里面跟 a 1 oldsymbol a^{oldsymbol 1} a1 相关的其它向量。我们做 self-attention 的目的是为了考虑整个 sequence,但是我们又不希望将所有的信息放在一个 window 里面,所有我们有一个特别的机制,这个机制就是说找出整个很长的 sequence 里面到底哪些部分是重要的,哪些部分跟判断 a 1 oldsymbol a^{oldsymbol 1} a1 是哪一个 label 是有关系的。

那么每一个向量跟 a 1 oldsymbol a^{oldsymbol 1} a1 的关联程度我们用一个数值 α alpha α 来表示,接下来的问题就是 self-attention 这个 module 怎么自动决定两个向量之间的关联性呢?比如你给它两个向量 a 1 oldsymbol a^{oldsymbol 1} a1 a 4 oldsymbol a^{oldsymbol 4} a4,它怎么决定 a 1 oldsymbol a^{oldsymbol 1} a1 a 4 oldsymbol a^{oldsymbol 4} a4 有多相关,然后给它一个数值 α alpha α 呢?

在这里插入图片描述

图1-9 self-attention相关性机制

那么这边你就需要一个计算 attention 的模块,它的输入是两个向量,直接输出 α alpha α 数值,你就可以把 α alpha α 数值当做两个向量的关联的程度,那具体怎么计算这个 α alpha α 数值呢?比较常见的做法有 dot-productAdditive

dot-product

  • 把输入的两个向量分别乘以两个不同的矩阵 W q W^q Wq W k W^k Wk,左边向量乘以 W q W^q Wq 这个矩阵,右边向量乘以 W k W^k Wk 这个矩阵,接下来得到 q oldsymbol q q k oldsymbol k k 这两个向量
  • 再把 q oldsymbol q q k oldsymbol k kdot product,就是把它们做 element-wise 相乘再相加得到 α alpha α

Additive

  • 同样把输入的两个向量分别乘以两个不同的矩阵 W q W^q Wq W k W^k Wk,得到 q oldsymbol q q k oldsymbol k k 这两个向量
  • 然后串起来丢到 t a n h tanh tanh 函数中,再经过一个 Transform 得到 α alpha α

总之有非常多不同的方法可以计算 Attention,可以计算这个 α alpha α 的数值,可以计算这个关联的程度,但是在接下来的讨论里面我们都只用左边 dot-product 这个方法,这是目前最常用的方法,也是 Transformer 里面的方法。

在这里插入图片描述

图1-10 Attention的计算方法

接下来怎么把它套用到 self-attention 里面呢?对于 a 1 oldsymbol a^{oldsymbol 1} a1 需要分别计算它与 a 2 oldsymbol a^{oldsymbol 2} a2 a 3 oldsymbol a^{oldsymbol 3} a3 a 4 oldsymbol a^{oldsymbol 4} a4 之间的关联性,也就是计算它们之间的 α alpha α,那怎么做呢?

你把 a 1 oldsymbol a^{oldsymbol 1} a1 乘上 W q W^q Wq 得到 q 1 oldsymbol q^{oldsymbol 1} q1,这个 q oldsymbol q q 有个名字叫做 Query,也就是搜寻查询的意思,然后接下来对于 a 2 oldsymbol a^{oldsymbol 2} a2 a 3 oldsymbol a^{oldsymbol 3} a3 a 4 oldsymbol a^{oldsymbol 4} a4 你都要去把它乘上 W k W^k Wk 得到 k oldsymbol k k 这个 vector,这个 k oldsymbol k k 有个名字叫做 Key,也就是关键字的意思。那你把这个 Query q 1 oldsymbol q^{oldsymbol 1} q1 和这个 Key k 2 oldsymbol k^{oldsymbol 2} k2 计算 inner product 就得到 α 1 , 2 alpha_{1,2} α1,2,代表向量 1 和向量 2 之间的相关性,其中 Query 是由向量 1 提供,Key 是由向量 2 提供, α alpha α 关联性也有一个名称叫做 attention score

同理可计算出 α 1 , 3 alpha_{1,3} α1,3 α 1 , 4 alpha_{1,4} α1,4,如 图1-11 所示

在这里插入图片描述

图1-11 attention score计算

其实一般在实际应用中, q 1 oldsymbol q^{oldsymbol 1} q1 也会和自己计算关联性,所以你也要把 a 1 oldsymbol a^{oldsymbol 1} a1 乘上 W k W^k Wk 得到 k 1 oldsymbol k^{oldsymbol 1} k1,然后计算它的关联性 α 1 , 1 alpha_{1,1} α1,1

在这里插入图片描述

图1-12 attention score计算(考虑自关联)

我们算出 a 1 oldsymbol a^{oldsymbol 1} a1 和每个向量的关联性之和,接下来会做一个 softmax,输出为一组 α ′ alpha' α,在这边不一定要用 softmax,你可以尝试用别的东西也没有问题,比如 ReLU,

在这里插入图片描述

图1-13 attention score计算经过softmax

得到 α ′ alpha' α 以后,我们就要根据 α ′ alpha' α 抽取出 sequence 里面重要的信息,接下来我们要根据关联性,根据这个 attention 的分数来抽取重要的信息,怎么抽取重要的信息呢?

我们会把 a 1 oldsymbol a^{oldsymbol 1} a1 a 4 oldsymbol a^{oldsymbol 4} a4 这边每一个向量乘上 W v W^v Wv 得到新的向量,分别用 v 1 oldsymbol v^{oldsymbol 1} v1 v 2 oldsymbol v^{oldsymbol 2} v2 v 3 oldsymbol v^{oldsymbol 3} v3 v 4 oldsymbol v^{oldsymbol 4} v4 来表示,接下来把 v 1 oldsymbol v^{oldsymbol 1} v1 v 2 oldsymbol v^{oldsymbol 2} v2 v 3 oldsymbol v^{oldsymbol 3} v3 v 4 oldsymbol v^{oldsymbol 4} v4 每一个向量都去乘上 attention 的分数,都去乘上 α ′ alpha' α 然后再把它加起来得到 b 1 oldsymbol b^{oldsymbol 1} b1

在这里插入图片描述

图1-14 根据attention score提取信息

如果某一个向量它得到的分数越高,比如 a 1 oldsymbol a^{oldsymbol 1} a1 a 2 oldsymbol a^{oldsymbol 2} a2 的关联性很强,这个 α 1 , 2 ′ alpha'_{1,2} α1,2 得到的值就很大,那我们在做 Weighted Sum 以后得到的 b 1 oldsymbol b^{oldsymbol 1} b1 的值就可能比较接近 v 2 oldsymbol v^{oldsymbol 2} v2,所有这边谁的 attention 的分数越大,谁的 v oldsymbol v v 就会 Dominant 你抽出来的结果。

OK! 到这边我们讲解了怎么从一整个 sequence 得到 b 1 oldsymbol b^{oldsymbol 1} b1

在这里插入图片描述

图1-15 b1的计算

这边需要强调的是 b 1 oldsymbol b^{oldsymbol 1} b1 b 4 oldsymbol b^{oldsymbol 4} b4 并不需要顺序产生,你并不需要算完 b 1 oldsymbol b^{oldsymbol 1} b1 再算 b 2 oldsymbol b^{ oldsymbol 2} b2 再算 b 3 oldsymbol b^{oldsymbol 3} b3 再算 b 4 oldsymbol b^{oldsymbol 4} b4 b 1 oldsymbol b^{oldsymbol 1} b1 b 4 oldsymbol b^{oldsymbol 4} b4 它们是一次同时被计算出来的

1.3 矩阵乘法角度理解

a 1 oldsymbol a^{oldsymbol 1} a1 a 4 oldsymbol a^{oldsymbol 4} a4 得到 b 1 oldsymbol b^{oldsymbol 1} b1 b 4 oldsymbol b^{oldsymbol 4} b4 是 self-attention 的运作过程,接下来我们从矩阵乘法的角度再重新讲一次我们刚才讲的 self-attention 是怎么运作的。

我们知道每一个 a oldsymbol a a 都要分别产生 q oldsymbol q q k oldsymbol k k v oldsymbol v v,如果用矩阵运算表示这个操作的话是什么样子呢?
q i = W q a i oldsymbol q^{oldsymbol i} = W^q oldsymbol a^{oldsymbol i} qi=Wqai
每一个 a oldsymbol a a 都要乘上 W q W^q Wq 得到 q oldsymbol q q,那么我们可以把 a 1 oldsymbol a^{oldsymbol 1} a1 a 4 oldsymbol a^{oldsymbol 4} a4 拼起来看作是一个矩阵用 I I I 来表示,而矩阵 I I I 有四列,每一列就是 a 1 oldsymbol a^{oldsymbol 1} a1 a 4 oldsymbol a^{oldsymbol 4} a4,那 I I I 乘上 W q W^q Wq 就得到另一一个矩阵,我们用 Q Q Q 来表示, Q Q Q 就是 q 1 oldsymbol q^{oldsymbol 1} q1 q 4 oldsymbol q^{oldsymbol 4} q4

在这里插入图片描述

图1-16 矩阵角度分析q产生

所以我们从 a 1 oldsymbol a^{oldsymbol 1} a1 a 4 oldsymbol a^{oldsymbol 4} a4 得到 q 1 oldsymbol q^{oldsymbol 1} q1 q 4 oldsymbol q^{oldsymbol 4} q4 这件事情就是把矩阵 I I I 也就是我们的 input 乘上另外一个矩阵 W q W^q Wq,而 W q W^q Wq 其实是 Network 的参数,把 I I I 乘上 W q W^q Wq 就得到 Q Q Q,而 Q Q Q 的四个 column 就是 q 1 oldsymbol q^{oldsymbol 1} q1 q 4 oldsymbol q^{oldsymbol 4} q4

那么接下来怎么产生 k oldsymbol k k v oldsymbol v v 呢?它的操作其实跟 q oldsymbol q q 是一模一样的,如 图1-17 所示:

在这里插入图片描述

图1-17 矩阵角度分析kv产生

所以每一个 a oldsymbol a a 怎么得到 q oldsymbol q q k oldsymbol k k v oldsymbol v v 呢?其实就是把输入的这个 vector set 乘上三个不同的矩阵,你就得到了 q oldsymbol q q k oldsymbol k k v oldsymbol v v

那么接下来每一个 q oldsymbol q q 都会去跟每一个 k oldsymbol k k 去计算 inner product 得到 attention 的分数,那得到 attention score 这件事情,如果从矩阵操作的角度来看,它在做什么样的事情呢?

比如 α 1 , i = ( k i ) T q 1 alpha_{1,i} = (oldsymbol k^{oldsymbol i})^T oldsymbol q^{oldsymbol 1} α1,i=(ki)Tq1,我们可以将 k 1 oldsymbol k^{oldsymbol 1} k1 k 4 oldsymbol k^{oldsymbol 4} k4 拼接起来看作是一个矩阵的四个 row,再把这个矩阵乘上 q 1 oldsymbol q^{oldsymbol 1} q1 就得到另外一个向量,这个向量里面的值就是 attention score, α 1 , 1 alpha_{1,1} α1,1 α 1 , 4 alpha_{1,4} α1,4

在这里插入图片描述

图1-18 矩阵角度分析attention score(一)

我们不止是 q 1 oldsymbol q^{oldsymbol 1} q1 要对 k 1 oldsymbol k^{oldsymbol 1} k1 k 4 oldsymbol k^{oldsymbol 4} k4 去计算 attention score,还有 q 2 oldsymbol q^{oldsymbol 2} q2 q 3 oldsymbol q^{oldsymbol 3} q3 q 4 oldsymbol q^{oldsymbol 4} q4 也要按照上述流程计算 attention score

在这里插入图片描述

图1-19 矩阵角度分析attention score(二)

那么这些 attention scores 是怎么计算得来的?你可以看作是两个矩阵 K K K Q Q Q 的相乘,一个矩阵的 row 就是 k 1 oldsymbol k^{oldsymbol 1} k1 k 4 oldsymbol k^{oldsymbol 4} k4,另外一个矩阵的 column 就是 q 1 oldsymbol q^{oldsymbol 1} q1 q 4 oldsymbol q^{oldsymbol 4} q4,得到矩阵 A A A,那矩阵 A A A 存储的就是 Q Q Q K K K 之间 的 attention 分数

那么接下来我们会对 attention 的分数做一下 normalization,对这边的每一个 column 做 softmax,使得每一个 column 的值相加为 1,前面有提到过做 softmax 并不是唯一的选项,当然你完全可以选择其它的操作,比如说 ReLU 之类的,得到的结果也不会比较差

在这里插入图片描述

图1-20 矩阵角度分析attention score(三)

接下来,我们需要通过 attention 分数矩阵 A ′ A' A 计算得到 b oldsymbol b b,那么 b oldsymbol b b 是怎么被计算出来的呢?你就把 v 1 oldsymbol v^{oldsymbol 1} v1 v 4 oldsymbol v^{oldsymbol 4} v4 拼起来,当成是 V V V 矩阵的四个 column,然后让 V V V 乘上 A ′ A' A 得到最终的输出矩阵 O O O

在这里插入图片描述

图1-21 矩阵角度分析输出b的产生

O O O 矩阵里面的每一个 column 就是 self-attention 的输出,也就是 b 1 oldsymbol b^{oldsymbol 1} b1 b 4 oldsymbol b^{oldsymbol 4} b4

所以说 self-attention 的整个操作是先产生了 q oldsymbol q q k oldsymbol k k v oldsymbol v v,然后再根据 q oldsymbol q q 去找出相关的位置,然后再对 v oldsymbol v v 做 weighted sum,其实这一串操作就是一连串矩阵的乘法而已

在这里插入图片描述

图1-22 矩阵角度分析self-attention整个过程

其中 I I I 是 self-attention 的 input,是一组 vector,即 vector set,这组 vector 拼起来当作矩阵 I I I 的 column,那这个 input 分别乘上三个矩阵 W q W^q Wq W k W^k Wk W v W^v Wv 得到 Q Q Q K K K V V V 三个矩阵,接下来 Q Q Q 乘上 K T K^T KT 得到矩阵 A A A,矩阵 A A A 经过一些处理得到 A ′ A' A,我们会把 A ′ A' A 称作 Attention Matrix,最后将 A ′ A' A 乘上 V V V 得到 O O O O O O 就是 self-attention 这个 layer 的输出。所以 self-attention 输入是 I I I 输出是 O O O,self-attention 中唯一需要学习的参数就是 W q W^q Wq W k W^k Wk W v W^v Wv,是通过 training data 找出来的。

1.4 Multi-head Self-attention

self-attention 它还有一个进阶的版本叫做 Multi-head Self-attention,它在现在的使用非常广泛。在机器翻译、在语音辨识任务用比较多的 head 反而可以得到比较好的结果,至于需要多少的 head,这又是一个 hyperparameter 需要自己去调节。

那为什么需要多 head 呢?在 self-attention 中我们通过 q oldsymbol q q 去寻找相关的 k oldsymbol k k,但相关这件事情有很多种不同的形式,有很多种不同的定义。所以也许我们不能只有一个 q oldsymbol q q,我们应该要有多个 q oldsymbol q q,不同的 q oldsymbol q q 负责不同种类的相关性。

所以如果你要做 Multi-head Self-attention 的话,你先把 a oldsymbol a a 乘上一个矩阵得到 q oldsymbol q q,接下来你再把 q oldsymbol q q 乘上另外两个矩阵分别得到 q i , 1 oldsymbol q^{oldsymbol {i,1}} qi,1 q i , 2 oldsymbol q^{oldsymbol {i,2}} qi,2,其中 i oldsymbol i i 代表的是位置,1 和 2 代表的是这个位置的第几个 q oldsymbol q q

在这里插入图片描述

图1-23 2 heads self-attention(一)

图1-23 中代表说我们有两个 head,我们认为这个问题里面有两种不同的相关性,是我们需要产生两种不同的 head 来找两种不同的相关性,既然 q oldsymbol q q 有两个,那么对应的 k oldsymbol k k v oldsymbol v v 也需要有两个,所以对另外一个位置也做相同的事情,也会得到两个 q oldsymbol q q 两个 k oldsymbol k k 两个 v oldsymbol v v

在这里插入图片描述

图1-24 2 heads self-attention(二)

那怎么做 self-attention 呢?还是和我们之前讲的操作是一模一样的,只是 1 那一类的一起做,2 那一类的一起做,也就是说 q 1 oldsymbol q^{oldsymbol 1} q1 在计算 attention score 的时候就不需要管 k 2 oldsymbol k^{oldsymbol 2} k2 了,它就只管 k 1 oldsymbol k^{oldsymbol 1} k1 就好

在这里插入图片描述

图1-25 2 heads self-attention(三)

所以 q i , 1 oldsymbol q^{oldsymbol {i,1}} qi,1 就跟 k i , 1 oldsymbol k^{oldsymbol {i,1}} ki,1 算 attention, q i , 1 oldsymbol q^{oldsymbol {i,1}} qi,1 就跟 k j , 1 oldsymbol k^{oldsymbol {j,1}} kj,1 算 attention,得到 attention score,在计算 weighted sum 的时候也不要管 v 2 oldsymbol v^{oldsymbol 2} v2 了,看 v i , 1 oldsymbol v^{oldsymbol {i,1}} vi,1 v j , 1 oldsymbol v^{oldsymbol {j,1}} vj,1 就好,所以你把 attention 的分数乘以 v i , 1 oldsymbol v^{oldsymbol {i,1}} vi,1,把 attention 的分数乘以 v j , 1 oldsymbol v^{oldsymbol {j,1}} vj,1,接下来就得到了 b i , 1 oldsymbol b^{oldsymbol {i,1}} bi,1图1-25 所示

这边只用了其中一个 head,那也可以用另外一个 head 也做一模一样的事情去计算 b i , 2 oldsymbol b^{oldsymbol {i,2}} bi,2图1-26 所示

在这里插入图片描述

图1-26 2 heads self-attention(四)

如果你有 8 个 head,有 16 个 head 也是同样的操作,这里是以两个 head 作为例子来演示。

接下来你可能会把 b i , 1 oldsymbol b^{oldsymbol {i,1}} bi,1 b i , 2 oldsymbol b^{oldsymbol {i,2}} bi,2 拼接起来,然后再通过一个 transform 得到 b i oldsymbol b^{oldsymbol i} bi,然后送到下一层去。

在这里插入图片描述

图1-27 2 heads self-attention(五)

这个就是 Multi-head attention,self-attention 的一个变形

1.5 Positional Encoding

那讲到目前为止,你会发现说 self-attention 的这个 layer 少了一个也许很重要的信息,这个信息就是位置的信息,对于一个 self-attention 而言,每一个 input 它是出现在 sequence 的最前面还是最后面,它是完全没有这个信息的,对不对。

对于 self-attention 而言,1 和 4 的距离并没有非常远,2 和 3 的距离也没有说非常近,所有的位置之间的距离都是一样的,没有任何一个位置距离比较远,也没有任何位置距离比较近。

但是这样子的设计可能存在一些问题,因为有时候位置的信息也许很重要,举例来说,我们在做这个 POS tagging 词性标记的时候,也许你知道说动词比较不容易出现在句首,所以我们知道说某一个词汇它是放在句首,那它是动词的可能性就比较低,会不会这样子的位置的信息往往也是有用的呢?

到目前为止我们讲到的 self-attention 的操作里面,它根本就没有位置的信息,所以你在做 self-attention 的时候,如果你觉得位置信息是一个重要的事情,那你可以把位置的信息把它塞进去。

怎么把位置的信息塞进去呢?这边就要用到一个叫做 positional encoding 的技术。你需要为每一个位置设定一个 vector 叫做 positional vector,这边用 e i oldsymbol e^{oldsymbol i} ei 来表示,上标 i oldsymbol i i 代表位置,每一个不同的位置就有不同的 vector,比如 e 1 oldsymbol e^{oldsymbol 1} e1 是一个 vector, e 2 oldsymbol e^{oldsymbol 2} e2 是一个 vector, e 128 oldsymbol e^{oldsymbol {128}} e128 也是一个 vector,不同的位置都有一个专属的 e oldsymbol e e,然后把这个 e oldsymbol e e 加到 a i oldsymbol a^{oldsymbol i} ai 上就结束了。

在这里插入图片描述

图1-28 positional encoding

上述操作就等于告诉 self-attention 位置的信息,如果它看到说 a i oldsymbol a^{oldsymbol i} ai 有被加上 e i oldsymbol e^{oldsymbol i} ei 它就知道说现在出现的位置应该是在 i oldsymbol i i 这个位置,那这个 e i oldsymbol e^{oldsymbol i} ei 是什么样子呢?最早的这个 transformer 也就是 Attention is all you need 那篇 paper 里面,它用的 e i oldsymbol e^{oldsymbol i} ei图1-29 所示

在这里插入图片描述

图1-29 ei

它的每一个 column 就代表一个 e oldsymbol e e,第一个位置就是 e 1 oldsymbol e^{oldsymbol 1} e1 第二个位置就是 e 2 oldsymbol e^{oldsymbol 2} e2 以此类推,每一个位置都有一个专属的 e oldsymbol e e,希望透过给每一个位置不同的 e oldsymbol e e,你的 model 在处理这个 input 的时候,它可以知道现在的 input 它的位置的信息是什么样子

这样子的 positional vector 它是 hand-crafted 也就是人为设定的,那人设的 vector 就存在很多问题呀,就假设我现在在定这个 vector 的时候只定到 128,那我现在 sequence 的长度如果是 129 怎么办呢?不过在 Attention is all you need 那篇 paper 里面是没有这个问题的,它这个 vector 是透过某一种规则所产生的,透过一个很神奇的 sin cos 的 function 所产生的。其实你也不一定非要这么产生,这个 positional encoding 仍然是一个尚待研究的问题,你可以创造新的方法,甚至说是可以 learned from data

1.6 Many application

那这个 self-attention 当然是用得很广,比如 transformer 这个东西,比如在 NLP 领域有一个东西叫做 BERT,BERT 里面也有用到 self-attention,所以 self-attention 在 NLP 上的应用是大家都耳熟能详的

但 self-attention 不只是可以用在 NLP 相关的应用上,它还可以用在很多其它的问题上,比如语音辨识、图像任务,例如 Truncated Self-attentionSelf-Attention GANDEtection Transformer(DETR)

那好,接下来我们来对比下 Self-attention 和 CNN 之间的差异或者关联性

如果我们用 self-attention 来处理一张图片,代表说假设你要处理一个 pixel,那它产生 query,其它 pixel 产生 key,你在做 inner product 的时候,你考虑得不是一个小的区域,而是整张图片的信息。

在这里插入图片描述

图1-30 self attention处理图片

但是在做 CNN 的时候我们会画出一个 receptive field,每一个 filter 只考虑 receptive field 范围里面的信息,所以我们比较 CNN 和 self attention 的话,我们可以说 CNN 可以看作是一种简化版的 self attention,因为在做 CNN 的时候,我们只考虑 receptive field 里面的信息,而在做 self attention 的时候,我们是考虑整张图片的信息。所以说 CNN 是一个简化版的 self attention

或者你可以反过来说,self-attention 是一个复杂化的 CNN,在 CNN 里面,我们要划定 receptive field,每一个 filter 只考虑 receptive field 里面的信息,而 receptive field 的范围和大小是人决定的。而对 self-attention 而言,我们用 attention 去找出相关的 pixel,就好像是 receptive field 是自动被学出来的,network 自己决定说 receptive field 的形状长什么样子,network 自己决定说以某个 pixel 为中心,哪些 pixel 是我们真正需要考虑的,哪些 pixel 是相关的,所以 receptive field 的范围不再是人工划定,而是让机器自己学出来。

更多细节:On the Relationship between Self-Attention and Convolutional Layers

在上面这篇 paper 里面会用数学的方式严谨的告诉你说其实 CNN 就是 self-attention 的特例,self-attention 只要设定合适的参数,它就可以做到跟 CNN 一模一样的事情,所以 self-attention 是更 flexible 的 CNN,而 CNN 是有受限制的 self-attention,self-attention 只要透过某些设计、某些限制它就会变成 CNN

既然 CNN 是 self-attention 的一个 subset,self-attention 比较 flexible,比较 flexible 的 model 当然需要更多的 data,如果你的 data 不够,就有可能 overfitting,而小的 model,比较有限制的 model,它适合在 data 小的情形,它可能比较不会 overfitting

接下来我们再来对比下 Self-attention 和 RNN

RNN 和 self-attention 一样都是要处理 input 是一个 sequence 的状况,其 output 都是一个 vector,而且 output 的一排 vector 都会给到 Fully-Connected Network 做进一步的处理

在这里插入图片描述

图1-31 self-attention v.s. RNN(一)

那 self-attention 和 RNN 有什么不同呢?当然一个非常显而易见的不同就是说 self-attention 考虑了整个 sequence 的 vector,而 RNN 只考虑了左边已经输入的 vector,它没有考虑右边的 vector,但是 RNN 也可以是双向的,如果是双向的 RNN 的话其实也是可以看作考虑了整个 sequence 的 vector

在这里插入图片描述

图1-32 self-attention v.s. RNN(二)

但是我们假设把 RNN 的 output 和 self-attention 的 output 拿来做对比的话,就算你用双向的 RNN 还是有一些差别的,如 图1-32 所示,对于 RNN 来说假设最右边的 vector 要考虑最左边的这个输入,那它必须要将最左边的输入存到 memory 里面,然后接下来都不能够忘掉,一路带到最右边才能够在最后一个时间点被考虑,但对 self-attention 来说没有这个问题,它只要最左边输出一个 query 最右边输出一个 key,只要它们匹配起来就可以轻易的提取信息,这是 RNN 和 self-attention 一个不一样的地方。

在这里插入图片描述

图1-32 self-attention v.s. RNN(三)

还有另外一个更主要的不同是 RNN 在处理的时候,你 input 一排 sequence 然后 output 一排 sequence 的时候,RNN 是没有办法平行化的,你要先产生前面一个向量,才能产生后面一个向量,它没有办法一次处理,没有平行一次处理所有的 output。但 self-attention 有一个优势,是它可以平行处理所有的输出,你 input 一排 vector 再 output vector 的时候是平行产生的,并不需要等谁先运算完才把其它运算出来,每一个 vector 都是同时产生出来的,所以在运算速度方面 self-attention 会比 RNN 更有效率。

现在很多的应用都在把 RNN 的架构逐渐改成 self-attention 的架构了

更多细节:Transformers are RNNs: Fast Autoregressive Transformers with Linear Attention

self-attention 拥有非常多的变形,self-attention 的运算量非常大,怎么减少 self-attention 的运算量是一个未来的重点。self-attention 最早是用到 Transformer 上面,所有在讲 Transformer 的时候,其实它指的就是这个 self-attention,广义的 Transformer 就是指 self-attention,所以后来各种各样 self-attention 的变形都叫做是 xxxformer,如 Linformer、Performer、Reformer 等等,那到底什么样的 self-attention 又快又好,这仍然是一个尚待解决的问题

更多细节:Long Range Arena: A Benchmark for Efficient Transformers Efficient Transformers: A Survey

2. Transformer

聊完 Self-attention 之后,接下来终于可以聊聊 Transformer 了

以下内容均来自于李宏毅老师的 Transformer 的视频讲解

视频链接:【机器学习2021】Transformer

2.1 前置知识

Transformer 是什么呢?Transformer 就是一个 Sequence-to-sequence(Seq2seq) 的 model,那 Seq2seq 的 model 又是什么呢?

我们之前在讲解 self-attention 的时候,如果你的 input 是一个 sequence,对应的 output 存在几种情况,一种是 input 和 output 的长度一样,一种是直接 output 一个东西,还有一种情况就是 Seq2seq model 需要解决的,我们不知道 output 多长,由模型自己决定 output 的长度

那有什么样的应用是我们需要用到这种 Seq2seq model,也就是 input 是一个 sequence,output 也是一个 sequence,但是我们不知道 output 的长度,应该由模型自己决定 output 的长度,如 图2-1 所示

在这里插入图片描述

图2-1 Seq2seq model应用

一个很好的应用就是语音辨识,其输入是声音讯号,输出是语音所对应的文字,当然我们没有办法根据输入语音的长度推出 output 的长度,那怎么办呢?由模型自己决定,听一段语音,自己决定它应该要输出几个文字;还有一个应用就是机器翻译,让模型读一种语言的句子,输出另外一种语言的句子;甚至还有更复杂的应用,比如说语音翻译,给定一段语音 machine learning,它输出的不是英文,它直接把它听到的语音信号翻译成中文

在文字上你也可以用 Seq2seq model,举例来说你可以用 Seq2seq model 来训练一个聊天机器人,需要收集到大量的聊天训练数据,各式各样的 NLP 的问题都可以看作是 Question Answering(QA) 问题,而 QA 的问题就可以用 Seq2seq model 来解。必须要强调的是,对多数 NLP 的任务或对多数的语音相关的任务而言,往往为这些任务定制化模型,你会得到更好的结果

Seq2seq model 是一个很 powerful 的 model,它是一个很有用的 model,我们现在就是来学怎么做 seq2seq 这件事情,一般的 Seq2seq model 会分成两个部分,一部分是 Encoder 另外一部分是 Decoder,你的 input sequence 由 Encoder 处理然后将处理好的结果丢给 Decoder,由 Decoder 决定它要输出什么样的 sequence,等下我们会细讲 Encoder 和 Decoder 的内部架构

在这里插入图片描述

图2-2 Seq2seq model组成

2.2 Encoder

接下来我们就来讲 Encoder 部分,那 Seq2seq model Encoder 要做的事情就是给一排向量输出另外一排向量,很多模型都可以做到,比如 self-attention、RNN、CNN,那在 Transformer 里面的 Encoder 用的就是 self-attention

在这里插入图片描述

图2-3 Seq2seq model的Encoder

我们用一张简单的图来说明 Encoder 如 图2-4,现在的 Encoder 里面会分成很多很多的 block,每个 block 都是输入一排向量输出一排向量,每一个 block 并不是 neural network 一层,而是好几个 layer 在做的事情。在 Transformer 的 Encoder 里面每个 block 做的事情如 图2-4 所示

在这里插入图片描述

图2-4 简化版Transformer的Encoder

input 一个 sequence 之后,经过一个 self-attention 考虑整个 sequence 的信息,output 另外一排 vector,接下来会再丢到 Fully-Connected 的 feed forward network 里面,再 output 另外一排 vector,而这排 vector 就是 block 的输出。

在原来的 Transformer 里面它做的事情是更复杂的,如 图2-5 所示,在 Transformer 里面加入了一个设计,我们将 input vector 经过 self-attention 后不只是输出这个 vector,我们还要把这个 vector 加上它的 input 得到新的 output。这样子的 network 架构叫做 residual connection,那么得到 residual 的结构之后呢,再做一件事情叫做 normalization,这边用的不是 batch normalization 而是 layer normalization

在这里插入图片描述

图2-5 原始版Transformer的Encoder

layer normalization 比 batch normalization 更加简单,它不用考虑 batch 的信息,输入一个向量,输出一个向量,首先它会对同一个 feature 同一个样本中不同的 dimension 去计算 mean 和 std,然后做一个 norm 就行

得到 normlization 的输出以后输入 FC network,在 FC network 这边同样也有 residual 的结构,最后将 residual 的结果再经过一次 layer normalization 后才是 Transformer 里面 Encoder 的输出

Transformer paper 中的 Encoder 如 图2-6 所示,整个结构就是我们刚刚讲解的部分,在 input 的地方有加上 Positional Encoding 获取位置的信息,然后有一个 Multi-Head Attention,这个就是 self-attention 的 block,Add & Norm 就是 Residual 加上 Layer norm,这个复杂的 block 在 BERT 中有使用到,BERT 就是 Transformer Encoder

在这里插入图片描述

图2-6 Transformer paper的Encoder

学到这里,你可能有许多困惑,那为什么 Encoder 要这样设计呢?不这样设计行不行呢?

!!!不一定要这样设计,这个 Encoder network 架构的设计方式是按照原始论文来讲的,但原始论文的设计不代表它是最好的

To Learn more…

2.3 AT Decoder

Decoder 有两种分别是 Autoregressive Decoder 和 Non-Autoregressive Decoder

Autoregresive Decoder 是怎么运作的呢?我们拿语音辨识任务为例讲解,语音辨识的流程如 图2-7 所示,语音辨识就是输入一段声音输出一段文字,输入的声音信号经过 Encoder 之后输出一排 vector,然后送入到 Decoder 中产生语音辨识的结果。

在这里插入图片描述

图2-7 语音辨识流程(一)

那 Decoder 怎么产生这个语音辨识的结果呢?那首先你要给它一个特殊的符号,这个特殊的符号代表开始,Decoder 吃到 START 之后呢会吐出一个向量,这个 vector 的长度和 Vocabulary Size 一样长,向量中的每一个 row 即每一个中文字都会对应到一个数值,经过 softmax 之后这个向量的数值就对应一个分布,其总和为 1,那么分数最高的那个中文字就是最终的输出。

接下来你把 Decoder 第一次的输出 当做是 Decoder 新的 input,除了 START 特殊符号外还有 作为输入,根据这两个输入 Decoder 就会得到一个输出 ,接下来继续把 当做是 Decoder 新的输入,Decoder 根据三个输入输出得到 ,依此类推最终得到语音辨识的结果 机器学习,如 图2-8 所示

在这里插入图片描述

图2-8 语音辨识流程(二)

那这边有一个关键的地方用红色的虚线把它标出来,也就是说 Decoder 看到的输入是它在前一个时间点自己的输出,Decoder 会把自己的输出当做接下来的输入,所以当我们的 Decoder 在产生一个句子的时候,它其实有可能看到错误的东西,比如它把 辨识错成天气的 ,那接下来 Decoder 看到错误的辨识结果,它还是要想办法根据错误的辨识结果产生期待是正确的输出

在这里插入图片描述

图2-9 Decoder错误辨识

让 Decoder 产生错误的输出,然后再被 Decoder 自己吃进去会不会造成问题呢?会不会造成 Error Propagation 的问题呢?这是有可能的,所以我们需要在 training model 的时候给 Decoder 输入一些错误的东西,这在 training 部分的时候会讲到

那我们接下来看下 Decoder 内部的结构,如 图2-10 所示

在这里插入图片描述

图2-10 Decoder内部结构

我们对比下 Encoder 和 Decoder,如果我们将中间部分遮挡起来,Encoder 和 Decoder 其实也没有太大的区别,这边有个稍微不一样的地方,在 Decoder 这边 Multi-Head Attention 这个 block 上面还加了一个 Maksed

在这里插入图片描述

图2-11 Encoder v.s. Decoder

原本的 self-attention 中 input 一排 vector 然后 output 另外一排 vector,每一个输出的 vector 都要看过完整的 input 以后才做决定。所以输出 b 1 oldsymbol b^{oldsymbol 1} b1 的时候其实是根据 a 1 oldsymbol a^{oldsymbol 1} a1 a 4 oldsymbol a^{oldsymbol 4} a4 所有的信息。

当我们将 self-attention 转成 Masked self-attention 以后,它的不同点在哪里呢?它的不同点是现在我们不能再看右边的部分,也就是产生 b 1 oldsymbol b^{oldsymbol 1} b1 的时候我们只能考虑 a 1 oldsymbol a^{oldsymbol 1} a1 的信息,你不能够再考虑 a 2 oldsymbol a^{oldsymbol 2} a2 a 3 oldsymbol a^{oldsymbol 3} a3 a 4 oldsymbol a^{oldsymbol 4} a4 同理产生 b 2 oldsymbol b^{oldsymbol 2} b2 的时候我们只能考虑 a 1 oldsymbol a^{oldsymbol 1} a1 a 2 oldsymbol a^{oldsymbol 2} a2 的信息,你不能够再考虑 a 3 oldsymbol a^{oldsymbol 3} a3 a 4 oldsymbol a^{oldsymbol 4} a4 依此类推,这个就是 Masked self-attention,如 图2-12 所示

在这里插入图片描述

图2-12 Self-attention v.s. Masked Self-attention

讲得更具体一点,你做的事情是这样,当我们要产生 b 2 oldsymbol b^{oldsymbol 2} b2 的时候,我们只拿第二个位置的 Query 去和第一个位置的 Key 和第二个位置的 Key 去计算 Attention,第三个位置跟第四个位置就不管它,不去计算 Attention

在这里插入图片描述

图2-13 Masked Self-attention实例

那为什么需要加 Masked 呢?这件事情其实非常的直觉,回顾下 Decoder 的运作方式是一个一个的输出,它的输出是一个一个产生的,所以说是先有 a 1 oldsymbol a^{oldsymbol 1} a1 再有 a 2 oldsymbol a^{oldsymbol 2} a2 再有 a 3 oldsymbol a^{oldsymbol 3} a3 再有 a 4 oldsymbol a^{oldsymbol 4} a4,这跟原来的 self-attention 不一样,原来的 self-attention 的 a 1 oldsymbol a^{oldsymbol 1} a1 a 4 oldsymbol a^{oldsymbol 4} a4 是一整个输进你的 model 里面的,我们在讲 Encoder 的时候,Encoder 是一次性把 a 1 oldsymbol a^{oldsymbol 1} a1 a 4 oldsymbol a^{oldsymbol 4} a4 读进去,但是对 Decoder 而言先有 a 1 oldsymbol a^{oldsymbol 1} a1 才有 a 2 oldsymbol a^{oldsymbol 2} a2 才有 a 3 oldsymbol a^{oldsymbol 3} a3 才有 a 4 oldsymbol a^{oldsymbol 4} a4,所以实际上当你有 a 2 oldsymbol a^{oldsymbol 2} a2 要计算 b 2 oldsymbol b^{oldsymbol 2} b2 的时候你是没有 a 3 oldsymbol a^{oldsymbol 3} a3 a 4 oldsymbol a^{oldsymbol 4} a4 的,所以你根本就没有办法把 a 3 oldsymbol a^{oldsymbol 3} a3 a 4 oldsymbol a^{oldsymbol 4} a4 考虑进来,所以在原始 Transformer 的 paper 中强调说 Decoder 的 Self-attention 是一个带有 Masked 的 Self-Attention

好,到此为止我们讲了 Decoder 的运作方式,但是这边还有一个非常关键的问题,那就是 Decoder 必须自己决定输出的 Sequence 的长度,可是到底输出的 Sequence 的长度是多少呢?我们并不知道

但是我们期待模型可以自己学习到,今天给它一个 Input Sequence 的时候 ouput sequence 应该要多长,但在我们目前的这整个 Decoder 的运作机制里面模型并不知道它什么时候应该停下来,那怎么让模型停下来呢?

我们要准备一个特殊的符号 结束,这样 Decoder 它就可以输出 结束 这个符号,如 图2-14 所示

在这里插入图片描述

图2-14 Decoder添加End

我们期待说当 Decoder 产生完 以后,再把 当作 Decoder 的输入以后,Decoder 就要能够输出 结束图2-15 所示,那整个 Decoder 产生 Sequence 的过程就结束了,如 图2-15 所示

在这里插入图片描述

图2-15 Decoder添加End(二)

以上就是 Autoregressive(AT) 的 Decoder 它运作的方式

2.4 NAT Decoder

接下来我们简短的说一下 Non-Autoregressive(NAT) Model 的 Decoder 运作过程,NAT Decoder 不像 AT Decoder 一次产生一个字,它是一次把整个句子都产生出来,那怎么一次性把整个句子都产生出来呢?NAT 的 Decoder 它可能吃的就是一整排的 START 的 Token,让它一次产生一排 Token 就结束了,它只要一个步骤就可以完成一个句子的生成

在这里插入图片描述

图2-16 AT v.s. NAT

那这边你可能会问一个问题,刚才不是说不知道输出的 Sequence 长度是多少吗,那我们这边怎么知道 START 要放多少个当作 NAT Decoder 的输入呢?你可以有几个做法,第一个就是你 train 一个 Classifier,它吃 Encoder 的 input 输出是一个数字,代表 Decoder 要输出的长度,这是一种可能的做法。

另一种可能的做法就是不管三七二十一,你就给它一堆 START 的 Token,然后你再看什么地方输出的特殊符号 结束,输出 END 右边的就当做它没有输出,就结束了

NAT Decoder 的好处当然有平行化,速度快,且比较能够控制输出的长度,比如语音合成任务,那你在做语音合成的时候假设你突然想让你的系统讲快一点,那你可以把 Classifier 的 ouput 除以二,限制 NAT Decoder 的输出长度。语音合成任务是可以用 Seq2seq model 来做,最知名的是一个叫做 Tacotron 的模型,它是 AT 的 Decoder,还有另外一个模型叫做 FastSpeech,它是 NAT 的 Decoder

NAT Decoder 目前是一个热门的研究主题,虽然它表面上看起来有种种的厉害之处,尤其是平行化,但是 NAT Decoder 的性能往往都不如 AT Decoder,为什么性能不好呢?其实有一个叫做 Multi-Modality 的问题,这里就不细讲了

2.5 Cross attention

接下来我们要讲 Encoder 和 Decoder 如何进行交流的,也就是我们之前遮住的部分,它叫做 Cross attention 是连接 Encoder 和 Decoder 之间的桥梁,如 图2-17 所示

在这里插入图片描述

图2-17 Transformer中的Cross attention

那这部分你会发现它有两个输入来自于 Encoder 的输出,那这个模组实际上是怎么运作的呢?那接下来根据 图2-18 说明一下

在这里插入图片描述

图2-18 Cross attention运作

首先 Encoder 输入一排向量输出一排向量,我们把它叫做 a 1 oldsymbol a^{oldsymbol 1} a1 a 2 oldsymbol a^{oldsymbol 2} a2 a 3 oldsymbol a^{oldsymbol 3} a3,而 Decoder 会吃 START 这个 special token 经过 self-attention 得到一个向量,接下来把这个向量做一个 Transform 也就是乘上一个矩阵得到一个 Query 叫做 q oldsymbol q q,然后 a 1 oldsymbol a^{oldsymbol 1} a1 a 2 oldsymbol a^{oldsymbol 2} a2 a 3 oldsymbol a^{oldsymbol 3} a3 都产生 key,得到 k 1 oldsymbol k^{oldsymbol 1} k1 k 2 oldsymbol k^{oldsymbol 2} k2 k 3 oldsymbol k^{oldsymbol 3} k3,那把 q oldsymbol q q k oldsymbol k k 去计算 Attention 的分数得到 α 1 ′ alpha'_1 α1 α 2 ′ alpha'_2 α2 α 3 ′ alpha'_3 α3,当然你也可能会做 softmax,把它稍微做一下 normalization,接下来再把 α 1 ′ alpha'_1 α1 α 2 ′ alpha'_2 α2 α 3 ′ alpha'_3 α3 乘上 v 1 oldsymbol v^{oldsymbol 1} v1 v 2 oldsymbol v^{oldsymbol 2} v2 v 3 oldsymbol v^{oldsymbol 3} v3 再把它 weighted sum 加起来得到 v oldsymbol v v,这个 v oldsymbol v v 接下来会丢到 Fully-Connected Network 做接下来的处理,那这个步骤 q oldsymbol q q 来自于 Decoder, k oldsymbol k k v oldsymbol v v 来自于 Encoder,这个步骤就叫做 Cross Attention,所以 Decoder 就是凭借着产生一个 q oldsymbol q q 去 Encoder 这边抽取信息出来当做接下来的输入,这个就是 Cross Attention 的运作过程

2.6 Training

我们已经讲了 Encoder,讲了 Decoder,讲了 Encoder 和 Decoder 怎么互动的,接下来我们简单聊聊训练的部分

现在假如我们要做一个语音辨识任务,那么首先你要有大量的训练数据,然后 train 一个 Seq2seq model 使得其最终的输出要和真实标签越接近越好,两个分布差异性越小越好,具体来说是计算你 model predict 的值和你的 Ground truth 之间的 cross entropy,然后 minimize cross entropy,当然这件事情和分类任务很像

那这边有一个事情值得我们注意,在 training 的时候 Decoder 的输入是什么?Decoder 的输入是 Ground Truth 是正确答案!!!,在训练的时候我们会给 Decoder 看正确答案,那这件事情叫做 Teacher Forcing:using the ground truth as input,那在 inference 的时候 Decoder 没有正确答案看,它有可能会看到错误的东西,那这之间有一个 Mismatch

Decoder 训练的时候看到的全部是正确答案,但在测试的时候可能会看到错误的东西,这个不一致的现象叫做 Exposure Bias,这会导致说 Decoder 看到错误的东西后继续产生错误,因为它在 train 的时候看到的都是正确答案呀,所以说会导致在 inference 的时候一步错,步步错,那么怎么解决这个问题呢?有一个可以思考的方向就是给 Decoder 的输入加一些错误的东西,没错,就这么直觉,那这招就叫做 Scheduled Sampling

那接下来我们聊聊训练过程中的一些小 Tips。首先是 Copy Mechanism 复制机制,那这个可能是 Decoder 所需要的,比如我们在做 chat-bot 聊天机器人的时候,复制对话是一个需要的技术,需要的能力,比如你对机器说 你好,我是周童鞋 那机器可能会回复你说 周童鞋你好,很高兴认识你,对机器来说它并不需要从头创造 周童鞋 这一段文字,它要学的也是是从使用者人的输入去 Copy 一些词汇当做是它的输出;或者是在做摘要的时候,你可能更需要 Copy 这样子的技能,所谓的摘要就是你要 train 一个 model,去读一篇文章然后产生这篇文章的摘要,对摘要这个任务而言,其实从文章里面复制一些信息出来可能是一个很关键的能力

其它的还有 Guided Attention、Beam Search 这里就不一一细说了

好,那以上我们就讲完了 Transformer 和种种的训练技巧

总结

博主之前一直对 NLP 相关的内容不感冒,对于 Transformer 也早有听闻,不过始终没有找到一个适合博主的讲解,这次乘着要学习 BEVFormer 补了下 Transformer 的相关知识,通过听了李宏毅老师非常通俗的讲解后,对 Transformer 有了一个整体的了解。

简单来说,Transformer 是一个 Seq2seq model,它由 Encoder、Decoder 以及桥梁 Cross attention 三部分组成,其中 Encoder 用到的就是 Self-attention,而 Decoder 和 Encoder 非常相像,不过使用的是带有 Masked 的 Multi-Head Attention,桥梁 Cross attention 借助 Decoder 产生的 q oldsymbol q q 通过 Encoder 的 k oldsymbol k k v oldsymbol v v 抽取信息当做下一步的输入

简单了解了 Transformer 对后续学习 BEVFormer 有一个基础,同时对 NLP ASR 相关的任务也产生了一定的兴趣,非常感谢李宏毅老师!!!

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。