【NLP基础理论】10 上下文表示(Contextual Representation)

注:

Unimelb Comp90042 NLP笔记

相关tutorial代码链接
本文除去COMP90042笔记之外还参考了李宏毅的视频和其他链接(在文中已标出)。

上下文表示

目录

  • 上下文表示
  • 1 ELMo
    • 1.1 简介
    • 1.2 提取上下文表示内容
      • 1.2.1 上下文 v.s. 非上下文
      • 1.2.2 上下文表示的缺点
  • 2 BERT
    • 2.1 前提回顾
    • 2.2 简介
    • 2.3 BERT目的
      • 2.3.1 目的1:屏蔽语言模型(Masked Language Model)
      • 2.3.2 目的2:下一句话的预测
    • 2.4 模型训练的细节
    • 2.5 如何使用BERT
      • 2.5.1 训练和微调(fine-tuning)
    • 2.6 BERT vs. ELMo
    • 2.7 BERT 有多好
  • 3 Transformers
    • 3.1 简介
    • 3.2 Encoder
      • 3.2.1 Self-Attention
        • 3.2.1.2 Self-Attention 中的 Query, Key, Value
        • 3.2.1.3 比较 Query 和 Key
        • 3.2.1.4 归一化等计算
        • 3.2.1.5 最终输出
        • 3.2.1.6 总结所有过程
      • 3.2.2 Multi-Head Attention
      • 3.2.3 Positional Encoding
    • 3.3 Self-attention 和 RNN的区别

前情提要:

  1. 词向量/嵌入
    • 每个单词类型都有一个表现形式(上一篇文章中说到的Word2Vec)
    • 但这些表现形式只有一种,不管这个单词的上下文是什么。也就是一词多义也只有一个向量。
    • Contextual representation(上下文表示) 指的是基于上下文来表示单词
    • 预训练的上下文表示对于下游应用来说真的不错。
  2. RNN 语言模型
    回忆一下之前的RNN,其实当时提到的隐藏状态 就是上下文表示,因为它包含了上一个单词的内容和当前单词的内容。
    【NLP基础理论】10 上下文表示(Contextual Representation)_第1张图片
    但从图中也可以看到,我们只能获取目标单词左边的上下文,不过我们可以用双向RNN解决这个问题,实现获取目标单词左右两边的上下文。
  3. 双向RNN
    双向RNN就是将原来的RNN reverse一下,然后将目标单词两边的上下文concatenate。
    【NLP基础理论】10 上下文表示(Contextual Representation)_第2张图片
    这里我们将 [ s 3 , u 3 ] [s_3,u_3] [s3,u3] 合并,既可以表示eats上下文。 s 3 s_3 s3 包括了单词 a, cow, eats u 3 u_3 u3 包括了 . , grass, eats

包括上一篇,至此我们能够根据上下文得出目标单词的词向量,但是当目标单词有多种意思时,我们没办法用同一向量来表示。

所以我们希望根据上下文生成同一单词的不同词向量。

1 ELMo

Embeddings from Language Models (ELMos)

  • Peters et al.(2018) 提出: https://arxiv.org/abs/
    1802.05365v2
  • 10 亿 单词上训练了一个双向多层 LSTM 语言模型。
  • 然后结合了多层LSTM的隐藏状态,用于下游任务。最开始只用了最顶层的信息用于研究。
  • 利用上下文来推断每个词对应的词向量,能够根据语境来对多义词理解
  • 大大提升了任务表现。

1.1 简介

ELMo是由两层 双向 LSTM (biLM)组成,其隐藏维度(hidden dimension)数量为 4096。
它主要是通过字符级的卷积神经网络(Character convolutional network) 来生成词嵌入(word embeddings),因此就不会存在不知道的单词了。

【NLP基础理论】10 上下文表示(Contextual Representation)_第3张图片
(图文链接)

  • 上述架构使用字符级卷积神经网络 (CNN) 将文本字符串中的单词表示为原始单词向量。
  • 这些原始词向量作为 biLM 第一层的输入
  • 前向传递包含有关某个单词和该单词之前的上下文(其他单词)的信息
  • 后向传递包含有关单词及其后的上下文的信息
  • 这对信息,来自前向和后向传播,形成了中间词向量
  • 这些中间词向量被输入到 biLM 的下一层
  • 最终表示(ELMo)是原始词向量和 2 个中间词向量的加权和

