AutoCV番外:Transformer

news2025/1/21 9:42:41

目录

  • Transformer
    • 前言
    • 1. Self-attention
      • 1.1 前置知识
      • 1.2 Self-attention机制
      • 1.3 矩阵乘法角度理解
      • 1.4 Multi-head Self-attention
      • 1.5 Positional Encoding
      • 1.6 Many application
    • 2. Transformer
      • 2.1 前置知识
      • 2.2 Encoder
      • 2.3 AT Decoder
      • 2.4 NAT Decoder
      • 2.5 Cross attention
      • 2.6 Training
    • 总结

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 \boldsymbol a a 来表示而不是用 x \boldsymbol x x 来表示,代表说它有可能前面已经做过一些处理,input 一排 a \boldsymbol a a 向量之后,self-attention 需要 output 另外一排 b \boldsymbol b b 向量,每个 b \boldsymbol b b 都是考虑了所有的 a \boldsymbol a a 生成出来的

在这里插入图片描述

图1-8 self-attention内部实现

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

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

那么每一个向量跟 a 1 \boldsymbol a^{\boldsymbol 1} a1 的关联程度我们用一个数值 α \alpha α 来表示,接下来的问题就是 self-attention 这个 module 怎么自动决定两个向量之间的关联性呢?比如你给它两个向量 a 1 \boldsymbol a^{\boldsymbol 1} a1 a 4 \boldsymbol a^{\boldsymbol 4} a4,它怎么决定 a 1 \boldsymbol a^{\boldsymbol 1} a1 a 4 \boldsymbol a^{\boldsymbol 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 \boldsymbol q q k \boldsymbol k k 这两个向量
  • 再把 q \boldsymbol q q k \boldsymbol k kdot product,就是把它们做 element-wise 相乘再相加得到 α \alpha α

Additive

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

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

在这里插入图片描述

图1-10 Attention的计算方法

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

你把 a 1 \boldsymbol a^{\boldsymbol 1} a1 乘上 W q W^q Wq 得到 q 1 \boldsymbol q^{\boldsymbol 1} q1,这个 q \boldsymbol q q 有个名字叫做 Query,也就是搜寻查询的意思,然后接下来对于 a 2 \boldsymbol a^{\boldsymbol 2} a2 a 3 \boldsymbol a^{\boldsymbol 3} a3 a 4 \boldsymbol a^{\boldsymbol 4} a4 你都要去把它乘上 W k W^k Wk 得到 k \boldsymbol k k 这个 vector,这个 k \boldsymbol k k 有个名字叫做 Key,也就是关键字的意思。那你把这个 Query q 1 \boldsymbol q^{\boldsymbol 1} q1 和这个 Key k 2 \boldsymbol k^{\boldsymbol 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 \boldsymbol q^{\boldsymbol 1} q1 也会和自己计算关联性,所以你也要把 a 1 \boldsymbol a^{\boldsymbol 1} a1 乘上 W k W^k Wk 得到 k 1 \boldsymbol k^{\boldsymbol 1} k1,然后计算它的关联性 α 1 , 1 \alpha_{1,1} α1,1

在这里插入图片描述

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

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

在这里插入图片描述

图1-13 attention score计算经过softmax

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

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

在这里插入图片描述

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

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

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

在这里插入图片描述

图1-15 b1的计算

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

1.3 矩阵乘法角度理解

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

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

在这里插入图片描述

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

所以我们从 a 1 \boldsymbol a^{\boldsymbol 1} a1 a 4 \boldsymbol a^{\boldsymbol 4} a4 得到 q 1 \boldsymbol q^{\boldsymbol 1} q1 q 4 \boldsymbol q^{\boldsymbol 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 \boldsymbol q^{\boldsymbol 1} q1 q 4 \boldsymbol q^{\boldsymbol 4} q4

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

在这里插入图片描述

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

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

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

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

在这里插入图片描述

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

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

在这里插入图片描述

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

那么这些 attention scores 是怎么计算得来的?你可以看作是两个矩阵 K K K Q Q Q 的相乘,一个矩阵的 row 就是 k 1 \boldsymbol k^{\boldsymbol 1} k1 k 4 \boldsymbol k^{\boldsymbol 4} k4,另外一个矩阵的 column 就是 q 1 \boldsymbol q^{\boldsymbol 1} q1 q 4 \boldsymbol q^{\boldsymbol 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 \boldsymbol b b,那么 b \boldsymbol b b 是怎么被计算出来的呢?你就把 v 1 \boldsymbol v^{\boldsymbol 1} v1 v 4 \boldsymbol v^{\boldsymbol 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 \boldsymbol b^{\boldsymbol 1} b1 b 4 \boldsymbol b^{\boldsymbol 4} b4

所以说 self-attention 的整个操作是先产生了 q \boldsymbol q q k \boldsymbol k k v \boldsymbol v v,然后再根据 q \boldsymbol q q 去找出相关的位置,然后再对 v \boldsymbol 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 \boldsymbol q q 去寻找相关的 k \boldsymbol k k,但相关这件事情有很多种不同的形式,有很多种不同的定义。所以也许我们不能只有一个 q \boldsymbol q q,我们应该要有多个 q \boldsymbol q q,不同的 q \boldsymbol q q 负责不同种类的相关性。

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

在这里插入图片描述

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

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

在这里插入图片描述

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

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

在这里插入图片描述

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

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

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

在这里插入图片描述

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

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

接下来你可能会把 b i , 1 \boldsymbol b^{\boldsymbol {i,1}} bi,1 b i , 2 \boldsymbol b^{\boldsymbol {i,2}} bi,2 拼接起来,然后再通过一个 transform 得到 b i \boldsymbol b^{\boldsymbol 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 \boldsymbol e^{\boldsymbol i} ei 来表示,上标 i \boldsymbol i i 代表位置,每一个不同的位置就有不同的 vector,比如 e 1 \boldsymbol e^{\boldsymbol 1} e1 是一个 vector, e 2 \boldsymbol e^{\boldsymbol 2} e2 是一个 vector, e 128 \boldsymbol e^{\boldsymbol {128}} e128 也是一个 vector,不同的位置都有一个专属的 e \boldsymbol e e,然后把这个 e \boldsymbol e e 加到 a i \boldsymbol a^{\boldsymbol i} ai 上就结束了。

在这里插入图片描述

图1-28 positional encoding

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

在这里插入图片描述

图1-29 ei

它的每一个 column 就代表一个 e \boldsymbol e e,第一个位置就是 e 1 \boldsymbol e^{\boldsymbol 1} e1 第二个位置就是 e 2 \boldsymbol e^{\boldsymbol 2} e2 以此类推,每一个位置都有一个专属的 e \boldsymbol e e,希望透过给每一个位置不同的 e \boldsymbol 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…

  • On Layer Normalization in the Transformer Architecture
  • PowerNorm: Rethinking Batch Normalization in Transformers

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 \boldsymbol b^{\boldsymbol 1} b1 的时候其实是根据 a 1 \boldsymbol a^{\boldsymbol 1} a1 a 4 \boldsymbol a^{\boldsymbol 4} a4 所有的信息。

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

在这里插入图片描述

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

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

在这里插入图片描述

图2-13 Masked Self-attention实例

那为什么需要加 Masked 呢?这件事情其实非常的直觉,回顾下 Decoder 的运作方式是一个一个的输出,它的输出是一个一个产生的,所以说是先有 a 1 \boldsymbol a^{\boldsymbol 1} a1 再有 a 2 \boldsymbol a^{\boldsymbol 2} a2 再有 a 3 \boldsymbol a^{\boldsymbol 3} a3 再有 a 4 \boldsymbol a^{\boldsymbol 4} a4,这跟原来的 self-attention 不一样,原来的 self-attention 的 a 1 \boldsymbol a^{\boldsymbol 1} a1 a 4 \boldsymbol a^{\boldsymbol 4} a4 是一整个输进你的 model 里面的,我们在讲 Encoder 的时候,Encoder 是一次性把 a 1 \boldsymbol a^{\boldsymbol 1} a1 a 4 \boldsymbol a^{\boldsymbol 4} a4 读进去,但是对 Decoder 而言先有 a 1 \boldsymbol a^{\boldsymbol 1} a1 才有 a 2 \boldsymbol a^{\boldsymbol 2} a2 才有 a 3 \boldsymbol a^{\boldsymbol 3} a3 才有 a 4 \boldsymbol a^{\boldsymbol 4} a4,所以实际上当你有 a 2 \boldsymbol a^{\boldsymbol 2} a2 要计算 b 2 \boldsymbol b^{\boldsymbol 2} b2 的时候你是没有 a 3 \boldsymbol a^{\boldsymbol 3} a3 a 4 \boldsymbol a^{\boldsymbol 4} a4 的,所以你根本就没有办法把 a 3 \boldsymbol a^{\boldsymbol 3} a3 a 4 \boldsymbol a^{\boldsymbol 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 \boldsymbol a^{\boldsymbol 1} a1 a 2 \boldsymbol a^{\boldsymbol 2} a2 a 3 \boldsymbol a^{\boldsymbol 3} a3,而 Decoder 会吃 START 这个 special token 经过 self-attention 得到一个向量,接下来把这个向量做一个 Transform 也就是乘上一个矩阵得到一个 Query 叫做 q \boldsymbol q q,然后 a 1 \boldsymbol a^{\boldsymbol 1} a1 a 2 \boldsymbol a^{\boldsymbol 2} a2 a 3 \boldsymbol a^{\boldsymbol 3} a3 都产生 key,得到 k 1 \boldsymbol k^{\boldsymbol 1} k1 k 2 \boldsymbol k^{\boldsymbol 2} k2 k 3 \boldsymbol k^{\boldsymbol 3} k3,那把 q \boldsymbol q q k \boldsymbol 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 \boldsymbol v^{\boldsymbol 1} v1 v 2 \boldsymbol v^{\boldsymbol 2} v2 v 3 \boldsymbol v^{\boldsymbol 3} v3 再把它 weighted sum 加起来得到 v \boldsymbol v v,这个 v \boldsymbol v v 接下来会丢到 Fully-Connected Network 做接下来的处理,那这个步骤 q \boldsymbol q q 来自于 Decoder, k \boldsymbol k k v \boldsymbol v v 来自于 Encoder,这个步骤就叫做 Cross Attention,所以 Decoder 就是凭借着产生一个 q \boldsymbol 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 \boldsymbol q q 通过 Encoder 的 k \boldsymbol k k v \boldsymbol v v 抽取信息当做下一步的输入

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何区分比特率、波特率和频谱带宽?

01、什么是比特率和波特率? 宽带网络里面提及的千兆即1000Mbit/s,一般描述的是我们家网络端口每秒最大可接收0、1比特(bit)的数量,即每秒可接收1000x106个比特。显而易见,比特率越高,每秒传送的…

利用resnet50模型实现车牌识别(Python代码,.ipynb和.py两种文件保存都有,可以使用jupyter或pycharm运行)

1.代码的主要流程如下: 导入所需的库和模块。对数据集进行可视化,随机选择一些图像进行展示。加载图像数据集,并将图像和标签存储在数组中。对标签进行独热编码。划分训练集和测试集。使用图像数据增强技术增加训练数据的多样性。定义一些评…

让ChatGPT成为全科医生的智能助理

医生问诊 医疗健康是所有人都关心的话题。涉及医疗健康领域的信息化事件,无论是搜索引擎推荐和广告信息,还是互联网挂号,或者电子商务在线买药,经常能引发社会性讨论。有了 ChatGPT,我们自然也会期待在医疗健康领域&a…

从零开始学习JVM(一)--初识Java虚拟机

1 虚拟机与Java虚拟机 1.1 基本介绍 所谓虚拟机(Virtual Machine)。就是一台虚拟的计算机。它是一款软件,用来执行一系列虚拟计算机指令。大体上,虚拟机可以分为系统虚拟机和程序虚拟机。 系统虚拟机:完全对物理计算…

(赠书活动第1期) Java 8 已无法满足需求?升级到 Java 17 让你体验酣畅淋漓的编程!

Java 8 已无法满足需求?升级到 Java 17 让你体验酣畅淋漓的编程! Java 17 的新特性如何升级到 Java 17❤️‍🔥 本期赠书三本《JAVA核心技术 卷2》 Java 8 是一个历史悠久的版本,自推出以来一直被广泛使用。但是随着时间的推移和技…

四举措实现数电票对企业经营的改善

数电票不仅是征管需求,也是企业业务的需求。 2021年3月,中共中央办公厅、国务院办公厅印发的《关于进一步深化税收征管改革的意见》(以下简称《意见》)提出,要全面推进税收征管数字化升级和智能化改造,把智…

Spark大数据处理讲课笔记4.2 Spark SQL数据源 - 基本操作

文章目录 零、本讲学习目标一、基本操作二、默认数据源(一)默认数据源Parquet(二)案例演示读取Parquet文件1、在Spark Shell中演示2、通过Scala程序演示 三、手动指定数据源(一)format()与option()方法概述…

解密Netty中的Reactor模式

文章目录 单线程Reactor模式多线程Reactor模式Reactor模式中IO事件的处理流程Netty中的通道ChannelNetty中的反应器ReactorNetty中的处理器HandlerNetty中的通道Channel和处理器Handler的协作组件Pipeline Reactor(反应器)模式是高性能网络编程在设计和架构方面的基础模式.Doug…

【MySQL速通篇004】这可能最详细的关于MySQL基础知识点的文章了

🍁前言 👑作者主页:CSDN丨博客园 🏆学习交流:在下周周ovoの社区 💎这篇8000多字的博客也是花了我比较久的时间,基本覆盖很大一部分的MySQL知识点,可以说是非常的详细,感谢…

【我的创作纪念日】IC人仍在路上,不停歇……

机缘 平台今天提示我已经坚持创作3年了。如果不提醒的话,我自己都没什么感觉。三年时间说长也不长,说短呢,其实也不短了。截止今天我在CSDN累计发文213篇,上传资源117个。涉及领域包含:数字信号处理、FPGA设计、IC设计…

【自制视频课程】C++OpnecV基础35讲——序言

OpenCV简介 OpenCV是一个开源的计算机视觉库,它可以用于图像处理、计算机视觉、机器学习等领域。OpenCV最初是由英特尔公司开发的,后来成为了开源项目,现在由OpenCV开源社区维护。OpenCV提供了丰富的图像处理和计算机视觉算法,包括…

【YOLO】Windows 下 YOLOv8 使用 TensorRT 进行模型加速部署

本文全文参考文章为 win10下 yolov8 tensorrt模型加速部署【实战】 本文使用的代码仓库为 TensorRT-Alpha 注:其他 Yolov8 TensorRT 部署项目:YOLOv8 Tensorrt Python/C部署教程 一、前期准备工作 安装Visual Studio 2019或者Visual Studio 2022、Nvidi…

Shell脚本文本三剑客之awk编辑器(人类从不掩饰探索星空的愿望)

文章目录 一、awk简介二、awk工作原理三、awk命令格式四、awk命令的使用1.print操作按行输出文本2.print操作按字段截取输出文本3.使用BEGIN和END指定操作5.使用操作getline6.使用操作OFS7.配合数组使用 一、awk简介 awk是linux的一个强大的命令,具备强大的文本格式…

puppeteer-不需重构,无痛加强vue单页面应用的SEO,提升百度收录排名

背景 最近产品觉得我们网站在百度收录上排名太靠后了,又不肯花钱,就让我们想办法提升网站的SEO。由于项目是用vue3写的,并且已经迭代多个版本了,用nuxt实在不适宜,当然俺的开发水平也不够,周期也会拉得很长…

字典翻译EasyTrans简单使用分享

前言 最近太忙了,一直按在项目上摩擦,都没有时间写分享了。今天终于市把所有负责的模块都写完了,本次迭代引入了字典翻译,借这个机会顺便分享下。 一、什么是字典翻译 所谓的字典翻译其实简单理解就是一些不常更新的有键值对属性的…

什么是 Java 的内存模型?如何保证安全

Java 的内存模型定义了多线程程序中,不同线程之间如何共享和访问共享变量的规则。Java 内存模型的设计旨在保证线程安全和可见性,同时保证程序的性能。本文将介绍 Java 内存模型的基本概念、线程安全的实现方法以及如何使用 synchronized 和 volatile 关…

yolo 训练

这里写目录标题 分配训练集&Validation数量数据集读取读取全部文件夹替换路径 loss weightNMSBBox_IOUEIou Optimizer 分配训练集&Validation数量 validation_size training_size * validation_ratio / (1 - validation_ratio)training_size 219 validation_ratio …

基于Java+SpringMVC+vue+element实现前后端分离校园失物招领系统详细设计

基于JavaSpringMVCvueelement实现前后端分离校园失物招领系统详细设计 博主介绍:5年java开发经验,专注Java开发、定制、远程、指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 Java项目精品实战案例《500套》 欢迎点赞 收藏 ⭐留言 文末获…

单轴丝杠平台实现搬运功能

1. 功能说明 本文示例将实现R279样机单轴丝杠平台搬运的功能。 该机构是由一个丝杠模组和一个 舵机关节模组 组合而成,关节模组上安装了一个电磁铁。 注意限位开关【①触碰传感器、②近红外传感器】的安装位置: 2. 丝杠传动机构原理 丝杠传动机构是一个将…

基于海思Hi3531 ARM+K7 FPGA高性能综合视频图像处理平台

板卡概述 XM703是自主研制的一款基于PCIE总线架构的高性能综合视频图像处理平台,该平台采用Xilinx的高性能Kintex UltraScale系列FPGA加上华为海思的高性能视频处理器来实现。 华为海思的HI3531DV200是一款集成了ARM A53四核处理器性能强大的神经网络引擎&#xff…