bert 多义词_自然语言处理:从EMLo到Bert

2018年对NLP是非常重要的一年。2月份的时候,提出了ELMo,10月份,BERT出现。Jay Alammar称这是NLP的ImageNet时刻。

9c31799288533cc12a38703bdb7f52c3.png

在这之后,出现了

ae046c2d3548c337d2c9c02f9fccafca.png

什么是ImageNet呢?

张俊林:从Word Embedding到Bert模型—自然语言处理中的预训练技术发展史​zhuanlan.zhihu.com
dadbe3e33f212a21b36e14d9cee72104.png

一般在图像处理领域,喜欢用ImageNet来做网络的预训练,主要有两点,一方面ImageNet是图像领域里有超多事先标注好训练数据的数据集合,分量足是个很大的优势,量越大训练出的参数越靠谱;另外一方面因为ImageNet有1000类,类别多,算是通用的图像数据,跟领域没太大关系,所以通用性好,预训练完后哪哪都能用。

自从深度学习火起来后,预训练过程就是做图像或者视频领域的一种比较常规的做法,有比较长的历史了,而且这种做法很有效,能明显促进应用的效果。

c8d1f5448f0fc8c7e792884010943444.png

那么图像领域怎么做预训练呢,上图展示了这个过程,我们设计好网络结构以后,对于图像来说一般是CNN的多层叠加网络结构,可以先用某个训练集合比如训练集合A或者训练集合B对这个网络进行预先训练,在A任务上或者B任务上学会网络参数,然后存起来以备后用。假设我们面临第三个任务C,网络结构采取相同的网络结构,在比较浅的几层CNN结构,网络参数初始化的时候可以加载A任务或者B任务学习好的参数,其它CNN高层参数仍然随机初始化。之后我们用C任务的训练数据来训练网络,此时有两种做法,一种是浅层加载的参数在训练C任务过程中不动,这种方法被称为“Frozen”;另外一种是底层网络参数尽管被初始化了,在C任务训练过程中仍然随着训练的进程不断改变,这种一般叫“Fine-Tuning”,顾名思义,就是更好地把参数进行调整使得更适应当前的C任务。一般图像或者视频领域要做预训练一般都这么做。

这么做有几个好处,首先,如果手头任务C的训练集合数据量较少的话,现阶段的好用的CNN比如Resnet/Densenet/Inception等网络结构层数很深,几百万上千万参数量算起步价,上亿参数的也很常见,训练数据少很难很好地训练这么复杂的网络,但是如果其中大量参数通过大的训练集合比如ImageNet预先训练好直接拿来初始化大部分网络结构参数,然后再用C任务手头比较可怜的数据量上Fine-tuning过程去调整参数让它们更适合解决C任务,那事情就好办多了。这样原先训练不了的任务就能解决了,即使手头任务训练数据也不少,加个预训练过程也能极大加快任务训练的收敛速度,所以这种预训练方式是老少皆宜的解决方案,另外疗效又好,所以在做图像处理领域很快就流行开来。

那么新的问题来了,为什么这种预训练的思路是可行的?

72c6f6973d256f0597724012fdf65bc2.png

目前我们已经知道,对于层级的CNN结构来说,不同层级的神经元学习到了不同类型的图像特征,由底向上特征形成层级结构,如上图所示,如果我们手头是个人脸识别任务,训练好网络后,把每层神经元学习到的特征可视化肉眼看一看每层学到了啥特征,你会看到最底层的神经元学到的是线段等特征,图示的第二个隐层学到的是人脸五官的轮廓,第三层学到的是人脸的轮廓,通过三步形成了特征的层级结构,越是底层的特征越是所有不论什么领域的图像都会具备的比如边角线弧线等底层基础特征,越往上抽取出的特征越与手头任务相关。正因为此,所以预训练好的网络参数,尤其是底层的网络参数抽取出特征跟具体任务越无关,越具备任务的通用性,所以这是为何一般用底层预训练好的参数初始化新任务网络参数的原因。而高层特征跟任务关联较大,实际可以不用使用,或者采用Fine-tuning用新数据集合清洗掉高层无关的特征抽取器。

1e15d0dd2efb8a12013ddb77ad69bcab.png

