赞
踩
最近想学一下BERT,在这之前就先学了一下transformer。
transformer原本是用来做机器翻译的,大概的体系结构长这样:
这个框架主要用在机器翻译和机器问答领域,就是有两个组件Encoder和Decoder。对于给定的输入source (x1,x2,x3,…,xn), 首先编码器将其编码成一个中间表示向量z=(z1,z2,…,zn)。接着,解码器根据z和解码器自身前面的输出,来生成下一个单词。
每个编码模块可能由多个编码器组成,每个解码模块也可能有多个解码器组成。
每个Encoder的输入首先会通过一个self-attention层,再经过一个前馈神经网络。
而Decoder在经过self-attention层后还会经过一个编码器训练的attention层。
attention其实表示的就是词与词之间的关联,比如下面这句话:
The animal didn’t cross the street because it was too tired
这句话中的"it"指的是什么?它指的是“animal”还是“street”?对于人来说,这其实是一个很简单的问题,但是对于一个算法来说,处理这个问题其实并不容易。self attention的出现就是为了解决这个问题,通过self attention,我们能将“it”与“animal”联系起来。
self-attention首先从输入的词向量中创建一个Query向量,一个Key向量和一个Value向量,通过Query向量,和Key向量的运算我们可以计算得到一个词在句子中与其他词的关联程度。再用各个词与当前词的关联程度乘上各个词的value向量求和(即累加加权),得到的向量即self-attention层的输出:
由于有时候一个词可能与多个词有较大关联,所以我们采用了一种叫做“多头”的策略,比如我们产生多个q\k\v向量,使self-attention层产生多个输出向量。对于这多个输出向量,我们把他们拼起来再与一个矩阵相乘使其变换为一个向量的标准大小:
比如上面的句子,it的注意力会集中在animal和tired身上。
但以上也只做了词与词之间的关联,词序的问题还没有考虑。为此我们在每个词嵌入的时候为他添上一个位置向量,位置编码向量不需要训练,它有一个规则的产生方式。
除此之外我们还会用残差做一下层归一化,最终编码器与解码器的内部结构如下:
当序列输入时,Encoder开始工作,最后在其顶层的Encoder输出矢量组成的列表,然后我们将其转化为一组attention的集合(K,V)。(K,V)将带入每个Decoder的“encoder-decoder attention”层中去计算(这样有助于decoder捕获输入序列的位置信息)
我们以下图的步骤进行训练,直到输出一个特殊的符号<end of sentence>,表示已经完成了。每个时间片Decoder的输出会作为下一个时间片decoder的输入。对于Decoder,和Encoder一样,我们在每个Decoder的输入做词嵌入并添加上表示每个字位置的位置编码。
当decoder的time step为1时(也就是第一次接收输入),其输入为一个特殊的token,可能是目标序列开始的token(如<BOS>),也可能是源序列结尾的token(如<EOS>).encoder的序列处理是并行的,而decoder的序列处理是串行的。
Decoder最后的输出是一个浮点数向量列表,我们再通过最终的线性层和softmax层将其映射到一个词列表上,根据词列表每个单元的概率,选择最大概率单元对应的词作为输出。
可见,transformer整体上还是很类似RNN的,词与词之间的时序特性作用明显。
参考博文:https://blog.csdn.net/qq_41664845/article/details/84969266
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。