2019-02-22 Transformer (GPT、BERT的核心)

前几天细读GPT的paper,里面使用的基础模型和BERT一样都是Transformer,区别就在于GPT用的是单向Transformer,而BERT使用的是双向Transformer。之前对Transformer认识也比较敷衍,这几天就专门看了相关的paper、文章和代码,重新认识一下Transformer。

首先,Transformer来自论文Attention Is All You Need,后面笔记很多参考文章The Illustrated Transformer,同时加了一些自己的理解。

1. 从上到下认识Transformer

首先我们把Transformer看做一个黑盒,以机器翻译示例为例,Transformer是输入就是待翻译的句子,输出就是翻译后的句子。


然后我们再一步一步打开这个潘多拉魔盒:


看到没有,这是一个经典的Encoder-Decoder模型,只是Encoder部分不是一个单独的Encoder,而是6个Encoder的堆栈,Decoder部分也是一样,至于为什么是6个,可能是实验效果最好。把Encoders、Decoders部分打开,就是下面这个样子:

在Encoders部分中每个encoder的结构都是一样的,只是不共享weights。每个encoder打开后,如下图结构:


每个Encoder包括一个Self-Attention层和feed-farward NN层。Encoder的输入先进入Self-Attention层(暂时先不关心Self-Attention细节,后面会介绍),Self-Attention层的输出作为feed-farward NN层的输入。

对于feed-farward NN层,是由多个feed-farward network组成的,每word对应一个,而且是互相独立的。

针对每个Decoder如下图,也是有Self-Attention层和feed-farward NN层组成,只是在两个中间加入了一个Encoder-Decoder Attention层,我的理解是对每个Encoder给予不同的注意力,用于表现在输入句子中应该更看着哪一部分。

2. 深入细节

现在开始深入模型的细节,从tensor级别来看看,这些输入向量在模型内部是如何流动和变型,到输出,来认识如何训练一个语言模型。

和一般NLP任务一样,一个句子中每个word用embedding word的形式表示,即每个word是一个向量。

如果embedding word的长度是512,那么每个word就是1*512的向量,下图简化表示每个词:

那么对于最底层的encoder输入就是一个向量的list,其中每个向量的长度是512,至于list的长度作为模型的一个超参数,一般情况去训练数据中最长句子的word个数,假设最长的句子有N个词,那么这个list就是N*512的向量。而对于其他encoder的输入就是它前面一层encoder的输出。


这里提到了Transformer一个重要的特性:并行化,原因就在于list经过self-attention层输出后也是一个向量的list,而且每个向量进入各自的feed-forward layer,而且每个feed-forward 都是独立,所以可以并行运算。

下面就以一个简单的示例具体看看在encoder里每个子层究竟做了什么。

-Self-Attention

如果我们要翻译这句话“The animal didn't cross the street because it was too tired”。句子中的it是指的是animal还是street呢,Self-Attention就是为了把animal和it联系起来,也就是说Self-Attention是Transformer去了解句子中词之间的关系。

这是第五层encoder中显示出来的句子中每个词对it的关联度,从图中可以看出注意力机制赋予更多的关注在"The animal"上。

究竟Self-Attention是如何做到这一点的呢,下面一步一步来看计算细节。

第一步——参数:每个encoder的输入就是每个词的word embedding,然后要根据这个输入对每个词创建3个向量,分别是:Query vector, Key vector, Value vector。那么这个三个向量是怎么产生的呢,这三个向量分别是通过输入得word embedding向量乘以三个矩阵产生的,而这三个矩阵就是我们要训练的。

q1 = X1 * WQ, k1= X1*WK, v1 = X1* WV

Query vector, Key vector, Value vector的长度要小于word embedding,word embedding和每个encoder的输入/输出向量长度是512,而Query vector, Key vector, Value vector是64。其实他们不是一定要求要小,只是为了运算更方便。那么这三个向量是怎么帮助计算词之间的注意力的呢,我们继续往下看。

第二步——计算得分:以计算例子中第一个词“Thinking”的self-attention得分为例,我们需要计算输入句子中每个个词对“Thinking”的self-attention得分,这个分数表示了当我们在解析句子特定位置的词时,输入句中其他词对这个词的关注程度。

如果我们要计算第一个位置词的self-attention得分,先计算q1*k1,再计算q1*k2。

第三步,把self-attention得分除以key vector长度的开方,在论文中key vector的长度是64,所以这个除以8。为什么要这么做,论文给的解释是可以得到更稳定的梯度,我的理解是给K的长度一定的惩罚项。

第四步,做一个softmax操作进行归一化,这个归一化的值保证了所有的self-attention得分都为正,而且<=1。

在这里,开始这几个概念开始把我弄得比较晕,现在开始梳理清楚了,首先是词和位置。Query vector表征的是位置向量,Key vector表征的是词向量,根据softmax score的计算可以表征的是词对当前位置的关注程度。根据这个定义,当然通常这个位置上词有最高的softmax score,但同时对表示其他词和当前词的关联程度的表示也是非常有用。

