bert为何是双向的transformer:
精品链接:()
add & norm:
https://www.jianshu.com/p/cd3e9a491426
WordtoVector
1 Transformer模型
Transformer由论文《Attention is All You Need》提出,现在是谷歌云TPU推荐的参考模型。
Transformer模型是2018年5月提出的,可以替代传统RNN和CNN的一种新的架构,用来实现机器翻译,论文名称是attention is all you need。无论是RNN还是CNN,在处理NLP任务时都有缺陷。CNN是其先天的卷积操作不很适合序列化的文本,RNN是其没有并行化,很容易超出内存限制(比如50tokens长度的句子就会占据很大的内存)。
下面左图是transformer模型一个结构,分成左边Nx框框的encoder和右边Nx框框的decoder,相较于RNN+attention常见的encoder-decoder之间的attention(上边的一个橙色框),还多出encoder和decoder内部的self-attention(下边的两个橙色框)。每个attention都有multi-head特征。最后,通过position encoding加入没考虑过的位置信息。
上图就是模型示意图,左侧是encode,编码部分,右边是decode解码部分
transformer由encode和decode两部分组成,因为我当前需求只是分类,所以只介绍encoder(编码部分),encoder包括:input embedding, 注意力层,残差模块,前馈神经网络。
下面对transformer从input embedding, 注意力层,前馈层进行介绍
ps: 因为我当前需求只是分类,所以只介绍上面提到的四个层,也就是:
1. input embedding
2.注意力层
3.残差模块
4. 前馈神经网络
5. 我们分类模型的应用
一、input embedding
- 首先我们把我们训练集,比如1000个句子中所有单词去重复编成一个字典,其中词频小于 n 统一替换成 ‘unknown’ , 既去除了干扰因素,也解决了矩阵稀疏性的问题,就是新的测试句子中有字典里没有的单词,可以赋予字典里 ‘unknown’ 的向量
- 那么如果字典里有200个单词,那么该单词的索引可以是1,2,3,… 200,也可以是****one-hot 形式
比如:[1 0 0 0 0 … 0 0 0 0 0 0] , [0 1 0 0 0 … 0 0 0 0 0 0] 。。。向量长度为200 - 如果我们输入的一句话有10个单词
和word2Vector一样,每个单词在我们字典中有一个索引或是向量 - 如果是向量的话就是乘以一个矩阵W,如果是索引(比如是1)的话就是在矩阵W中提取第1行的向量。这个矩阵的维度 V * E ,(V是字典单词数目, E是人为设定,默认是512),在我们的例子中,矩阵W的维度就是 200 *512。索引或是向量其实效果都是一样,只不过一个是乘以矩阵W,另一个是从W中提取指定行。(如下图)
- 当我们整个模型训练完了,我们的W也就训练完了,应用的时候新的句子进入模型,句子里的每个词语我们可以根据字典向量或是索引从W里面提取对应的词向量
- 为了考虑到每个单词在句子里面的顺序问题,对应每个单词我们会生成一个位置向量。你可以在 get_timing_signal_1d()中看到生成位置编码的代码。这不是唯一可能的位置编码方法。然而,它的优点是能够扩展到未知的序列长度(例如,当我们训练出的模型需要翻译远比训练集里的句子更长的句子时)。
- 你可以看到它从中间分裂成两半。这是因为左半部分的值由一个函数(使用正弦)生成,而右半部分由另一个函数(使用余弦)生成。然后将它们拼在一起而得到每一个位置编码向量。
- 我们会把词向量(1512的向量)+ 位置向量(1512的向量)
截止目前为止,embeding层彻底结束了。只有一个W的矩阵用来训练
二、注意力层
一个编码器的内部结构如下图,输入序列的每个单词都经过自编码过程。然后,他们各自通过前向传播神经网络——完全相同的网络,而每个向量都分别通过它:
从宏观视角看自注意力机制
不要被我用自注意力这个词弄迷糊了,好像每个人都应该熟悉这个概念。其实我之也没有见过这个概念,直到读到Attention is All You Need 这篇论文时才恍然大悟。让我们精炼一下它的工作原理。
例如,下列句子是我们想要翻译的输入句子:
The animal didn’t cross the street because it was too tired
这个“it”在这个句子是指什么呢?它指的是street还是这个animal呢?这对于人类来说是一个简单的问题,但是对于算法则不是。
当模型处理这个单词“it”的时候,自注意力机制会允许“it”与“animal”建立联系。
随着模型处理输入序列的每个单词,自注意力会关注整个输入序列的所有单词,帮助模型对本单词更好地进行编码。
如果你熟悉RNN(循环神经网络),回忆一下它是如何维持隐藏层的。RNN会将它已经处理过的前面的所有单词/向量的表示与它正在处理的当前单词/向量结合起来。而自注意力机制会将所有相关单词的理解融入到我们正在处理的单词中。
当我们在编码器#5(栈中最上层编码器)中编码“it”这个单词的时,注意力机制的部分会去关注“The Animal”,将它的表示的一部分编入“it”的编码中。
请务必检查Tensor2Tensor notebook ,在里面你可以下载一个Transformer模型,并用交互式可视化的方式来检验。
从微观视角看自注意力机制
首先我们了解一下如何使用向量来计算自注意力,然后来看它实怎样用矩阵来实现。
计算自注意力的第一步就是从每个编码器的输入向量(每个单词的词向量)中生成三个向量。也就是说对于每个单词,我们创造一个查询向量、一个键向量和一个值向量。这三个向量是通过词嵌入与三个权重矩阵后相乘创建的。
可以发现这些新向量在维度上比词嵌入向量更低。他们的维度是64,而词嵌入和编码器的输入/输出向量的维度是512. 但实际上不强求维度更小,这只是一种基于架构上的选择,它可以使多头注意力(multiheaded attention)的大部分计算保持不变。
X1与WQ权重矩阵相乘得到q1, 就是与这个单词相关的查询向量。最终使得输入序列的每个单词的创建一个查询
什么是查询向量、键向量和值向量向量?
它们都是有助于计算和理解注意力机制的抽象概念。请继续阅读下文的内容,你就会知道每个向量在计算注意力机制中到底扮演什么样的角色。
计算自注意力的第二步是计算得分。假设我们在为这个例子中的第一个词“Thinking”计算自注意力向量,我们需要拿输入句子中的每个单词对“Thinking”打分。这些分数决定了在编码单词“Thinking”的过程中有多重视句子的其它部分。
这些分数是通过打分单词(所有输入句子的单词)的键向量与“Thinking”的查询向量相点积来计算的。所以如果我们是处理位置最靠前的词的自注意力的话,第一个分数是q1和k1的点积,第二个分数是q1和k2的点积。向量、一个键向量和一个值向量。
第三步和第四步是将分数除以8(8是论文中使用的键向量的维数64的平方根,这会让梯度更稳定。这里也可以使用其它值,8只是默认值),然后通过softmax传递结果。softmax的作用是使所有单词的分数归一化,得到的分数都是正值且和为1
这个softmax分数决定了每个单词对编码当下位置(“Thinking”)的贡献。显然,已经在这个位置上的单词将获得最高的softmax分数,但有时关注另一个与当前单词相关的单词也会有帮助。
第五步是将每个值向量乘以softmax分数(这是为了准备之后将它们求和)。这里的直觉是希望关注语义上相关的单词,并弱化不相关的单词(例如,让它们乘以0.001这样的小数)。
第六步是对加权值向量求和(译注:自注意力的另一种解释就是在编码某个单词时,就是将所有单词的表示(值向量)进行加权求和,而权重是通过该词的表示(键向量)与被编码词表示(查询向量)的点积并通过softmax得到。),然后即得到自注意力层在该位置的输出(在我们的例子中是对于第一个单词)
这样自自注意力的计算就完成了。得到的向量就可以传给前馈神经网络。然而实际中,这些计算是以矩阵形式完成的,以便算得更快。那我们接下来就看看如何用矩阵实现的。
通过矩阵运算实现自注意力机制
第一步是计算查询矩阵、键矩阵和值矩阵。为此,我们将将输入句子的词嵌入装进矩阵X中,将其乘以我们训练的权重矩阵(WQ,WK,WV)
x矩阵中的每一行对应于输入句子中的一个单词。我们再次看到词嵌入向量 (512,或图中的4个格子)和q/k/v向量(64,或图中的3个格子)的大小差异。
最后,由于我们处理的是矩阵,我们可以将步骤2到步骤6合并为一个公式来计算自注意力层的输出。
“大战多头怪”(multi-attention)
通过增加一种叫做“多头”注意力(“multi-headed” attention)的机制,论文进一步完善了自注意力层,并在两方面提高了注意力层的性能:
1.它扩展了模型专注于不同位置的能力。在上面的例子中,虽然每个编码都在z1中有或多或少的体现,但是它可能被实际的单词本身所支配。如果我们翻译一个句子,比如“The animal didn’t cross the street because it was too tired”,我们会想知道“it”指的是哪个词,这时模型的“多头”注意机制会起到作用。
2.它给出了注意力层的多个“表示子空间”(representation subspaces)。接下来我们将看到,对于“多头”注意机制,我们有多个查询/键/值权重矩阵集(Transformer使用八个注意力头,因此我们对于每个编码器/解码器有八个矩阵集合)。这些集合中的每一个都是随机初始化的,在训练之后,每个集合都被用来将输入词嵌入(或来自较低编码器/解码器的向量)投影到不同的表示子空间中。
在“多头”注意机制下,我们为每个头保持独立的查询/键/值权重矩阵,从而产生不同的查询/键/值矩阵。和之前一样,我们拿X乘以WQ/WK/WV矩阵来产生查询/键/值矩阵。
如果我们做与上述相同的自注意力计算,只需八次不同的权重矩阵运算,我们就会得到八个不同的Z矩阵。
这给我们带来了一点挑战。前馈层不需要8个矩阵,它只需要一个矩阵(由每一个单词的表示向量组成)。所以我们需要一种方法把这八个矩阵压缩成一个矩阵。那该怎么做?其实可以直接把这些矩阵拼接在一起[10*512]。从第二张图中可以多头函数看出:attention函数输入为由原来的Q,K,V变成了QW(上标为Q,下标为i),KW(上标为K,下标为i),VW(上标为V,下标为i);即3个W都不相同;将Q,K,V由原来的512维度变成了64维度(因为采取了8个多头);然后再拼接在一起变成512维,通过W(上标为O)进行线性转换;得到最终的多头注意力值;
个人最终认为:多头的本质是多个独立的attention计算,作为一个集成的作用,防止过拟合;从attention is all your need论文中输入序列是完全一样的;相同的Q,K,V,通过线性转换,每个注意力机制函数只负责最终输出序列中一个子空间,即1/8,而且互相独立;
这几乎就是多头自注意力的全部。这确实有好多矩阵,我们试着把它们集中在一个图片中,这样可以一眼看清。
既然我们已经摸到了注意力机制的这么多“头”,那么让我们重温之前的例子,看看我们在例句中编码“it”一词时,不同的注意力“头”集中在哪里:
当我们编码“it”一词时,一个注意力头集中在“animal”上,而另一个则集中在“tired”上,从某种意义上说,模型对“it”一词的表达在某种程度上是“animal”和“tired”的代表。
然而,如果我们把所有的attention都加到图示里,事情就更难解释了:
至此注意力层结束,得到 向量 Z(1*512), 在本例子中 就是 10*512 (输入的这条句子有10个单词)
三、残差模块(层-归一化)
在继续进行下去之前,我们需要提到一个编码器架构中的细节:在每个编码器中的每个子层(自注意力、前馈网络)的周围都有一个残差连接,并且都跟随着一个“层-归一化”步骤。
如果有多个解码器和编码器的话,就如下图所示:
四、前馈神经网络
其实是一个全连接的神经网络,前面三个处理都是线性,这里加入前馈神经网络目的是使得模型由非线性的成分,提高模型效能
五、我们分类模型的应用
较于transformer, 改进在于:
- 如下图利用了一个 E * H 的矩阵,减小了模型的参数量,举个本文的例子,如果1000个单词的字典,那么就需要一个 1000*512 的矩阵去转化input的单词,现在我们只需要 1000 * 16,和一个 16*512 的两个矩阵就可以完成这个事情了。
- 下图中每一个Trm层都是 有 attention,FFN组成的,区别在于transformer每次只有一个Trm层,然后串联的迭代循环,如下图之下图
- 还有一个优势在于,transformer每一个Trm层都有自己参数矩阵,但是 Albert不是,如本例子中5个Trim为一次,他下一次的,也就是下一个layer是共享上一个Trm的参数矩阵的。
综上为 Albert 相较于 Bert 的优势
然后 在经过 n layer 的训练后,图中5个Trim,每个Trm都会有一个 10 * 512 的矩阵,然后这5个10 * 512 mean()求均值。得到 10 * 512 的矩阵 然后根据单词顺序拼接成 10个1512的向量,也就是15120的向量, 经过一个 线性的 linear(浅层神经网络,神经元里不加上 非线性函数就好 ) 输出 为 1* 2 的向量,第一维度代表阳性,第二维度代表阴性,softmax函数就是均一化两个结果,使之和为1,这样就可以看成 属于阳性的概率和属于阴性的概率了。