那么大家一定会问下面这个问题:”既然图像领域预训练这么好用,那干嘛自然语言处理不做这个事情呢?“

NLP很早就尝试过了,不过总体而言不太成功而已。2003年提出的NNLM,word embedding其实就是NLP里的早期预训练技术。当然也不能说word embedding不成功,一般加到下游任务里,都能有1到2个点的性能提升。那么问题是,为什么这样训练及使用Word Embedding的效果没有期待中那么好呢?答案很简单,因为Word Embedding有问题呗。关键是Word Embedding存在什么问题?这其实是个好问题。

这片在Word Embedding头上笼罩了好几年的乌云是什么?是多义词问题。我们知道,多义词是自然语言中经常出现的现象,也是语言灵活性和高效性的一种体现。多义词对Word Embedding来说有什么负面影响?如下面的例子中所示,多义词Bank,有两个常用含义,但是Word Embedding在对bank这个单词进行编码的时候,是区分不开这两个含义的,因为它们尽管上下文环境中出现的单词不同,但是在用语言模型训练的时候,不论什么上下文的句子经过word2vec,都是预测相同的单词bank,而同一个单词占的是同一行的参数空间,这导致两种不同的上下文信息都会编码到相同的word embedding空间里去。所以word embedding无法区分多义词的不同语义,这就是它的一个比较严重的问题。

自从word2vec出现之后,人们提出了各种方法来解决这个问题,直到ELMO提供了一种简洁优雅的解决方案。

芝麻街中的三个人物:ELMo,BERT以及Ernie。

e384ebcd3d06fdcaf19feed7452e199d.png

NAACL 2018 Best Paper,文章提出了ELMo(Embeddings from Language Models)。文章一作Matthew Peters[1]现在在华盛顿大学的Allen 人工智能实验室任职,并且是AllenNLP 项目的领导人。AllenNLP[2]是一个基于PyTorch 的开源NLP 库,里面包含了数据与处理,模型训练及调用等模块。

https://arxiv.org/pdf/1802.05365.pdf​arxiv.org

word embedding 是现在自然语言处理中最常用的 word representation 的方法,常用的word embedding 是word2vec的方法,然而word2vec本质上是一个静态模型,也就是说利用word2vec训练完每个词之后,词的表示就固定了,之后使用的时候,无论新句子上下文的信息是什么,这个词的word embedding 都不会跟随上下文的场景发生变化,这种情况对于多义词是非常不友好的。例如英文中的 Bank这个单词,既有河岸的意思,又有银行的意思,但是在利用word2vec进行word embedding 预训练的时候会获得一个混合多种语义的固定向量表示。即使在根据上下文的信息能明显知道是“银行”的情况下,它对应的word embedding的内容也不会发生改变。

1c8d38b77861e071e1fda37b4b553b63.png

ELMO的提出就是为了解决这种语境问题,动态的去更新词的word embedding。ELMO的本质思想是:事先用语言模型在一个大的语料库上学习好词的word embedding,但此时的多义词仍然无法区分,不过没关系,我们接着用我们的训练数据(去除标签)来运行预训练好的ELMO 模型。

作者将这种称为domain transfer。这样利用我们训练数据的上下文信息就可以获得词在当前语境下的word embedding。

f0ca53b0dcbf465bb6b32a495f0e0e60.png

作者给出了ELMO 和Glove的对比

f482285c88538afa8a89e28cc0ea751b.png

  对于Glove训练出来的word embedding来说,多义词play,根据他的embedding 找出的最接近的其他单词大多数几种在体育领域,这主要是因为训练数据中包含play的句子大多数来源于体育领域,之后在其他语境下,play的embedding依然是和体育相关的。而使用ELMO,根据上下文动态调整后的embedding不仅能够找出对应的“表演”相同的句子,还能保证找出的句子中的play对应的词性也是相同的。接下来看看ELMO是怎么实现这样的结果的。

模型结构

ELMO 基于语言模型的,确切的来说是一个 Bidirectional language models,也是一个 Bidirectional LSTM结构。

双向语言模型(biLM)

给定

个token 的序列
,前向语言模型概率的表示方法通常如下:

(1),

类似地,后向语言模型概率的表示方法如下:

(2),

前向语言模型在前向模型中预测