第五步,针对每个词对位置#1的softmax score乘以词#1的value vector得到权重。同时乘以一个很小的数(比如0.001),这样保留需要关注的词,同时丢弃那些不相关的词。

第六步,把每个词针对位置#1的权重相加,就得到位置#1self-attention层的输出值。

上面的计算向量值被送到feed-forward neural层计算。在实际计算中,为了加快计算速度,这些计算是以矩阵的形式进行的。所以下面我们来以矩阵的视角看看是如何计算的。

Self-Attention的矩阵运算

第一步,计算Query、Key、Value矩阵。我们的输入X:word embedding矩阵,然后分别乘以我们要训练的三个权重矩阵WQ、WK、WV。

每个X矩阵对应输入的句子,每一行对应句子一个词。在论文中X的列数是512,图中简化为4,q/k/v的的列数是64,图中以3表示。

然后对前面针对self-attention向量计算,压缩成矩阵运算就是:

“multi-headed” attention

上面计算看似OK了?不,论文作者还加入了“multi-headed”机制,我们先来看什么是multi-headed,再看它带来的性能提升。

简单来说,前文讲到的attention属于一个head,但还不够,我们还要多加几个head。如下图所示,有W0Q、W0K、W0V计算出Q0、K0、W0,这算1个head,同时还有W1Q、W1K、W1V计算出Q1、K1、W1,这算第2个head。

按照上图所示,论文中用了8个不同的矩阵(即8个不同的WQ、WK、WV),即8个head,得到了8个不同的Z矩阵。

好了,这儿又带来一个问题,对于下一步的feed-forward层的输入只期望是一个矩阵,而不是8个,那么如何是的8个矩阵变成1个呢?论文中的方法是将8个矩阵按行链接成一个,然后乘以一个额外的权重矩阵WO,得到最终的输出矩阵Z。

至于为什么multi-head能提升性能,我个人理解就是类似学习器的组合,通过不同的随机初始化矩阵训练,捕获不同的特征,从不同的侧面表征词之间的关联,以组合的形式得到更强大的学习器。下面用一张图来表示前面描述的过程:

下面再来看看multi-head的效果,回顾一下之间的示例,不同位置的词对“it”的关注程度:

通过multi-head不仅捕获了animal和it的强关联,还捕获到了tired和it的强关联。

Positional Encoding

到目前为止,该模型还没有描述词之间的顺序关系,也就是如果将一个句子打乱其中的位置,也应该获得相同的注意力,为了解决这个问题,论文加入了自定义位置编码,位置编码为word embedding长度相同的特征向量,然后和word embedding进行求和操作。

论文中给出的编码公式:

pos is the position and i is the dimension

具体代码的实现参考get_timing_signal_1d()。关于这部分的理解还不是很清楚,后面理清了再补充。

The Residuals

在继续之前,关于self-attention层还有一个细节需要提到就是residuals,如果熟悉CNN,对ResNet了解的,一定对residuals不陌生,residuals的关键点就是skip connection。在Transformer里,在每一个encoder的子层(也就是self-attention,FFNN )有一个residual connection, 输入和输出有一个add和归一化操作。

以向量的视觉来看就是:

同样,在decoder的子层里也有这样的操作,如果我们把Transformer看做2层的encoders和decoders,将是下面这样:

Decoder

下面重点来看Decoder这方是如何工作的。

最顶层的encoder转化成了注意力向量集合K、V。这作为decoder的输入,下面的gif以机器翻译为例,展示了decoder如何工作。

以把目标句子翻译成英语为例

最后的linear+softmax层

decoder栈最后输出的是一个浮点数的向量,如何把它转化为word,这就是最后linear和softmax层的作用。

假设目前词典的大小是10000个,那么linear层就是decoder栈的输出到10000节点的全连接,每个节点就是表示一个词,最后跟上softmax层,表示到目标词的概率到大小,选择概率最大的词作为输出。

training and loss function

和RNN一样,以机器翻译为例,training的y值就是翻译后句子的one-hot编码,loss function一般采用cross-entropy或者Kullback-Leibler divergence。

假设目标词典大小为6(一般情况下,词典大小是目标所有可能出现的词个数),上图展示了每个词的one-hot编码


显示了训练后取每个词的概率值

一般有,先取位置1概率最大的值,然后在位置1取值的基础上取位置2的概率最大值,依次往后推。为了捕获更准确或者说更广泛的取值,可以采取beam-search。beam-search中有个参数B,假设B取3,表示在位置1取概率排前3的词,然后在这三个词的基础上选取位置2概率最高的三个值,往后依次类推。

好了,到此为止,我们对transformer有了一个全面的了解,更多细节参考:

1. 论文Attention Is All You Need

2. 代码实现http://nlp.seas.harvard.edu/2018/04/03/attention.html

参考

https://jalammar.github.io/illustrated-transformer/

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,393评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,790评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,391评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,703评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,613评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,003评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,507评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,158评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,300评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,256评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,274评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,984评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,569评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,662评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,899评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,268评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,840评论 2 339

推荐阅读更多精彩内容