由于 biLM 的输入是根据字符而不是单词计算的,因此它捕获了单词的内部结构。例如,biLM甚至无需查看它们经常出现的上下文,就可以辨别出 beautybeautiful 是相似的。

CNN
卷积神经网络经常会使用在图像处理中。我们把一张图看成一个像素矩阵,然后拿着一个小正方形窗口(通常为3*3或5*5)从左到右从上到下,在图片上进行滑动。然后将每个窗口内的信息送入卷积层,因为卷积层有不同参数,所以输出的数据大小也不同。
它会通过 padding 来保证获取到图像边缘处的信息(因为进入卷积层之后,如果没有进行padding可能会出现边缘信息消失),会通过 Max pooling 对数据大小进行压缩。

把它带到NLP里,也是相同的作用,可以把单词当做一维单通道的图像。我们通过增加 padding 来保证单词最前最后的字符能送入卷积层。然后通过滑动窗口依次进行移动,进入卷积层再通过池化层压缩,最后经过全连接再输出一个字符级代表向量(包含着该单词内的一些特征)。
【NLP基础理论】10 上下文表示(Contextual Representation)_第4张图片
ELMo 有多好?
【NLP基础理论】10 上下文表示(Contextual Representation)_第5张图片
【NLP基础理论】10 上下文表示(Contextual Representation)_第6张图片
在这五项任务中,ELMo至少比baseline高了 5.8%。

其他发现

  • 较低层的向量表示可以抓住句法(syntax)
    • 比如说对于 词性标注命名实体识别会有较好效果。(可能底层只能想抽出一些句子中单词之间的关系)
  • 较高层的向量表示可以抓住语义(semantics)
    • 对于 问题回答(QA)文本蕴含情感分析会有较好效果。(高层就能抽出一些句子中比较抽象的东西)

1.2 提取上下文表示内容

假设现在我们有一个已经训练好的ELMo模型,我们希望得到 “Let’s stick to”stick 的词向量(根据这句话得出的词向量)

Step 1:
【NLP基础理论】10 上下文表示(Contextual Representation)_第7张图片
按照单词进入CNN,生成绿色的词嵌入,随后分别进入正向和反向的两层LSTM,得到每一层的词向量(图中的红色、紫色)。
Step2
【NLP基础理论】10 上下文表示(Contextual Representation)_第8张图片

  • 按照层,将正反模型中输出的向量进行合并;
  • 得到三个向量之后,给每个向量乘上不同的权重(这个权重设置是在下游模型中进行调整的,ELMo也是预训练模型,后文慢慢讲预训练模型)
  • 最后把三个已经乘上权重的向量相加,得到最后的词向量,这个词向量便是基于上下文得到的最后结果。

下游任务:词性标注
假设现在我们拿着训练好的ELMo,去做一个词性标注任务,我们将ELMo输出的词向量原文向量进行合并,作为RNN的输入向量。,从而进行预测。
【NLP基础理论】10 上下文表示(Contextual Representation)_第9张图片
此时,状态 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(Wssi1+(Wxxiei)+b)

1.2.1 上下文 v.s. 非上下文

Glove 是一种统计共现矩阵、非上下文的词向量生成方法。当给定一个单词 play 的时候,我们能通过比较向量之间的远近,找到 playinggame 等单词;
biLM 是双向语言模型,通过上下文来生成不同的词向量。当给定不同包含 play 的句子时,它会给出包含 play 的整句话最相近的邻居。比如下图中,虽然两个 play 都是话剧的意思,但是他们的最近邻居并不是同一个,这是因为此处词向量是根据上下文的不同而有所不同。
【NLP基础理论】10 上下文表示(Contextual Representation)_第10张图片

1.2.2 上下文表示的缺点

  • 难以进行内在的评价,例如:单词
    相似性、类比性。(因为同一个单词它的向量都不同,所以以单词来进行评价会比较难)
  • 可解释性(很难解释他到底从上下文中学到的是什么)
  • 训练大规模的上下文嵌入(要根据上下文找到单词的意思会需要非常大的同类数据)

2 BERT

一个总结了很多BERT相关问题的链接,值得一看,可以看完本文再去了解。

2.1 前提回顾

RNN的缺点:

  • 顺序处理:难以扩展到非常大的语料库或模型。
  • RNN语言模型从左到右运行(捕获
    只有一侧的语境)
  • 双向RNN虽然有帮助,但它们只能捕捉到
    表面的双向表征

