Transformer论文逐段精读【论文精读】笔记 - 哔哩哔哩 (bilibili.com)
Transformer论文逐段精读【论文精读】_哔哩哔哩_bilibili
1. 标题 + 作者(title & author)
8位作者都带了星号,贡献是一样的哦。
文章末尾有说明,每位作者的分工。
200页综述(来自评论区: https://arxiv.org/pdf/2108.07258.pdf )建议将Transformer作为基础模型。
2. 摘要(abstract)
在主流的序列转录模型一般是依赖复杂的RNN或者CNN,一般使用encoder和decoder的架构。【注:所谓序列转录模型就是说给定一个序列生成另外一个序列。比如机器翻译】。在性能最好的这些模型中,通常也会在endoer和decoder之间架设注意力机制。本文提出了一个新的简单的架构,transformer,仅仅依赖于注意力机制,没有使用RNN或者CNN。【之前一般都以novel的架构为佳,渐渐地变成simple为佳】做了机器翻译的实验,性能上表现非常,并行性更好,训练时间更短,更好的BLEU分数。transofrmer任务还可以泛化到其他领域上。
3. 结论(conclusion)
transformer,第一个仅仅使用注意力机制的序列转录模型。在encoder-decoder使用了多头注意力机制替换了RNN层。transformer架构,训练更快更强,此架构应该不止可以用在文本上,图片,视频都可以推广使用。
代码放在https://github.com/tensorflow/tensor2tensor
4. 导言(introduction)
[基本是摘要前半部分的扩充]
第一段:在时序模型中主流的是LSTM/RNN,当输出结构化信息比较多的时候,还会使用编码器-解码器架构。
第二段:
- RNN的特点(缺点)
在RNN中,给定一个序列,其计算方式是把序列从左往右移动,一步一步往前走,假设是个句子的话,就是一个一个词的看,对第t个词,RNN会计算一个输出,也称为隐藏状态,是有前面一个词的隐藏状态和当前第t个词本身决定的。即可将前面学到的历史信息,通过放到当下和当前的词做一些计算后输出。RNN就是通过这种机制有效处理时序信息,把之前的信息全部放在隐藏状态里,依次往后进行。但是RNN的问题也出现在这里,1.RNN是时序即一个一个地执行计算,难以并行,即计算的时候,必须保证前面的输入完成了。无法并行,计算性能比较差。2.历史信息是一步一步地往后传递,如果时序(步数)比较长,早期的历史信息会丢掉,如果不想丢掉,就需要比较大,但是比较大,每个步骤都存储,内存开销会很大。当然后续做了很多改进,但是并没有改变基本问题。
第三段:attention在RNN上的应用。主要是用在如何把编码器的东西很有效地传输给解码器。
最后一段:全新的使用注意力机制transformer,可以并行计算,更少的资源和时间即可训练。
5. 相关工作(background)
第一段:如何使用CNN替换RNN来减少时序的计算。CNN用在时序存在的问题:卷积神经网络无法对较长的序列进行建模。(这是因为CNN计算的时候,每一次看一个一个比较小的窗口,比如3×3的像素块,如果两个像素离得比较远,那么需要很多层卷积,一层一层上去才能够最后把这两个隔得远的像素给融合起来。),
如果使用transformer的注意力机制,每次可以看到所有的像素,所以一层就可以把整个序列全部看到,就没有这个问题。但是CNN还有个优点是,CNN可以做多个输出通道,一个输出通道去识别不一样的模式,transformer使用Multi_Head Attention来模拟这种多输出通道的效果
第后续段落:关键点:自注意力机制。自注意力机制并不是本文提出,但是transformer是第一个仅仅靠自注意力机制的encoder-decoder架构模型。
讲清楚相关的工作有哪些,区别与联系是什么。
6. 模型(Model Architecture)【chapter 3】
深度神经网络的论文最重要的一章。
第一段: 序列模型中现在比较好的是编码器-解码器架构。(接下来解释什么是encoder,decoder)编码器:将一个长为的的东西(假设是一个句子的话,有n个词,就表示第个词),编码器会将此序列表示为(输出)一个长度也是的,对应的是的一个向量表示(如果是个句子,那么就表示第个词的向量表示)。解码器:拿到编码器的输出,生成一个长为的序列,注意:和是可以不一样的,解码器和编码器不一样在于,在解码器中,词是一个一个生成的。编码器是一次性看到整个句子。但是解码的时候只能一个一个生成)这是一个自回归()的过程(输入又是输出)。在最开始给定的,生成第一个输出,在拿到后可以去生成,要生成,可以把之前所有的到全部拿到,即翻译时,一个一个词往外蹦。过去时刻的输出可以是是当前时刻的输入【那么RNN也是属于自回归的啦?】
好的论文要有优秀的图示结构。
左半边是编码器,右半边是解码器。“input embedding”是编码器输入,比如中文翻译英文时的中文句子embedding,“output”是解码器之前时刻的输出,作为此刻解码器的输入。“shifted right”一个一个往后往右移。
编码器:N个块堆叠,具体内部:multi-head attention,残差&LN,前馈神经网络,残差&LN。编码器的输出作为解码器的输入。
解码器:其中一部分和编码器结构相同,但是有一块是“Masked Multi-Head Attention”,N个这样的块堆叠后,进入输出层,softmax层输出结果。
6.1 编码器&解码器
- 编码器
由6个相同的layer组成。每个layer有两个sub-layer:①multi-head self-attention;②position wise fully feed-forward network。 每个sub-layer都用了残差链接,同时后面有LN,每个sub-layer的输出是。残差链接需要输入和输出是一样大小的,如果不一样,还需要做投影。为了简单起见,把每一个层的输出维度变成512,固定长度表示,使得模型比较简单。(这里和之前的CNN或MLP时是不一样的,那时经常把维度往下减,要么CNN的话是空间维度往下减且channel维度往上拉)
简单的网络使得调参实际上只有两个可调,和- LayerNorm(文章中如果用了别人的东西,最好花几句话讲一下是什么,免得还要打开链接去看到底是个啥)
- 通过LN和BN的对比来解释一下什么是LN,以及变长的应用中不适用BN,而采用LN。
RNN或transformer的输入是三维情况,是一个序列。
- 为什么RNN/transformer中使用LN?
①在持续的序列模型里面,每个样本的长度可能会发生变化,比如机器翻译,句子/单词可长可短,短的会在后面补零。BN是跨样本计算同一特征的均值和方差,如果样本的长度变化非常大,那么每次的mini-batch计算得到的均值方差的抖动可能会非常大;且预测时候是将全局的均值和方差记录下来,那么全局的均值方差如果遇到一个很长很长的样本,那么模型的表现很可能就不尽人意了。而LN来说,是每个样本自己的特征来计算均值和方差,也不需要存一个全局的均值方差,故不管样本长还是短,均值都是在样本自身里计算的,相对稳定一些。
②另一篇文章解释LN:从梯度归一化等角度解释LN的有效性,( LayerNorm是Transformer的最优解吗?_夕小瑶的卖萌屋-CSDN博客)
- 解码器
同样由个layer组成,每个layer同样有encoder的两个sub-layer,但是解码器还多了第三个sub-layer,这个sub-layer同样是多头注意力机制+ResNet+LN,但是区别在于是“Masked-Multi-Head attention”
(前文提到,解码器做的是自回归的过程,即当前时刻的输出的输入集是上面一些时刻的输出,意味着在做预测时候是不可以看到当前之后那些时刻的输出,但是注意力机制中每次是可以看到完整的输入的,为了避免这种情况发生,即保证解码器训练时,在预测第个时刻的输出的时候其不应该看到时刻以后的那些输入,
文章的做法是通过一个带掩码的注意力机制,保证了输入进来时,时间是不会看到时间以后的那些输入,从而保证训练和预测时候的行为是一致的。
(这里保证训练和预测行为一致是怎么得到的???)
6.2 注意力机制(attention)
第一段,attention的一般化介绍。注意力函数是将Query和Key-Value对映射成一个输出的函数。output是value的一个加权和,即输出的维度和value的维度是一样的。
value的权重是此value对应的key和查询query的相似度得来的。
6.2.1 Scaled Dot-Product Attention (3.2.1)
query和key是等长的,value的长度是。计算query和key做内积,(两个向量做内积,内积越大,余弦相似度越大,如果为0则二者垂直),内积再除以(向量的长度),再用softmax计算权重,得到n个非负的和为1的权重(假设一个query,有n个k-v对)。
实际计算中,query作为一个矩阵,与k矩阵相乘,除以后进入,最后乘以。
其他注意力机制:常见两种:加型注意力机制,另一种点积注意力机制。点积注意力机制和本文的区别就在于除以了,原因是:
当 不大时候,除不除没关系,但是当 比较大,也就是说两个向量(Q和K)的长度比较长的时候,做点积结果会比较大也可能比较小,当结果比较大的时候,之间的相对的差距就会变大,导致最大的那个值在 之后会更加靠近于1,剩下的值就会更加靠近0,即: 的结果会更加向两端靠拢,这样的情况下计算梯度,会发现梯度会比较小(因为: 最后的结果就是希望模型的预测值,置信的地方尽量靠近1,不置信的地方尽量靠近0,如此认为模型接近了收敛,此时梯度会变得比较小,模型的优化就会跑不动),而transformer中 比较大(512),故除以 比较合适。
上图中的 ,主要是避免在第 时间的时候看到以后时间的东西,具体讲:假设 和 是等长的 ,而且时间上是能对应起来的,对于第 时刻的 ,在计算时应该只看 到 ,不去看 及其之后的内容。给不该看的部分给予一个权重为极大的负数,这样进入 后,这些就会接近于0.
6.2.2 多头注意力(3.2.2 Multi-Head Attention)
与其我做一个单个的注意力函数,不如把整个,,投影到低维,投影次,然后做次的投影函数,每一个函数的输出把它并在一起,然后再投影来会得到最终输出。下图演示效果:
进入一个线性层(线性层就是投影的比较低的维度),再做一个Scaled Dot-Product Attention,做 次,将 个向量并在一起,最后做一次线性投影,得到结果。
为什么要做多头注意力机制呢
如果我们回过头来看dot-product的注意力的话,会发现里面没有什么可以学的参数,其具体函数就是内积,但有时候为了识别不一样的那些模式,我希望你可能有一些不一样的计算像素的办法,如果你用的是加性attention的话,那里面其实还是有一个权重的可以用来学习,也许是可以学到一些东西。但是对于点积attention,可以如此:先投影到低维,那么投影的是可以学的(即给模型次机会,希望其学到不一样的投影的方法,使得在投影进去的那个度量空间里面能够去匹配不同模式需要的一些相似函数,最后把这些东西回来,再做一次投影),跟之前说的在卷积神经网络里面有多个输出通道的情形有些像。具体公式:
实际使用中, ,投影的维度为 ,在此64维投影空间计算注意力函数,最后再投影回来。如何用矩阵实现上述公式中的很多小矩阵运算?
6.2.3 transformer中如何使用注意力机制(Application of Attention in our Model)
- ① 编码器中的注意力机制:
编码器的输入:假设句子长度是的话,那么其输入是个长为的向量(假设大小设置为1了)。注意力层有三个输入(Q,K,V),但是图中可以看到,是同一个输入复制了三份,就是说此处的是一个东西(故称为自注意力机制),输入了个,那么每个会拿到一个输出,则会有个输出,且输出和长度是一样的,维度都是,即输入和输出都是,计算过程见前文。 不考虑多头和投影的情况,输出其实就是输入的加权和,权重来自于本身跟各个向量的相似度。多头和投影情况下,会学到个不一样的距离空间出来。输出则和纯粹的单注意力机制会不一样。 - ② 解码器的第一个注意力机制(下方的注意力块)
输入也是一样,只是不是而是,主要计算过程和编码器一样,但是有一个操作,只看到以前不包括的数据,详见前文描述。 - ③ 解码器的第二个注意力机制。
首先输入的不同,和是来自于编码器的输出,是来自于解码器下方的输出。此时权重的计算为解码器输出作为的去和编码器的输出作为的去计算相似度作为权重,在和计算得到注意力分数,即此attention做的事情是:有效的把编码器里面输出根据相似度给拎出来。根据解码器的输入不一样,根据当前的向量去编码器的输出中挑出感兴趣(对应)的内容出来。
6.3 Position-wise Feed-Forward Networks
其实就是全连接神经网络层(MLP),但是不一样的是,()position是指输入序列中每个词,即MLP对每个词作用了一次,说白了就是MLP只是作用在最后一个维度。
注意力层的输出为512,那么公式中的就是一个512的向量,会把512投影成2048,即维度扩大四倍。因为最后有个残差链接,还得投影回去,故又把2048投影回512,说白就是个单隐层的MLP。如果用pytorch实现,两个线性层放在一起就可以了,不需要改任何参数,因为pytorch的输入是3D时,其计算默认就是在最后一个维度做计算。
attention起的作用:把整个序列里面的信息抓取出来,做一次汇聚aggregation,注意力的输出中已经有了序列中感兴趣的内容,信息已经抓取到,在做投影,MLP时,映射到我更想要的语义空间的时候,由于每个attention的输出已经包含序列信息,所以MLP对每个点独立做即可。
对比RNN:RNN的输入是向量,对于第一个点,其实就是做了一个线性层MLP,直接出去即可,下一个点,时序信息(绿色)上一时刻的输出和输入(蓝色)一起并入,如此完成了历史信息的传递。
二者虽有区别,但是关注点都是在于如何利用序列信息。
6.4 Embeddings and Softmax
embedding:输入是一个个的词,或者叫词源叫token,我需要把它映射成一个向量,embedding就是说给任何一个词,学一个一个长为的向量表示它。本文中就是512啦。
transformer的三个embedding:编码器输入,解码器输入,softmax前面的线性也需要embedding。
三个embedding权重一样,且把权重乘以了,因为在学embedding的时候,多多少少会把向量的L2 Norm学成相对比较小的,比如说1,即不管维度多大,最后的值都会等于1. 即维度一大,学到的权重值就会变小,但是之后加上的位置编码(position encoding),位置便编码并不会随着长度变长,是把long固定住的。所以权重乘以之后,使得位置编码和embedding相加的时候,二者具有差不多的scale,相当于做了一个hat。【这里没明白】
6.5 position encoding
attention并不具有时序信息,输出是value的加权和,权重是query和key的距离,和顺序(序列信息)是无关的,一句话打乱顺序前后的attention值是一样,这样的情况在处理时序信息是有问题的。
故而,transformer在输入中加入时序信息,即位置编码。
(RNN是上一时刻的输出作为下一个时刻的输入来传递历史信息)
思路:举例:计算机表示数值,32bit二进制,可以理解为长度为32的向量表示。而transformer中,一个词在嵌入层会表示成512的向量,同样再使用512维的向量表示词的位置,用周期不一样的sin/cos函数的值算出来的。二者相加,就完成了给attention添加时序信息。
位置编码是cos/sin函数,在+1和-1之间抖动,输入的embedding乘以 ,使得每个数字也差不多在+1和-1之间。
为什么使用自注意力机制(chapter 4)
三个维度:① 复杂度;②顺序的计算:下一步计算必须要等前面多少步计算完成,越不需要等,那么并行度就越高; ③ 信息从一个数据点到另外一个数据点要走多远,越短越好。
- 自注意力层:① n是序列的长度,d是向量的长度。self-attention的矩阵运算:query×key,q和k都是n×d维度。③矩阵计算,并行度很高,认为O(1)
③ 任何query和任何k-v对只要一次就可以 - RNN层:① 序列长为n,就一个一个做运算,每个里面计算时d×d的矩阵再乘以n的输入。 ② n个步骤都是一次依赖的 ③ 最初到最后,需要走过n步
- CNN层:①序列上的用的1d的卷积,k为kernel数,n是序列长度,d是输入/输出通道数。② 并行度非常高 ③ 每次一个长为k的窗口,k以内可以一次传递,超过k需要多层,一层一层地传递
- 自注意力层(受限)query只和最近的r个邻居进行计算,这样复杂度就降低了(① 提升)。但是举例比较长的点,就需要多走几步才能完成传递(③牺牲)
得与失使用了attention后,对长数据的处理更好,而且算的也不慢,但是实际上,由于attention对模型的假设做的更少,导致需要更多的数据和更大的模型才能训练出RNN/CNN同样的效果。
7. 实验(chapter 5)
英语-德语。WMT 2014的数据,使用byte-pair encoding:每个词有各种变化形式,如果每个形式都单独做成一个词,他们之间的区别模型就无法获知了,且会造成词典太大。bpe做的是把词的词根提出来,词典可以较小。并且英语和德语共享一个字典,好处:编码器和解码器可以使用同一种embedding,即编码器和解码器共享权重。
优化器使用adma,
学习率公式计算:
正则化:每一个子层的输出上,进入残差前和进入layernorm之前,加了dropout(0.1),输入:加上词嵌入和位置编码时,也加了dropout(0.1)
label smoothing,将softmax的输出为0.1时,即可认为是正确的。(置信度为0.1),这里会损失困惑度(perplexity)可理解为模型不确信度。
8. 评论
写作非常简洁,没有用什么写作技巧,基本就是提出了什么模型,模型长什么样子,跟RNN/CNN比,结论是什么。不推荐这样写,而是:可以选择把自己的东西减少一些,甚至把一些东西不那么重要的东西放到附录里面,建议正文最好讲个故事,为什么做这些事情,设计理念是什么样的,整个文章的思考是什么样子的,这样会让大家认为文章比较有深度一些。
transformer架构作为一种类似CNN的一种基础架构,应用非常广泛,有影响力。同样一个模型能在许多领域使用。transformer能够融合多模态的数据。
attention主要在模型起了一部分作用:把整个序列的信息给聚合起来,后面的MLP,残差是缺一不可的;attention根本没有对序列顺序建模但是效果却比CNN/RNN效果好,现在认为,attention使用了一个更广泛的归纳偏置,使得它能处理更一般化的信息。从而使得attention并没有做任何空间上的假设,他也能够跟CNN甚至比CNN取得更好的一些效果,但是代价是假设更一般,造成对数据的信息抓取能力变弱,所以transformer的模型都是非常大