的方式如下:首先计算上下文无关的token 表示
,然后将它传递通过前向LSTM 的
层。对于每个位置
,LSTM 层输出上下文相关的表示
,其中
。LSTM 的最上层输出
,通过连接一个softmax 层用来预测下一个token
的值。类似地,应用到后向模型中,给定
,可以通过
预测
的值。

那么, 这里设定第 j 层的第 k 个位置的forward LSTM(也就是右向LSTM)输出为

3a77dd55084162ae12c2ec988216bba0.png


那么, 左向就是

0bfb18333d3d2a5eabcdaf945b2650fb.png


Input, 也就是最原始的词向量为

33fac99801a33c065af5fbf4536daf05.png


那么, 这个最原始的词向量是怎么获得的呢?前面提到了, 是通过字符卷积, 大概是这个样子:

47f5b4a12731f054bb83ee9c19d9c656.png


BiLM 结合了前后向语言模型,有极大log 似然估计:

(3),

其中token 表示的参数

以及softmax 层参数
前后向是通用的,LSTM 的参数按照方向取不同值。

  模型的结构图如下:

f265a30bb166fd7a13f28b1be70daf01.png

ELMo 是task specific 上biLM 中间层表示的线性组合。基于此,我们应该认识到相比于word2vec 预训练的到的产物是词向量,这里的预训练产物是biLM,而ELMo 是最终根据task specific 学习得到的结果。

ae3818c9c154ea1396ec1c090b98c663.gif

如上层,Layer 1 和Layer 2 代表2个biLM 层,每一层由两个LSTM 层叠加在一起,用来表示前向和后向。训练的步骤如下:

  1. 用字符级别的CNN 表示的原始词向量;
  2. 在两层biLM 中进行计算,得到两个中间词向量;
  3. 对原始词向量和两个中间词向量加权平均,得到最终的ELMo。

因此ELMo 在训练时,对于每个token

,一个
层的biLM 可以计算得到
层的表示集合:

(4),

其中

为最顶层,对于每个biLSTM 层:

为了能够包含在下游的模型中,ELMo 将

中所有的层折叠为一个向量,有
。特别地,此时ELMo 只选择最上层,这时候
。更一般地,对所有biLM 层计算task specific 的权重:

(5),

其中

为softmax 标准化的权重,标量参数
允许任务模型将所有ELMo 向量按比例缩放,
合适的
对整个优化过程至关重要。由于每个biLM 层有着不同分布的激活,在某些情况下,在对biLM 层加权前使用Layer-Normalization 也能起到帮助。

其中,s就是softmax-normalized weights , 也就是加和为1的一组权重向量,这组权重不仅仅代表的是权重, 因为每层LSTM内部状态,也就是 h 的分布是不同的, 这个也可以用作layer normalization.

PS : 原文中有关获取s值的方法的描述很简单:
are softmax-normalized weights.

计算方法是: ​

因为这个
​是一个模型的参数,是独立于词向量的,也就是说不会随着输入词的改变而改变 . 所以应该不会以每层的隐藏状态作为输入(因为每层的隐藏状态会随着词向量改变). 所以, 在利用语言模型进行初始化的过程中, 应该会将每层中的s标志位设置为相同的值, 这样经过softmax转换后的值也是一样.

而, ​

允许具体的task模型去放缩 ELMo 的大小. 这个地方非常重要, 作者在补充中进行了强调, 在没有这个的情况下, 只采用该模型的最后一层输出作为词向量的时候的效果甚至差于 baseline。这个重要的原因是, BiLM的内部表征和具体任务的表征的分布是不一样的。

总结,ELMo使用双层BiLSTM来训练语言模型,创新是线性组合不同层的word vectors, 作为最终的word representation。核心公式:

  • 第一层是普通的word embedding 可以用wrod2vec或者glove来得到,或者使用character level得到token embedding》 这部分是general embedding,上下文无关。文中使用的character level的CNN+Highway.
  • 后面连接两个biLSTM 去encode 输入(同时也有残差连接), 每一层LSTM得到的输出(隐状态) 作为每个词的上下文相关的word vectors.
  • 这样每个词就会有(L+1)个词向量,L为biLSTM的层数.
  • 词向量的线性组合,针对不同的任务,不同层的向量做不同的权重加和。 其中权重s是一个维度为L的vector,参与训练。

