Transformer是谷歌在2017年的论文 Attention Is All You Need 中提出的一种模型,可以很好地处理序列相关的问题,如机器翻译。在此之前,对于机器翻译问题一般使用CNN或RNN作为encoder-decoder的模型基础,如使用RNN的Seq2Seq模型。
本文将通过对Seq2Seq模型、Attention模型的简单介绍,引入并重点介绍Transformer模型,加深自己对各个模型的理解。
Seq2Seq模型,Sequence-to-Sequence,即序列到序列的过程。
典型的Seq2Seq模型如下,包含编码器Encoder和解码器Decoder两个部分。
Encoder是一个RNN/LSTM模型,将输入的句子编码得到context vector,即
(1) C = F ( x 1 , x 2 , . . . , x m ) C=F(x_1,x_2,...,x_m)\tag{1} C=F(x1,x2,...,xm)(1)
Decoder是Encoder的逆过程,每个状态由之前的状态和context vector决定,即
(2) y i = G ( C , y 1 , y 2 , . . . , y i − 1 ) y_i=G(C,y_1,y_2,...,y_{i-1})\tag{2} yi=G(C,y1,y2,...,yi−1)(2)
在这种模型下,所有输入被压缩在一个向量中,导致——
2015年提出的Attention模型,使用多个context vector,有效地解决了使用Seq2Seq模型难以处理长句子的问题。
注意力机制(Attention Mechanism)源于对人类视觉的研究。在认知科学中,由于信息处理的瓶颈,人类会选择性地关注所有信息的一部分,同时忽略其他可见的信息。上述机制通常被称为注意力机制。
在机器翻译中,注意力机制衡量输出单词与每个输入单词的关联程度,关联程度更大的输入单词具有更大的权重,使得输出单词可以更关注其对应的语义。比如,当翻译 I eat an apple
时,输出 吃
时应该重点关注 eat
这个单词,即eat
的权重应该比其他单词更高。
最先的Attention模型[5]架构如下:
输入:待翻译的句子
Encoder:双向的RNN或LSTM,计算得到每个位置的隐状态,下面只用 h i h_i hi 表示
Decoder:对当前输出位置 t t t,使用上一个隐状态 s t − 1 s_{t-1} st−1 与Encoder的结果计算,如下:
(3) e i j = a ( s i − 1 , h j ) e_{ij}=a(s_{i-1},h_j)\tag{3} eij=a(si−1,hj)(3)
(4) α i j = e x p ( e i j ) ∑ k e x p ( e i k ) \alpha_{ij}=\frac{exp(e_{ij})}{\sum_k exp(e_{ik})}\tag{4} αij=∑kexp(eik)exp(eij)(4)
(5) c i = ∑ j = 1 T α i j h j c_i=\sum_{j=1}^{T}\alpha_{ij}h_j\tag{5} ci=j=1∑Tαijhj(5)
(6) s t = f ( s t − 1 , y t − 1 , c t ) s_t = f(s_{t-1},y_{t-1},c_t)\tag{6} st=f(st−1,yt−1,ct)(6)
(7) y t = g ( y t − 1 , s t , c t ) y_t=g(y_{t-1},s_t,c_t)\tag{7} yt=g(yt−1,st,ct)(7)
通过为每个输出位置计算一个context vector,使得每个位置的输出可以关注到输入中最相关的部分,效果比传统模型更好。
Attention模型提出后,出现了许多Attention模型的变体,包括——
另外,上述模型计算 c t c_t ct 时使用的是前一个状态 s t − 1 s_{t-1} st−1,也有一些模型中直接使用当前状态 s t s_{t} st,如下[4]:
计算过程为:
(8) s t = f ( s t − 1 , y t − 1 ) s_t=f(s_{t-1},y_{t-1})\tag{8} st=f(st−1,yt−1)(8)
(9) α t j = a ( s t , h j ) ∑ k a ( s t , h k ) \alpha_{tj}=\frac{a(s_t,h_j)}{\sum_k a(s_t,h_k)}\tag{9} αtj=∑ka(st,hk)a(st,hj)(9)
(10) c t = ∑ j = 1 T α t j h j c_t=\sum_{j=1}^T \alpha_{tj}h_j\tag{10} ct=j=1∑Tαtjhj(10)
(11) y t = g ( y t − 1 , s t , c t ) y_t=g(y_{t-1},s_t,c_t)\tag{11} yt=g(yt−1,st,ct)(11)
RNN:其结构使得其天然适合处理NLP领域的问题,但最大的瓶颈是难以并行化,尽管有一些并行化思路,但仍然只能并行很小一部分。
CNN:卷积核抽取类似n-gram的特征,但难以处理长距离依赖问题,且pooling层会丢失位置信息。通过将CNN层数加深可以提高其处理长距离依赖问题的能力,同时去除pooling层保留位置信息,使得CNN可以更适合处理NLP问题。在并行能力上,CNN各个卷积核之间没有依赖,非常适合并行,因此速度比RNN快得多。
摘录来自[6]中的关于RNN、CNN、Transformer的对比。(此处的RNN和CNN指在RNN和CNN基础上增加Attention机制等改进版)
- 语义特征提取能力:RNN与CNN能力相近,而Transformer要超过两者4-8个百分点
- 长距离特征捕获能力:RNN与Transformer能力相近,CNN则弱得多(尽管已经加深了层数)
- 任务综合特征抽取能力:Transformer 显著强于 RNN 和 CNN,CNN略强于RNN
- 并行计算能力及运行效率:Transformer 和 CNN 差不多,都远远远远强于 RNN
从上面的对比可以看出,Transformer在效果和速度上都具有很好的表现。
Transformer模型架构如下[1]:
Encoders由N个Encoder组成,Decoders由N个Decoder组成,图示为 N = 6 N=6 N=6 。每个Encoder和Decoder内部简化结构如下:
在了解其内部具体流程之前,先了解下论文中提出的一些概念。
Attention的目的是要算出一个context vector,原始的Attention模型使用①输出当前位置的隐状态与②输入所有位置的隐状态计算匹配程度,并根据匹配程度对③输入所有位置的隐状态进行加权求和得到context vector。
在Self-Attention中,输入输出都是句子本身,对原始Attention做一个转化——
在NLP的领域中,Key, Value通常就是指向同一个文字隐向量[7],即key=value。
有了上述理解,Self-Attention的过程也就跟原始的Attention模型基本相同,如下[2]:
Self-Attention对每个输入(句子)的embedding,计算得到3个向量,分别为query Q Q Q,key K K K,value V V V
对第 i i i 个单词,使用query与所有单词的key点乘计算匹配得分,并除以上述向量维度的平方根 d k \sqrt{d_k} dk(也就是论文中提出的scaled dot-Product attention
),使得点积结果不会过大,训练过程梯度更稳定
(12) s c o r e ( i , j ) = Q i K j d score(i,j)=\frac{Q_iK_j}{\sqrt{d}}\tag{12} score(i,j)=dQiKj(12)
对分数进行softmax得到权重,并对value加权求和得到当前单词的向量映射
(13) α i j = e x p ( s c o r e ( i , j ) ) ∑ k e x p ( s c o r e ( i , k ) ) \alpha_{ij}=\frac{exp(score(i,j))}{\sum_kexp(score(i,k))}\tag{13} αij=∑kexp(score(i,k))exp(score(i,j))(13)
(14) Z i = ∑ j α i j V j Z_i=\sum_j \alpha_{ij}V_j\tag{14} Zi=j∑αijVj(14)
实际应用时直接使用矩阵进行运算,即
(15) Z = s o f t m a x ( Q K T d ) V Z=softmax(\frac{QK^T}{\sqrt{d}})V\tag{15} Z=softmax(dQKT)V(15)
论文中使用Multi-headed机制进一步完善了Self-Attention层,具体地,对输入的 Q , K , V Q,K,V Q,K,V 进行多次不同的映射,相当于把句子投影到不同的子空间(representation subspaces) 中,提高其表达能力。其结构如下[2]:
其工作流程如下[1]:
上述Attention过程没有考虑到输入序列中单词的顺序,transformer为每个输入单词的词嵌入上添加了一个新向量——位置向量,即embedding_with_time_signal = positional_encoding + embedding
。位置向量遵循一定规则生成,此处不涉及。
此外,上述结构的每一层后都要增加一个layer-normalization步骤,如下:
综合上述的各个模块,一个完整的Transformer结构大致如下[1]:
了解上述各概念后,梳理一下Transformer的整个训练过程如下:
输入是句子的embedding表示,加上位置向量后输入到第一个Encoder里
Encoders包含N个结构相同的Encoder,每个Encoder包含一个Multi-headed Attention层和一个前馈层,包含以下几个步骤:
每层的输出和输入具有相同的shape
Decoders包含N个结构相同的Decoder,每个Decoder包含一个Multi-headed Attention层、一个Encoder-Decoder Attention层、一个前馈层,训练时是逐个词生成的,即一个句子Decoders要执行多次,包含以下几个步骤: