BERT : Bidirectional Encoder Representations from Transformers
0 序
最近看了台大教授李宏毅的<Transformer>, <BERT>视频讲解,本篇文章大部分为课程笔记。
1 理论
Bert是Transformer的Encoder部分
Transformer是seq2seq的模型,seq2seq一般分为两个阶段,encoder和decoder,最初encoder和decoder分别由一个RNN组成。RNN有很多串联的子节点组成,前一个节点的输出会作为当前节点的输入。如下图,循环神经网络的当前状态At是根据前一个时刻的状态At-1和当前的输入Xt共同决定的,所以很难并行化。
CNN是解决并行化的一个很好的思路,但是每一层的featuremap的节点都有自己的“感受野”,只有高层的featuremap才能才能考虑到长距的信息。
Transformer中的selfAttention layer层和RNN的作用相同,都是seq2seq的模型。而且解决了RNN和CNN的痛点,不仅可以并行化运行,而且每个输入的编码如y1,都有全局的信息。
在google的一篇blog中,可视化展示了selfAttention Layer中的注意力矩阵。
第一个句子:
"The animal didn't cross the street because it was too tired"。从图示中看到和it和animal的关联性比较强。
第二个句子:
"The animal didn't cross the street because it was too wide"。只改变了最后一个单词。it的注意力从animal转到了street。神不神奇,惊不精喜!
Transformer最初是在论文<Attention is all you need>中提出的。意思很明确,只需要Attention,什么RNN,CNN等等之辈皆不需~它是怎么做的呢?输入Xi乘以一个权重矩阵W,进行了embedding,表示为ai。之后丢到self attention layer。ai分别乘以三个矩阵Wq,Wk,Wv,转换为qi,ki,vi。
每个q会跟每个k做Attention。
计算公式为:
其中d为矩阵q和k的维度数值,除以sqrt(d),是为了避免内积(对应位置数值累加之和)过大。
Attention的工作:吃(feed 或 input)两个向量,output一个分数,表示匹配度,称之为attention。
之后做softmax计算,把数值归一化到(0,1)之间。
天涯若比邻:可以看到b1是看过了a1到a4产生的。如果b1只想关注a1,那么可设置a12, a13, a14为0. 如果考虑a4的输入信息,那么a14不为0即可。b2,b3,b3也可以采用同样的方式获取。并且b1,b2,b3,b4的计算过程是可并行的。
以上讲的为由输入{x1,x2, x3, x4}并行得到他们的特征{b1,b2,b3,b4}的计算过程。
再用矩阵演算一遍之前的过程:
输入{a1,a2,a3,a4}组成输入矩阵I。{a1,a2,a3,a4}分别乘以Wq得到{q1,q2,q3,q4}。{q1,q2,q3,q4}可表示为Q。同理{a1,a2,a3,a4}分别乘以Wk得到{k1,k2,k3,k4}。{k1,k2,k3,k4}可表示为K;
{a1,a2,a3,a4}分别乘以Wv得到{v1,v2,v3,v4}。{v1,v2,v3,v4}可表示为V。
q1需要分别和k1,k2,k3,k4做内积。那么{k1,k2,k3,k4}可以作为一个列向量。q1与此列向量KT相乘。
类似q1, q2,q3,q4也需要分别与KT进行内积。同样q1, q2,q3,q4也可以组成列向量Q。那么得到注意力矩阵A即为矩阵Q和矩阵KT内积运算的结果。
串联整个运算过程,从上图可看到,从输入向量I到输出向量O,中间的过程都可以用矩阵运算表示。而GPU由专门芯片设计做并发计算,适合海量数据的并行处理。矩阵乘法运算,可运行GPU并行运算加速!
上述所罗列的是一次self-attention的过程,Transformer对其进行了扩充,可同时存在多个self-attention,各个O矩阵的contact作为最终结果。即每一组q,k,v做不同的事情,如下图第一张图每个单词更关注它周围的词的信息,而第二张图更复杂些,每个word关注更远矩阵的词信息。
多head可以理解为对每个q,k,v进行了多次裂变(如下图2个head,裂变了2次)。和上述运算过程相同。qi1只会和ki1,vi1......做运算,类似qi2只会和ki2,vi2......做运算。分别得到bi1和bi2。
如果想改变最终的输入维度,可以对{bi1,bi2}做一次矩阵变换。{bi1,bi2}变成bi。
I加上b作为最终self-layer层的输出。只能说resnet影响深远。哈哈。
以上所 讲的为Transformer的encoder的self-layer层,此外它还有一个前向运算(借了一个全连接层),然后selfattention-layer的输出和全连接层的输出做Add和LayerNorm的运算。至此,Bert部分完了。即Bert是Transformer的Encoder部分,Transformer除Encoder部分,还有Decoder部分,如下图阴影部分所示。
之前感觉维度变换很乱,分析了源码后,画了一张维度变化图:
2 应用
应用主要分为4大类:
应用1:文本分类
应用2:序列标注
应用3:句子关系判断(输入是2个句子)
应用4:生成式任务
3 关键技术总结
1 word embedding
2 Transformer Encoder部分应用