因此ELMo的基本输入单元为句子,每个词没有固定的词向量,是根据词的上下文环境来动态产生当前词的词向量,常见的场景可以较好解决一词多义的问题,这一点跟word2vec与glove等通用词向量模型是不同的。

具体来看一下,ELMo的使用,准备ELMo模型向量

引入事先训练过的ELMo模型。请注意这个模型的大小超过350 mb所以可能需要一些时间来下载。

import tensorflow_hub as hub
import tensorflow as tf
elmo = hub.Module("https://tfhub.dev/google/elmo/2", trainable=True)

如何给一个句子生成ELMo向量,只需要将一列字符串输入elmo中:

# just a random sentence
x = ["Roasted ants are a popular snack in Columbia"]
# Extract ELMo features
embeddings = elmo(x, signature="default", as_dict=True)["elmo"]
embeddings.shape
Output: 
TensorShape([Dimension(1), Dimension(8), Dimension(1024)])

这个输出是一个三维张量(1, 8, 1024):

  • 第一个维度表示训练样本的数量,在这个案例中是1;
  • 第二个维度表示输入列表中的最大长度,因为我们现在只输入了一个字符串,所以第二个维度就是该字符串的长度8;
  • 第三个维度等于ELMo向量的长度。

输入中的每个词都有个长度为1024的ELMo向量。

$ ipython
> from allennlp.commands.elmo import ElmoEmbedder
> elmo = ElmoEmbedder()
> tokens = ["I", "ate", "an", "apple", "for", "breakfast"]
> vectors = elmo.embed_sentence(tokens)

> assert(len(vectors) == 3) # one for each layer in the ELMo output
> assert(len(vectors[0]) == len(tokens)) # the vector elements correspond with the input tokens

> import scipy
> vectors2 = elmo.embed_sentence(["I", "ate", "a", "carrot", "for", "breakfast"])
> scipy.spatial.distance.cosine(vectors[2][3], vectors2[2][3]) # cosine distance between "apple" and "carrot" in the last layer
0.18020617961883545

ELMo的效果如何呢?

4a9f3b8b78d54ed23b9aebc82aab6752.png

那么,ELMo的缺点是什么呢?

首先,一个非常明显的缺点在特征抽取器选择方面,ELMO使用了LSTM而不是新贵Transformer,Transformer是谷歌在17年做机器翻译任务的“Attention is all you need”的论文中提出的,引起了相当大的反响,很多研究已经证明了Transformer提取特征的能力是要远强于LSTM的。

另外一点,ELMO采取双向拼接这种融合特征的能力可能比Bert一体化的融合特征方式弱,但是,这只是一种从道理推断产生的怀疑,目前并没有具体实验说明这一点。“不完全双向”是指模型的前向和后向LSTM两个模型是分别训练的,从图中也可以看出,对于一个序列,前向遍历一遍获得左边的LSTM,后向遍历一遍获得右边的LSTM,最后得到的隐层向量直接拼接得到结果向量(前向的hidden state1 + 后向的hidden state2 = 总的hidden state,+是concat),并且在最后的Loss function中也是前向和后向的loss function直接相加,并非完全同时的双向计算。


从Word Embedding到GPT

GPT paper​s3-us-west-2.amazonaws.com

GPT 发表于2018年6月。

d2121a6c7ed413cf400936a0b15a1880.png

GPT是“Generative Pre-Training”的简称,从名字看其含义是指的生成式的预训练。GPT也采用两阶段过程,第一个阶段是利用语言模型进行预训练,第二阶段通过Fine-tuning的模式解决下游任务。上图展示了GPT的结构,其实和ELMO是类似的,主要不同在于两点:首先,特征抽取器不是用的RNN,而是用的Transformer的decoder;其次,GPT的预训练虽然仍然是以语言模型作为目标任务,但是采用的是单向的语言模型,所谓“单向”的含义是指:语言模型训练的任务目标是根据

单词的上下文去正确预测单词
之前的单词序列Context-before称为上文,之后的单词序列Context-after称为下文。ELMO在做语言模型预训练的时候,预测单词
同时使用了上文和下文,而GPT则只采用Context-before这个单词的上文来进行预测,而抛开了下文。这个选择现在看不是个太好的选择,原因很简单,它没有把单词的下文融合进来,这限制了其在更多应用场景的效果,比如阅读理解这种任务,在做任务的时候是可以允许同时看到上文和下文一起做决策的。如果预训练时候不把单词的下文嵌入到Word Embedding中,是很吃亏的,丢掉了一些信息。

fde2ac1d8dc4b08c01fe806912056eb3.png

上图展示了GPT在第二阶段如何使用。首先,对于不同的下游任务来说,本来你可以任意设计自己的网络结构,现在不行了,你要向GPT的网络结构看齐,把任务的网络结构改造成和GPT的网络结构是一样的。然后,在做下游任务的时候,利用第一步预训练好的参数初始化GPT的网络结构,这样通过预训练学到的语言学知识就被引入到你手头的任务里来了,这是个非常好的事情。再次,你可以用手头的任务去训练这个网络,对网络参数进行Fine-tuning,使得这个网络更适合解决手头的问题。

对于分类问题,不用怎么动,加上一个起始和终结符号即可;对于句子关系判断问题,比如Entailment,两个句子中间再加个分隔符即可;对文本相似性判断问题,把两个句子顺序颠倒下做出两个输入即可,这是为了告诉模型句子顺序不重要;对于多项选择问题,则多路输入,每一路把文章和答案选项拼接作为输入即可。从上图可看出,这种改造还是很方便的,不同任务只需要在输入部分施工即可。

GPT的效果是非常令人惊艳的,在12个任务里,9个达到了最好的效果,有些任务性能提升非常明显。

问题:

GPT为啥会用transformer中的decoder?

“自己看见自己”。是指要预测的下一个词在给定的序列中已经出现的情况。传统语言模型的数学原理决定了它的单向性。从公式

9000605b9242164125ab42184e2bdd0f.png

可以看出,传统语言模型的目标是获得在给定序列从头到尾条件概率相乘后概率最大的下一词,而双向模型会导致预测的下一词已经在给定序列中出现了的问题,这就是“自己看见自己”。如下图所示(图片从下往上看),最下行是训练数据A B C D,经过两个bi-lstm操作,需要预测某个词位置的内容。比如第二行第二列A|CD这个结果是第一层bi-lstm在B位置输出内容,包括正向A和反向CD,直接拼接成A|CD。比如第三行第二例ABCD这个结果是前向BCD和反向AB|D拼接结果,而当前位置需要预测的是B,已经在ABCD中出现了,这就会有问题。因而对于Bi-LSTM,只要层数增加,就是会存在“自己看见自己”的问题。

c105bd67f409be940b0417eb70f37c12.png

BERT(基于Transformer的双向编码器表示形式,(Bidirectional Encoder Representations from Transformers))是Google AI语言研究人员2018年9月发表的论文。

bert paper​arxiv.org

BERT的主要技术创新是将流行的注意力模型,Transformer的双向训练应用于语言建模。 这与以前的工作不同,之前的工作从左到右或从左到右和从右到左的训练的组合,来查看文本序列。 论文的结果表明,经过双向训练的语言模型比单向语言模型具有更深的语言背景和流程感。 在论文中,研究人员详细介绍了一种称为Masked LM(MLM)的新技术,该技术使得进行以前不可能进行双向训练。

BERT模型的结构如下图最左:

3a29ef7781ba56ccec8c3b650e1481ad.png

对比OpenAI GPT(Generative pre-trained transformer),BERT是双向的Transformer block连接;就像单向rnn和双向rnn的区别,直觉上来讲效果会好一些。

从上图可见,Bert其实和ELMO及GPT存在千丝万缕的关系,比如如果我们把GPT预训练阶段换成双向语言模型,那么就得到了Bert;而如果我们把ELMO的特征抽取器换成Transformer,那么我们也会得到Bert。所以可以看出:Bert最关键两点,一点是特征抽取器采用Transformer;第二点是预训练的时候采用双向语言模型。

对比ELMo,虽然都是“双向”,但目标函数其实是不同的。ELMo是分别以

作为目标函数,独立训练处两个representation然后拼接,而BERT则是以
作为目标函数训练LM。

BERT如何工作

BERT利用Transformer(一种注意力机制)来学习文本中单词(或子单词sub-word)之间的上下文关系。与单向模型相反,单向模型按顺序(从左到右或从右到左)读取文本输入,而Transformer编码器一次读取整个单词序列。因此,尽管说它是非方向性(non-directional)的更为准确,但它被认为是双向的。此特征使模型可以根据单词的所有周围环境(单词的左右)来学习单词的上下文。

下图是对Transformer编码器的上层描述。输入是一系列token,这些token首先进行词向量嵌入,然后在神经网络中进行处理。输出是大小为H的向量序列,其中每个向量对应于具有相同索引的输入token。

“We’ll use transformer encoders”, said BERT.
“This is madness”, replied Ernie, “Everybody knows bidirectional conditioning would allow each word to indirectly see itself in a multi-layered context.”
“We’ll use masks”, said BERT confidently.

以下是BERT论文的思路:

假如给一个句子 “能实现语言表征[mask]的模型”,遮盖住其中“目标”一词。从前往后预测[mask],也就是用“能/实现/语言/表征”,来预测[mask];或者,从后往前预测[mask],也就是用“模型/的”,来预测[mask],称之为单向预测 unidirectional。单向预测,不能完整地理解整个语句的语义。于是研究者们尝试双向预测。把从前往后,与从后往前的两个预测,拼接在一起 [mask1/mask2],这就是双向预测 bi-directional。 BERT 的作者认为,bi-directional 仍然不能完整地理解整个语句的语义,更好的办法是用上下文全向来预测[mask],也就是用 “能/实现/语言/表征/../的/模型”,来预测[mask]。BERT 作者把上下文全向的预测方法,称之为 deep bi-directional。如何来实现上下文全向预测呢?BERT 的作者建议使用 Transformer 模型。 这个模型的核心是聚焦机制,对于一个语句,可以同时启用多个聚焦点,而不必局限于从前往后的,或者从后往前的,序列串行处理。不仅要正确地选择模型的结构,而且还要正确地训练模型的参数,这样才能保障模型能够准确地理解语句的语义。BERT 用了两个步骤,试图去正确地训练模型的参数。第一个步骤是把一篇文章中,15% 的词汇遮盖,让模型根据上下文全向地预测被遮盖的词。假如有 1 万篇文章,每篇文章平均有 100 个词汇,随机遮盖 15% 的词汇,模型的任务是正确地预测这 15 万个被遮盖的词汇。通过全向预测被遮盖住的词汇,来初步训练 Transformer 模型的参数。 然后,用第二个步骤继续训练模型的参数。譬如从上述 1 万篇文章中,挑选 20 万对语句,总共 40 万条语句。挑选语句对的时候,其中 2 10 万对语句,是连续的两条上下文语句,另外 210 万对语句,不是连续的语句。然后让 Transformer 模型来识别这 20 万对语句,哪些是连续的,哪些不连续。

在训练语言模型时,定义预测目标存在挑战。许多模型会按顺序预测下一个单词(例如“孩子从___回家”),这是一种定向方法,从本质上限制了上下文学习。为了克服这一挑战,BERT使用了两种训练策略:

在将单词序列送入BERT之前,每个序列中15%的单词被替换为[MASK] token。 然后,模型会根据序列中其他未屏蔽单词提供的上下文,尝试预测被屏蔽单词的原始值。 用技术术语来说,输出单词的预测需要:

  1. 在编码器输出的顶部添加分类层。
  2. 将输出向量乘以嵌入矩阵,将其转换为相应的维度。
  3. 用softmax计算词汇中每个单词的概率。

具体看一下:

bd3351dbc3004a72141aa87bd22db2af.png

BERT损失函数仅考虑被屏蔽词的预测,而忽略非屏蔽词的预测。 结果,该模型的收敛速度比方向模型慢,不过这一特征被上下文感知能力的提高所抵消。

虽然这确实能让团队获得双向预训练模型,但这种方法有两个缺点。首先,预训练和fine-tuning之间不匹配,因为在fine-tuning期间从未看到[MASK]token。为了解决这个问题,团队并不总是用实际的[MASK]token替换被“masked”的词汇。相反,训练数据生成器随机选择15%的token。例如在这个句子“my dog is hairy”中,它选择的token是“hairy”。然后,执行以下过程: 数据生成器将执行以下操作,而不是始终用[MASK]替换所选单词:

80%的时间:用[MASK]标记替换单词,例如,my dog is hairy → my dog is [MASK] 10%的时间:用一个随机的单词替换该单词,例如,my dog is hairy → my dog is apple 10%的时间:保持单词不变,例如,my dog is hairy → my dog is hairy. 这样做的目的是将表示偏向于实际观察到的单词。

导致作者选择这种方法的原因如下:

  • 如果我们100%地使用[MASK],则该模型不一定会为非屏蔽词产生良好的标记表示形式。非屏蔽token仍用于上下文,但是该模型优化用于预测屏蔽词。
  • 如果我们90%地情况中使用[MASK],而有10%的时间使用随机单词,则模型会学到它观察到的单词永远是不正确的。
  • 如果我们90%的时间使用[MASK],而10%的时间使用相同的单词,则该模型可以简单地复制非上下文嵌入。

因为没有对这个比率进行消融测试,所以有可能在不同比率下可能效果更好。此外,模型性能并未进行简单地屏蔽100%所选令牌的测试。

Transformer encoder不知道它将被要求预测哪些单词或哪些单词已被随机单词替换,因此它被迫保持每个输入token的分布式上下文表示。此外,因为随机替换只发生在所有token的1.5%(即15%的10%),这似乎不会损害模型的语言理解能力。

使用MLM的第二个缺点是每个batch只预测了15%的token,这表明模型可能需要更多的预训练步骤才能收敛。团队证明MLM的收敛速度略慢于 left-to-right的模型(预测每个token),但MLM模型在实验上获得的提升远远超过增加的训练成本。

下一句预测(NSP)

在BERT训练过程中,模型接收成对的句子作为输入,并学习预测成对的第二个句子是否是原始文档中的后续句子。在训练期间,输入的50%是一对,其中第二个句子是原始文档中的后续句子,而在其他50%的输入中,从语料库中选择一个随机句子作为第二个句子。假定随机句子将与第一句断开。

为了帮助模型区分训练中的两个句子,在输入模型之前,将以以下方式处理输入:

  1. 在第一个句子的开头插入一个[CLS]令牌,在每个句子的末尾插入一个[SEP]令牌。
  2. 将指示句子A或句子B的句子嵌入添加到每个标记。句子嵌入的概念类似于词汇量为2的令牌嵌入。

将位置嵌入添加到每个令牌以指示其在序列中的位置。 Transformer论文介绍了位置嵌入的概念和实现。

7abe678abe047c67d466c70cb3b21122.png

举例来看

02375032085aabaa5a2df70c39f3ba9a.png

Bert特征抽取

9eafb5b9054096c51e0c6620aefe5839.png

哪个向量最适合作为上下文嵌入? 这取决于任务。 论文研究了六个选择(与经过微调的模型相比,得分为96.4):

a0595339444c3ee09cbd9dd9977539b9.png

如何使用BERT(fine-tuning)

使用BERT完成特定任务相对简单:

BERT可用于多种语言任务,而仅在核心模型中添加一小层:

  • 通过在[CLS]令牌的Transformer输出顶部添加分类层,可以类似于Next Sentence分类来完成诸如情感分析之类的分类任务。
  • 在问答任务(例如SQuAD v1.1)中,软件会收到有关文本序列的问题,并需要在序列中标记答案。使用BERT,可以通过学习两个标记答案开头和结尾的额外矢量来训练问答模型。
  • 在命名实体识别(NER)中,该软件会接收文本序列,并且需要标记文本中出现的各种类型的实体(人,组织,日期等)。使用BERT,可以通过将每个令牌的输出向量馈入预测NER标签的分类层来训练NER模型。

具体例子:

对BERT模型的观点

  1. high-performance的原因其实还是归结于两点,除了模型的改进,更重要的是用了超大的数据集(BooksCorpus 800M + English Wikipedia 2.5G单词)和超大的算力(对应于超大模型)在相关的任务上做预训练,实现了在目标任务上表现的单调增长
  2. 这个模型的双向和Elmo不一样,Elmo是拼一个左到右和一个右到左,bert是训练中直接开一个窗口。
  3. 可复现性差:有钱才能为所欲为(Reddit对跑一次BERT的价格讨论)
 For TPU pods:  
 4 TPUs * ~$2/h (preemptible) * 24 h/day * 4 days = $768 (base model)   