我们在回想一下刚刚讲的ELMo,它是使用了两层双向LSTM,然而所谓双向实际上是分别运行,直到最后才将两个方向生成的向量合并在一起。
也就是它的正反向在处理数据的时候并没有相互考虑到对方!

为了解决这些缺点,Devlin 在2019年提出了一个 BERT(Bidirectional Encoder Representations from Transformers)

2.2 简介

BERT

  • 使用 self-attention (aka Transformers)来抓取单词之间的联系,并且 self-attention能够避免顺序处理。
  • 通过 Masked language model (屏蔽语言模型)来抓住更深层的双向表示。
  • 但因为不是顺序处理,所以失去了生成语言的能力。
  • 如果目标是去学习一个上下文表示,那就没问题了

对比 ELMo 和 BERT 结构
如前文所述,ELMo是按照顺序输输入(一次只看一个当下的)正向与反向的两层LSTM,随后再将各层向量进行合并再输出。
【NLP基础理论】10 上下文表示(Contextual Representation)_第11张图片
BERT 会一股脑让模型看到所有的输入数据,然后由多层 Transformers 来同时处理所看到的每个数据。后文将会详细说明 Transformer,这里就记住BERT通过Transformers对输入数据进行并行处理。
【NLP基础理论】10 上下文表示(Contextual Representation)_第12张图片

2.3 BERT目的

2.3.1 目的1:屏蔽语言模型(Masked Language Model)

  • 随机 “遮蔽(mask)” 所有tokens中的 k%
  • 目的是为了去预测这些被遮住的单词
  • 比如下图中,我们随机遮住了两个单词,然后希望通过浏览整句话来预测被遮住的两个单词是什么。
    【NLP基础理论】10 上下文表示(Contextual Representation)_第13张图片

2.3.2 目的2:下一句话的预测

  • 希望模型能够从句与句中学习到一定关联
  • 预测句子B是不是跟在句子A后面
  • 为下游任务(分析句子对,比如说文本蕴含)提供有用的预训练目标
  • 比如,我们通过输入两个句子 A 和 B,然后输出二元结果,即判断 B 是不是 A 的下一句。
    在这里插入图片描述

2.4 模型训练的细节

  • 预训练模型的训练数据用的是 子单词(subword)
  • 使用了多层 transformers 去学习上下文表示
  • 数据是来自维基百科(Wikipedia)和 BookCorpus
  • 最初的模型训练使用了多个GPU,并花费了多天才训练出来

2.5 如何使用BERT

  • 在预训练 BERT 模型上,根据下游任务的数据在此基础上继续训练(这个过程也叫 fine-tune)
  • 但如何使预训练模型适应下游任务?
  • 在上下文表示的顶层多加一层分类层

2.5.1 训练和微调(fine-tuning)

下图是 BERT 的最核心的两个步骤:

  • Step 1:在大量的文本上进行半监督训练。
    一开始我们只需要去预测一些被遮住的单词是什么,相当于让BERT去学习填空题,但在这个学习填空的过程中就逐渐了解了什么是单词、句子、文章和他们之间的关系。
  • Step 2:在有标注数据的具体的任务上进行监督训练。
    这一步基于 BERT 已经是一个会读书认字的模型了,那我们再给它灌输一些特定的任务,让它学一下,想必很快就能学会了。
    【NLP基础理论】10 上下文表示(Contextual Representation)_第14张图片

例子:垃圾邮件鉴别

根据前文所述,BERT会将所有相关数据输入,通过多层的 Transformers 输出要注意的是,我们需要在原始句子最开头添加一个特殊token [CLS]
因为 Transformers 会以此把 [CLS] 和句子中的其他token进行关联计算,所以相当于 [CLS] 输出的 上下文表示向量可以代表整句话的含义
此时,我们就用 [CLS] 的上下文向量作为我们下游任务的输入!
【NLP基础理论】10 上下文表示(Contextual Representation)_第15张图片
为了去鉴别垃圾邮件,我们简单的在BERT上加了一个二元分类器,仅把 [CLS] 对应生成的上下文向量作为输入,然后先随机生成分类器中的参数。
根据监督分类方法,我们通过计算误差项反向传播更新分类器中的参数,同时整个BERT中的参数也会被更新
【NLP基础理论】10 上下文表示(Contextual Representation)_第16张图片
监督分类器之后,我们就训练好一个基于 BERT 的垃圾邮件分类器了!

2.6 BERT vs. ELMo

  • ELMo模型是通过语言模型任务得到句子中单词的 embedding 表示,然后将向量作为下游任务的输入
  • 因为ELMo输出的都是每个单词的上下文表示(也可以说是提取了这个单词的特征),所以这一类预训练的方法被称为“Feature-based Pre-Training”
  • ELMo 的参数都是固定的,即每一层向量合并之后的权重参数是固定的,它不会像 BERT 一样受到更新。
  • BERT 模型是“基于 Fine-tuning 的模式”,也就是我们在 BERT 模型的基础上,增加一个能够配合BERT的模型(而不需要配某个特定任务的模型),从而更新整个网络的参数。

2.7 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层。
【NLP基础理论】10 上下文表示(Contextual Representation)_第17张图片

3 Transformers

别人的Transformer模型详解
前文中提到, ELMo中处理数据的都是 LSTM,LSTM我们已经清楚是什么。但 BERT 中处理数据的 Transformer Encoders 我们并不清楚,因此本章节将会说 什么是 Transformers!
【NLP基础理论】10 上下文表示(Contextual Representation)_第18张图片

3.1 简介

Transformer 是 2017年 Google 团队提出的,有两个主要模块 EncodersDecoders。简略图就是如下展示,通过编码器得到编码信息,再对编码信息进行解码,得到最后结果。
【NLP基础理论】10 上下文表示(Contextual Representation)_第19张图片
这张图是 Attention is all you need 论文中 Transformers 的完整结构图,后面将慢慢细讲。
【NLP基础理论】10 上下文表示(Contextual Representation)_第20张图片

3.2 Encoder

既然 BERT 中使用的是 Transformer Encoder,那先看一波 Encoder 的结构。
从下至上简单的浏览一下:

  • Inputs:输入的原始数据,比如 “Let’s play balls
  • Input Embedding:把每个单词变成词嵌入,变成向量。
  • Positional Encoding:一个表示位置的向量。因为输入的词嵌入都是单独的,它没有任何位置信息,所以就算你是按照某种顺序输入数据,模型都不会知道每个词所对应的位置是如何。所以要对每一个不同位置设置一个位置向量,然后直接将位置向量拼接在输入向量前面。
  • Multi-Head Attention:多个 Self-Attention 组成 Multi-Head Attention。 Attention(注意力)是一种机制,在预测结果时把注意力放在不同的特征上(可以理解为当我们要预测 play 时,我们可以专注看 playLet’s 的关系或者 playballs 之间的关系)。后文会详细讲解 Self-Attention。
  • Add & Norm:分别是将处理结果和输入结果相加(类似残差网络),然后最归一化。后文会解释具体公式。
  • Feed Forward:就是一个简单的前馈神经,包括两层全连接层。
    【NLP基础理论】10 上下文表示(Contextual Representation)_第21张图片

接下来我们从最陌生 自注意力模型 Self-Attention(SA) 开始。
(注:Attention和self-attention不同)

3.2.1 Self-Attention

假设现在有一句话 “昨天上课讲了BERT模型,竟然知道BERT这么!” ,我希望通过一个模型来判断这句话的正负向情感。回想一下之前说的方法:

  • FFNN和CNN:虽然可以自动提取处单词属性,但是单词是一股脑塞进去的,毫无时序可言。在上面的例句中,可能模型会被训练成看到 就是负向,看到 就是正向,不好 通常一起出现的时候也是负向,所以这里例句可能会被判为负向。
  • RNNs:虽然有时序,但是真正决定这个句子正负向的关键词还是 ,RNNs会记录之前那么长没有用的东西,可能反而干扰了最终判断。

所以想象一下,当我们去看这句话的时候,我们会更关注后半句话,或者可能会一眼看到那个 字,从而判断感情。
或者举另一个翻译的例子,若要把上面的中文翻译成英文,那在翻译 昨天 的时候,我们只会更注意 今天 这两个字,毕竟翻译最基本的想法就是一一对应。
或者再举另一个翻译的例子,从中译英时,我们需要考虑的是时态,Yesterday’s class covered the BERT model 那么在翻译动词 的时候,我们不仅要把注意力放在 本身上,还要去注意 昨天
这就是 Attention 机制最直译地理解。

那我们如何让模型实现这个过程?

3.2.1.2 Self-Attention 中的 Query, Key, Value

现在要生成 made 的上下文表示向量,那么我们将把 made 和其前后的这三个词分别计算关联,然后生成包括自己在内的四个向量,并且给这个四个向量分配不同的权重。
【NLP基础理论】10 上下文表示(Contextual Representation)_第22张图片

  • input :
    • Query q ,在这里是 made ,即我们当下正在想要查询的那个词
    • Key k 和 Value v,在这里就是出去 made 之外的词,需要去pay attention的词
    • 键/值/查询概念类似于检索系统。例如,当您在 Youtube 上搜索视频时,搜索引擎会将您的查询(搜索栏中的文本)映射到与数据库中的候选视频相关联的一组键(视频标题、描述等),然后呈现给您最佳匹配的视频(值)。
  • Query, Key, Value 都是向量,都是经过embeddings线性投影来的
  • 比较目标词的Query向量made)和上下文词的Key向量以计算权重。(这个就是在pay attention的过程)
  • 目标词的上下文表述 = 上下文词和目标词的Value向量的加权和
    c m a d e = 0.1 v I + 0.5 v m a d e + 0.2 v h e r + 0.3 v d u c k c_{made} = 0.1v_I+0.5v_{made}+0.2v_{her}+0.3v_{duck} cmade=0.1vI+0.5vmade+0.2vher+0.3vduck

题外话
其实看到这里,我就很迷惑为什么我们需要从上下文单词中拉出 Key 和 Value 两个向量,用一个不就行了吗。
但后来发现他们虽然存在一定关系但是是完全不一样的用意。
比如说现在有一个单词 network ,但所在的句子中既有 neural 也有 social。根据我们的经验,social networkneural network 都会经常出现,所以说当判断 network 的query和这两个单词的 key 时,都会得到较大的权重。我们也可以理解为 “对于 network 来说,socialneural 需要 pay的attention是一样的”。key是这两个词对于query的attention程度,但是!!value是这两个词本身含义的向量,这两个词的vaule就不可能相像了。
题外话结束

这张图是整个 Self-Attention 求一个 target word 上下文向量的结构。
【NLP基础理论】10 上下文表示(Contextual Representation)_第23张图片
首先我们先来讲最底下两层:生成qkv向量以及kq比较。

3.2.1.3 比较 Query 和 Key

现在设 α \alpha α 可以表示两个单词相关的程度,我们有两种方法来体现:

  1. Dot-Product

    • 分别将目标字向量、上下文向量乘上 Query 参数和 Key 参数,得到 q 向量和 k 向量。
    • qk 两个矩阵进行点乘,得到相关程度 α \alpha α

    【NLP基础理论】10 上下文表示(Contextual Representation)_第24张图片

  2. Additive
    第二种方法将 q k 两个向量进行相加,然后通过 tanh 进行变化生成矩阵 W 最后计算得到 α \alpha α
    【NLP基础理论】10 上下文表示(Contextual Representation)_第25张图片

在 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
【NLP基础理论】10 上下文表示(Contextual Representation)_第26张图片
由于 W q , W k , W v W^q,W^k,W^v WqWkWv 三个参数对于任何一个向量来说都是不变的,且他们三个大小相等。那我们就可以矩阵运算把所有的向量一股脑乘上这三个参数,从而得到 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向量。
【NLP基础理论】10 上下文表示(Contextual Representation)_第27张图片
之所以采用矩阵方式计算的目的 是为了提高经计算速度

随后开始 计算 α \alpha α
因为 qk 是两个大小相等的向量,点乘过程相当于是对 k 做了个转置。
【NLP基础理论】10 上下文表示(Contextual Representation)_第28张图片
这里变成了 k 在前面 q 的原因应该是由于我们这里给的向量的图解释是 4 * 1,但实际向量表示都是 1 * 4,可以理解为 A B T = ( B A T ) T AB^T=(BA^T)^T ABT=(BAT)T,但这里正好两个都是向量,所以交换相乘结果还是一样。

以第一个单词的query去乘上所有单词的key,变成矩阵运算:
【NLP基础理论】10 上下文表示(Contextual Representation)_第29张图片
然后将矩阵计算推广成一个 α \alpha α 矩阵:
【NLP基础理论】10 上下文表示(Contextual Representation)_第30张图片
至此,我们得到了所有比较的 Attention Score。也就是下图中,红色框内的东西。
【NLP基础理论】10 上下文表示(Contextual Representation)_第31张图片

3.2.1.4 归一化等计算

结束下两层,现在进行最后三层讲解:
【NLP基础理论】10 上下文表示(Contextual Representation)_第32张图片
我们对每一列 α \alpha α 做归一化得到 α ′ \alpha ' α
最后求输出层的向量, V 乘上 *A’*每一列就可以得到一个 b矩阵相乘包括了乘法和加法),b 就是输出向量了。
【NLP基础理论】10 上下文表示(Contextual Representation)_第33张图片
接下来展开讲一下这两层具体的内容:

Softmax
softmax在这里的作用就是归一化
【NLP基础理论】10 上下文表示(Contextual Representation)_第34张图片
下面公式中的 q ⋅ k q \cdot k qk 即我们前面提到的 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} } α=jeqkjeqk
α ′ \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 jeqkjeqkv
【NLP基础理论】10 上下文表示(Contextual Representation)_第35张图片
但要注意的是这里的 kv 都是来自同一个 word 的。

3.2.1.5 最终输出

每一层都看懂了之后,我们写出 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)=isoftmax(qki)×vi=ijeqkjeqki×vi
【NLP基础理论】10 上下文表示(Contextual Representation)_第36张图片
一般 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 AV同理,使得最终两者答案一致。
题外话结束

3.2.1.6 总结所有过程

【NLP基础理论】10 上下文表示(Contextual Representation)_第37张图片
如果我们想避免点乘的结果过大,可以用将 Attention Score 矩阵进行缩放,其中 d k d_k dk 是 query和key向量的维度。(更新:当时说的模糊,看完激活函数之后才反应过来,可以看这篇文章,重点就是归一化,防止softmax饱和,导致梯度消失)
【NLP基础理论】10 上下文表示(Contextual Representation)_第38张图片

3.2.2 Multi-Head Attention

醒醒,我们现在其实在讲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
【NLP基础理论】10 上下文表示(Contextual Representation)_第39张图片

比如说现在我们有 4 个头,那会得到 4 个 输出向量。然后就是无脑拼接,再用一个矩阵做线性变化得到最后的输出。
整体过程其实就如下图所示(输入时 2 * 4 的矩阵,Self-Attention 输出是2 * 3,拼成 2 * 21,用 21 * 4 的矩阵进行线性变化,最后得到一个 2 * 4 的输出):
【NLP基础理论】10 上下文表示(Contextual Representation)_第40张图片
写成通式的话:
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)

3.2.3 Positional Encoding

Multi-Head Attention 结束了之后,我们终于可以回到 Transformer Encoder了。
【NLP基础理论】10 上下文表示(Contextual Representation)_第41张图片
我们发现在进入Multi-Head Attention 之前还有一步,就是这个 Positional Encoding。
我们简单回想一下刚刚的所有过程,因为Attention能一下子接收到所有的输入数据,然后在计算 QKV,但是它并不知道这些数据之间的顺序是如何的,即在查看两个单词关联性的时候并没有考虑过单词位置信息
因此需要Positional Encoding。对每一个不同位置设置一个位置向量,然后直接将位置向量加在输入向量前面。
【NLP基础理论】10 上下文表示(Contextual Representation)_第42张图片
但是位置向量目前大部分是人为设置的,不过也有用sin/cos函数生成。positional encoding还是待研究的,可以参考一下下图的研究内容。
【NLP基础理论】10 上下文表示(Contextual Representation)_第43张图片

3.3 Self-attention 和 RNN的区别

  1. 虽然 bi RNN也能让每个输入向量考虑到前后文,但是相比self-attention来说,越后面的向量就越难抓住前面的信息(也就是之前说的前面的信息会被遗忘)。而self-attention的话它是通过每个query配不同向量的key,即使两个向量间隔很远,但是他们会有直接的比较,也就能更好的考虑遥远的前文。
    【NLP基础理论】10 上下文表示(Contextual Representation)_第44张图片
  2. RNN不能并行执行但是self-attention可以。
    【NLP基础理论】10 上下文表示(Contextual Representation)_第45张图片
    但self-attention运算量大,所以目前方向就是提高运算速度,比如transformer(Efficient Transformers:A Survey)

至此,新知识都已经讲过了,哈哈就戛然而止,这一节课要拓展的内容实在太多了,其实应该就按照学校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
【NLP基础理论】10 上下文表示(Contextual Representation)_第46张图片

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

你可能感兴趣的:(ai,自然语言处理,nlp)