注:
Unimelb Comp90042 NLP笔记
相关tutorial代码链接
本文除去COMP90042笔记之外还参考了李宏毅的视频和其他链接(在文中已标出)。
包括上一篇,至此我们能够根据上下文得出目标单词的词向量,但是当目标单词有多种意思时,我们没办法用同一向量来表示。
所以我们希望根据上下文生成同一单词的不同词向量。
Embeddings from Language Models (ELMos)
ELMo是由两层 双向 LSTM (biLM)组成,其隐藏维度(hidden dimension)数量为 4096。
它主要是通过字符级的卷积神经网络(Character convolutional network) 来生成词嵌入(word embeddings),因此就不会存在不知道的单词了。
由于 biLM 的输入是根据字符而不是单词计算的,因此它捕获了单词的内部结构。例如,biLM甚至无需查看它们经常出现的上下文,就可以辨别出 beauty 和 beautiful 是相似的。
CNN :
卷积神经网络经常会使用在图像处理中。我们把一张图看成一个像素矩阵,然后拿着一个小正方形窗口(通常为3*3或5*5)从左到右从上到下,在图片上进行滑动。然后将每个窗口内的信息送入卷积层,因为卷积层有不同参数,所以输出的数据大小也不同。
它会通过 padding 来保证获取到图像边缘处的信息(因为进入卷积层之后,如果没有进行padding可能会出现边缘信息消失),会通过 Max pooling 对数据大小进行压缩。
把它带到NLP里,也是相同的作用,可以把单词当做一维单通道的图像。我们通过增加 padding 来保证单词最前最后的字符能送入卷积层。然后通过滑动窗口依次进行移动,进入卷积层再通过池化层压缩,最后经过全连接再输出一个字符级代表向量(包含着该单词内的一些特征)。
ELMo 有多好?
在这五项任务中,ELMo至少比baseline高了 5.8%。
其他发现
假设现在我们有一个已经训练好的ELMo模型,我们希望得到 “Let’s stick to” 中 stick 的词向量(根据这句话得出的词向量)
Step 1:
按照单词进入CNN,生成绿色的词嵌入,随后分别进入正向和反向的两层LSTM,得到每一层的词向量(图中的红色、紫色)。
Step2:
下游任务:词性标注
假设现在我们拿着训练好的ELMo,去做一个词性标注任务,我们将ELMo输出的词向量和原文向量进行合并,作为RNN的输入向量。,从而进行预测。
此时,状态 s i s_i si的函数就变为了:
s i = t a n h ( W s s i − 1 + ( W x x i ⊕ e i ) + b ) s_i=tanh(W_ss_{i-1}+(W_xx_i\oplus e_i)+b) si=tanh(Wssi−1+(Wxxi⊕ei)+b)
Glove 是一种统计共现矩阵、非上下文的词向量生成方法。当给定一个单词 play 的时候,我们能通过比较向量之间的远近,找到 playing,game 等单词;
biLM 是双向语言模型,通过上下文来生成不同的词向量。当给定不同包含 play 的句子时,它会给出包含 play 的整句话最相近的邻居。比如下图中,虽然两个 play 都是话剧的意思,但是他们的最近邻居并不是同一个,这是因为此处词向量是根据上下文的不同而有所不同。
一个总结了很多BERT相关问题的链接,值得一看,可以看完本文再去了解。
RNN的缺点:
我们在回想一下刚刚讲的ELMo,它是使用了两层双向LSTM,然而所谓双向实际上是分别运行,直到最后才将两个方向生成的向量合并在一起。
也就是它的正反向在处理数据的时候并没有相互考虑到对方!
为了解决这些缺点,Devlin 在2019年提出了一个 BERT(Bidirectional Encoder Representations from Transformers)
BERT
对比 ELMo 和 BERT 结构
如前文所述,ELMo是按照顺序输输入(一次只看一个当下的)正向与反向的两层LSTM,随后再将各层向量进行合并再输出。
BERT 会一股脑让模型看到所有的输入数据,然后由多层 Transformers 来同时处理所看到的每个数据。后文将会详细说明 Transformer,这里就记住BERT通过Transformers对输入数据进行并行处理。
下图是 BERT 的最核心的两个步骤:
例子:垃圾邮件鉴别
根据前文所述,BERT会将所有相关数据输入,通过多层的 Transformers 输出要注意的是,我们需要在原始句子最开头添加一个特殊token [CLS]。
因为 Transformers 会以此把 [CLS] 和句子中的其他token进行关联计算,所以相当于 [CLS] 输出的 上下文表示向量可以代表整句话的含义。
此时,我们就用 [CLS] 的上下文向量作为我们下游任务的输入!
为了去鉴别垃圾邮件,我们简单的在BERT上加了一个二元分类器,仅把 [CLS] 对应生成的上下文向量作为输入,然后先随机生成分类器中的参数。
根据监督分类方法,我们通过计算误差项反向传播更新分类器中的参数,同时整个BERT中的参数也会被更新!
监督分类器之后,我们就训练好一个基于 BERT 的垃圾邮件分类器了!
每一项任务都有最高的准确率,其中 B E R T B A S E BERT_{BASE} BERTBASE 是12层 Transformer Encoder, B E R T L A R G E BERT_{LARGE} BERTLARGE 是24层。
别人的Transformer模型详解
前文中提到, ELMo中处理数据的都是 LSTM,LSTM我们已经清楚是什么。但 BERT 中处理数据的 Transformer Encoders 我们并不清楚,因此本章节将会说 什么是 Transformers!
Transformer 是 2017年 Google 团队提出的,有两个主要模块 Encoders 和 Decoders。简略图就是如下展示,通过编码器得到编码信息,再对编码信息进行解码,得到最后结果。
这张图是 Attention is all you need 论文中 Transformers 的完整结构图,后面将慢慢细讲。
既然 BERT 中使用的是 Transformer Encoder,那先看一波 Encoder 的结构。
从下至上简单的浏览一下:
接下来我们从最陌生 自注意力模型 Self-Attention(SA) 开始。
(注:Attention和self-attention不同)
假设现在有一句话 “昨天上课讲了BERT模型,竟然不知道BERT这么好!” ,我希望通过一个模型来判断这句话的正负向情感。回想一下之前说的方法:
所以想象一下,当我们去看这句话的时候,我们会更关注后半句话,或者可能会一眼看到那个 好 字,从而判断感情。
或者举另一个翻译的例子,若要把上面的中文翻译成英文,那在翻译 昨天 的时候,我们只会更注意 今天 这两个字,毕竟翻译最基本的想法就是一一对应。
或者再举另一个翻译的例子,从中译英时,我们需要考虑的是时态,Yesterday’s class covered the BERT model 那么在翻译动词 讲 的时候,我们不仅要把注意力放在 讲 本身上,还要去注意 昨天 。
这就是 Attention 机制最直译地理解。
那我们如何让模型实现这个过程?
现在要生成 made 的上下文表示向量,那么我们将把 made 和其前后的这三个词分别计算关联,然后生成包括自己在内的四个向量,并且给这个四个向量分配不同的权重。
题外话
其实看到这里,我就很迷惑为什么我们需要从上下文单词中拉出 Key 和 Value 两个向量,用一个不就行了吗。
但后来发现他们虽然存在一定关系但是是完全不一样的用意。
比如说现在有一个单词 network ,但所在的句子中既有 neural 也有 social。根据我们的经验,social network 和 neural network 都会经常出现,所以说当判断 network 的query和这两个单词的 key 时,都会得到较大的权重。我们也可以理解为 “对于 network 来说,social 和 neural 需要 pay的attention是一样的”。key是这两个词对于query的attention程度,但是!!value是这两个词本身含义的向量,这两个词的vaule就不可能相像了。
题外话结束
这张图是整个 Self-Attention 求一个 target word 上下文向量的结构。
首先我们先来讲最底下两层:生成qkv向量以及kq比较。
现在设 α \alpha α 可以表示两个单词相关的程度,我们有两种方法来体现:
Dot-Product:
Additive
第二种方法将 q k 两个向量进行相加,然后通过 tanh 进行变化生成矩阵 W 最后计算得到 α \alpha α。
在 Self-Attention 里面,我们用的是第一种 点乘法 来得到 α \alpha α 。
将比较过程公式化
我们现在想知道 目标单词 a 1 a^1 a1 向量与上下文词 a 2 a^2 a2 之间的关联性如何。
那么把 W q a 1 W^qa^1 Wqa1 当成 query q 1 q^1 q1, W k a 2 W^ka^2 Wka2 当成 key k 2 k^2 k2,点乘后(由于两个都是向量所以是对应相乘再相加)得到的 α 1 , 2 \alpha _{1,2} α1,2 作为 attention score。
由于 W q , W k , W v W^q,W^k,W^v Wq,Wk,Wv 三个参数对于任何一个向量来说都是不变的,且他们三个大小相等。那我们就可以矩阵运算把所有的向量一股脑乘上这三个参数,从而得到 Query、Key、Value 向量。
注: 因为是矩阵参数乘上向量,所以我们可以通过矩阵的大小来控制输出向量的大小!比如说我现在输入的向量大小是 5 * 1,然后用 大小为 4 * 5 的参数矩阵乘上它,就可以输出一个 4 * 1 的向量。
假设现在我们只有四个输入向量 a 1 , a 2 , a 3 , a 4 a^1,a^2,a^3,a^4 a1,a2,a3,a4(多行一列) ,然后将他们拼成多行四列的大矩阵。随后再用参数矩阵去乘上大矩阵,根据矩阵的乘法,我们得出的结果矩阵 Q Q Q 其实可以直接拆成 q q q。
通过参数矩阵乘上拼接输入向量之后,我们得到了三个大矩阵 Q , K , V Q,K,V Q,K,V,分别包含了所有单词的query、key、value向量。
之所以采用矩阵方式计算的目的 是为了提高经计算速度
随后开始 计算 α \alpha α。
因为 q 和 k 是两个大小相等的向量,点乘过程相当于是对 k 做了个转置。
这里变成了 k 在前面 q 的原因应该是由于我们这里给的向量的图解释是 4 * 1,但实际向量表示都是 1 * 4,可以理解为 A B T = ( B A T ) T AB^T=(BA^T)^T ABT=(BAT)T,但这里正好两个都是向量,所以交换相乘结果还是一样。
以第一个单词的query去乘上所有单词的key,变成矩阵运算:
然后将矩阵计算推广成一个 α \alpha α 矩阵:
至此,我们得到了所有比较的 Attention Score。也就是下图中,红色框内的东西。
结束下两层,现在进行最后三层讲解:
我们对每一列 α \alpha α 做归一化得到 α ′ \alpha ' α′
最后求输出层的向量, V 乘上 *A’*每一列就可以得到一个 b(矩阵相乘包括了乘法和加法),b 就是输出向量了。
接下来展开讲一下这两层具体的内容:
Softmax
softmax在这里的作用就是归一化。
下面公式中的 q ⋅ k q \cdot k q⋅k 即我们前面提到的 Attention Score,q 是 target word的,k 是其中一个 context word 的,经过 softmax 函数之后结果为 α ′ \alpha ' α′ 如下所示
α ′ = e q ⋅ k ∑ j e q ⋅ k j \alpha '= \frac{e^{q\cdot k}}{\sum_j e^{q\cdot k_j} } α′=∑jeq⋅kjeq⋅k
α ′ \alpha ' α′ 即为归一化的 Attention Score
处理 Value 向量
前一层得出的 归一化 Attention Score 在这一层将作为权重乘上对应的 value 向量。所以红圈内的值为 e q ⋅ k ∑ j e q ⋅ k j ⋅ v \frac{e^{q\cdot k}}{\sum_j e^{q\cdot k_j}} \cdot v ∑jeq⋅kjeq⋅k⋅v
但要注意的是这里的 k 和 v 都是来自同一个 word 的。
每一层都看懂了之后,我们写出 target word 的通式,我们用 A ( q , K , V ) A(q,K,V) A(q,K,V) 来表示最上方的 output,其中 q 是 target word 的 query 向量, K,V 是所有单词的 key、value向量所组成的矩阵:
A ( q , K , V ) = ∑ i s o f t m a x ( q ⋅ k i ) × v i = ∑ i e q ⋅ k i ∑ j e q ⋅ k j × v i A(q,K,V) = \sum_i softmax(q\cdot k_i) \times v_i= \sum_i\frac{e^{q\cdot k_i}}{\sum _j e^{q\cdot k_j}} \times v_i A(q,K,V)=i∑softmax(q⋅ki)×vi=i∑∑jeq⋅kjeq⋅ki×vi
一般 Self-Attention 用作 seq2seq 的情形(比如翻译、POS等),也就是说一次输出一串序列,那么每个单词都会作为一次 target word。同样,为了提高计算速度,用矩阵方式计算。那么最终的通式即为:
A ( Q , K , V ) = s o f t m a x ( Q K T ) V A(Q,K,V) = softmax(QK^T)V A(Q,K,V)=softmax(QKT)V
题外话
这里可能有人会疑惑,因为前面文章写的是 K T K^T KT 乘上 Q Q Q,而这里却反过来了。之前也讲过了,因为前文是将输入向量作为一个多行一列的矩阵来计算,但通常输入向量都是一行多列,两者是一个转置的关系。因为要用此处的一行多列向量形成的 Q K T QK^T QKT 为基准 那么 前文的公式就应该表示为 K Q T KQ^T KQT。两者相乘结果为 E E E(基本公式就是 A B T = ( B A T ) T AB^T=(BA^T)^T ABT=(BAT)T)。
所以在计算输出矩阵 A ′ V A'V A′V同理,使得最终两者答案一致。
题外话结束
如果我们想避免点乘的结果过大,可以用将 Attention Score 矩阵进行缩放,其中 d k d_k dk 是 query和key向量的维度。(更新:当时说的模糊,看完激活函数之后才反应过来,可以看这篇文章,重点就是归一化,防止softmax饱和,导致梯度消失)
醒醒,我们现在其实在讲BERT,还记得不。
我们从BERT → \rightarrow →Transformer的Encoder → \rightarrow →Multi-Head Attention → \rightarrow → Self-Attention,然后 Self-Attention 我们总算是搞完了,现在开始讲 Multi-Head Attention。(好一个讨人厌的递归啊!)
(我还是像墨大一样,只讲需要用到的地方吧。后面再单独开文章。。)
Multi-Head ,可以理解为我们有多个 Self-Attention,每个Self-Attention 都有不同的 W q , W k , W v W_q,W_k,W_v Wq,Wk,Wv。
比如说现在我们有 4 个头,那会得到 4 个 输出向量。然后就是无脑拼接,再用一个矩阵做线性变化得到最后的输出。
整体过程其实就如下图所示(输入时 2 * 4 的矩阵,Self-Attention 输出是2 * 3,拼成 2 * 21,用 21 * 4 的矩阵进行线性变化,最后得到一个 2 * 4 的输出):
写成通式的话:
M u l t i ( Q , K , V ) = c o n c a t ( h e a d 1 , . . . , h e a d h ) W o h e a d i = A t t e n t i o n ( Q W i Q , K W i K , V W i V ) Multi(Q,K,V)=concat(head_1,...,head_h)W_o\\ head_i=Attention(QW_i^Q,KW_i^K,VW_i^V) Multi(Q,K,V)=concat(head1,...,headh)Woheadi=Attention(QWiQ,KWiK,VWiV)
Multi-Head Attention 结束了之后,我们终于可以回到 Transformer Encoder了。
我们发现在进入Multi-Head Attention 之前还有一步,就是这个 Positional Encoding。
我们简单回想一下刚刚的所有过程,因为Attention能一下子接收到所有的输入数据,然后在计算 QKV,但是它并不知道这些数据之间的顺序是如何的,即在查看两个单词关联性的时候并没有考虑过单词位置信息。
因此需要Positional Encoding。对每一个不同位置设置一个位置向量,然后直接将位置向量加在输入向量前面。
但是位置向量目前大部分是人为设置的,不过也有用sin/cos函数生成。positional encoding还是待研究的,可以参考一下下图的研究内容。
至此,新知识都已经讲过了,哈哈就戛然而止,这一节课要拓展的内容实在太多了,其实应该就按照学校ppt来写,其他的内容再做衍生。
题外话
self-attention的应用会在transformer会在bert,但在语音里面应用的时候,当self-attention考虑一整句话的时候,矩阵大小会非常大,导致内存紧张,所以出现了 truncated self-attention ,也就是原本考虑一整句话的地方现在仅截取其中一段作为考虑。
在图像处理中,CNN就是self-attenttion的特例,也就是CNN限制更多看到的。
CNN在数据量少的时候效果比较好,当在3亿张图片的时候self-attention的结果就比CNN好,因为self-attention的弹性会比CNN高,训练少的时候self-attention容易overfitting。
paper : Attention is all you need
Transformers are RNN
ALbert (小型bert)
transformer-xl segment-level的pretrain
Encoder和decoder的最大区别就是encoder可以看到所有输入,但是decoder只能顺序看到输入
这一篇关于把Attention用于深度学习的不错。
https://zhuanlan.zhihu.com/p/265108616
https://zhuanlan.zhihu.com/p/53682800
https://zhuanlan.zhihu.com/p/43493999
transformer https://zhuanlan.zhihu.com/p/338817680