16 TPUs = ~$3k (large model)       

For TPU:   
16 tpus * $8/hr * 24 h/day * 4 days = 12k   
64 tpus * $8/hr * 24 h/day * 4 days = 50k

补充

在Bert的论文中提到了Feature-based和Fine-tune这两种无监督的NLP学习方法,其中ELMo是feature-based,而GPT和Bert都是属于fine-tuning的。两者的特点在[14]中介绍的比较清楚。

Feature-based

Feature-based指利用语言模型的中间结果也就是LM embedding, 将其作为额外的特征,引入到原任务的模型中,例如在TagLM中,采用了两个单向RNN构成的语言模型,将语言模型的中间结果

a3e66401b17b61150935c5842896c8b7.png

引入到序列标注模型中,如下图所示,其中左边部分为序列标注模型,也就是task-specific model,每个任务可能不同,右边是前向LM(Left-to-right)和后向LM(Right-To-Left), 两个LM的结果进行了合并,并将LM embedding与词向量、第一层RNN输出、第二层RNN输出进行了concat操作。

0bc3b76ba67601ae02f5588bd0f52927.png

feature-based只变化了最后一层的参数。

通常feature-based方法包括两步:

  1. 首先在大的语料A上无监督地训练语言模型,训练完毕得到语言模型
  2. 然后构造task-specific model例如序列标注模型,采用有标记的语料B来有监督地训练task-sepcific model,将语言模型的参数固定,语料B的训练数据经过语言模型得到LM embedding,作为task-specific model的额外特征

ELMo是这方面的典型工作。

Fine-tune

Fine-tuning方式是指在已经训练好的语言模型的基础上,加入少量的task-specific parameters, 例如对于分类问题在语言模型基础上加一层softmax网络,然后在新的语料上重新训练来进行fine-tune。除了最后一层,所有的参数都变化了。

例如OpenAI GPT 中采用了这样的方法,模型如下所示

ed6d99fa1de334077e2d0c99472f6356.png

首先语言模型采用了Transformer Decoder的方法来进行训练,采用文本预测作为语言模型训练任务,训练完毕之后,加一层Linear Project来完成分类/相似度计算等NLP任务。因此总结来说,LM + Fine-Tuning的方法工作包括两步:

  1. 构造语言模型,采用大的语料A来训练语言模型
  2. 在语言模型基础上增加少量神经网络层来完成specific task例如序列标注、分类等,然后采用有标记的语料B来有监督地训练模型,这个过程中语言模型的参数并不固定,依然是trainable variables.

in the fine-tuning strategy all weights are changed when training on the new task (except for the weights of the last layers for the original task), whereas in the feature extraction strategy only the weights of the newly added last layers change during the training phase:

参考:

  1. https://posts.careerengine.us/p/5d1437a6fe4add4da6190da5
  2. https://towardsdatascience.com/bert-explained-state-of-the-art-language-model-for-nlp-f8b21a9b6270
  3. https://zhuanlan.zhihu.com/p/76714382
  4. https://jalammar.github.io/a-visual-guide-to-using-bert-for-the-first-time/
  5. https://jalammar.github.io/illustrated-bert/
  6. https://zhuanlan.zhihu.com/p/49271699
  7. https://www.cnblogs.com/jiangxinyang/p/10060887.html
  8. https://zhuanlan.zhihu.com/p/46652512
  9. https://mccormickml.com/2019/05/14/BERT-word-embeddings-tutorial/
  10. https://gluon-nlp.mxnet.io/examples/sentence_embedding/bert.html 【bert使用】
  11. https://cloud.tencent.com/developer/article/1458629
  12. https://github.com/allenai/allennlp/blob/master/docs/tutorials/how_to/elmo.md
  13. https://www.cnblogs.com/jiangxinyang/p/10235054.html
  14. https://blog.csdn.net/sinat_25394043/article/details/104308576
  15. https://gluon-nlp.mxnet.io/examples/sentence_embedding/elmo_sentence_representation.html 【Elmo使用】
  16. https://zhuanlan.zhihu.com/p/70257427 【xlnet的mask】

参考

  1. ^https://www.linkedin.com/in/petersmatthew/
  2. ^https://allennlp.org/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值