NLP之一文搞懂word2vec、Elmo、Bert演变

导读

自然语言处理本质是解决文本相关的问题,我们可以把它的任务分为大致两部分:预训练产生词向量以及对词向量进行操作(下游NLP具体任务)。在自然语言处理中有词向量模型word2vec、Elmo以及Bert等,也有RNN,LSTM等下游encoding模型,初学者很容易搞混,下面就分别介绍这几个模型之间的区别和联系,以及NLP技术的发展之路。

word2vec

1.原理

word2vec是一种编码方式,于2013年由google实验室提出,它的特点是将所有词表示成低位稠密向量,它解决了one-hot词袋编码的三个弊端:

  1. 编码过于稀疏,向量大小即词典大小
  2. 无法体现词在上下文中的关系
  3. 无法体现两个词之间的关系

word2vec原理是把一个词典大小的向量用几百维的向量进行编码,每一维都有其特定的含义,并且可以计算两两之间的相似度,得到king-man+woman=queen这种结果

2.训练方式

word2vec有两种训练方式:CBOW(Continuous Bag-of-Words)和Skip-gram,二者的区别在于:

  1. 若拿一个词语的上下文作为输入,来预测这个词语本身,那么该模型叫CBOW模型;
  2. 如果是用一个词语作为输入,来预测它周围的上下文,那么该模型叫做Skip-gram模型;
    二者的示意图分别如下:
    在这里插入图片描述
    在这里插入图片描述

3.算法流程

不论是CBOW还是skip-gram输入和输出都是类似的,流程如下:

  1. 输入一个单词,用one-hot表示,维度为: 1 × V 1 \times V 1×V,其中1表示一个输入单词,V表示词袋or词典大小。
  2. 随机初始化一个矩阵W,维度为 V × E V \times E V×E,其中V为词袋大小,E为人为设定的Embedding大小,通常为300-500维不等。用该one-hot表示乘以一个共享的输入权重矩阵W,(最终我们要拿到的就是这个权重矩阵W)得到中间结果: 1 × E 1 \times E 1×E
  3. 再随机初始化一个矩阵 W ′ W^{\prime} W,维度为 E × V E \times V E×V,得到输出 1 × V 1 \times V 1×V,即又回到了one-hot的表示形式
  4. 把上面的结果过一个softmax,使词典的每一个位置输出均为一个概率,且和为1。
  5. 用真实值标签和输出做交叉熵,反向传播即可。

4.反向传播

在反向传播的时候由于softmax计算量巨大,故提出两种可以大大降低计算量的方法:Hierarchical SoftmaxNegtive Sampling

Hierarchical Softmax

Hierarchical Softmax算法是按词频构建霍夫曼树,huffman树的特点是,高频词更靠近树根,因而找到它需要的时间(或着说,计算比较次数)更少。它将求解的计算量由 O ( V ) O(V) O(V)(V为词表大小)降到 O ( l o g 2 V ) O(log_{2}V) O(log2V),Hierarchical Softmax的缺点在于:如果中心词是一个很生僻的词,会在赫夫曼树中向下走很久。

负采样

由于训练词向量模型的目标不是为了得到一个多么精准的语言模型,而是为了获得它的副产物——词向量。所以要做到的不是在几万几十万个token中艰难计算softmax获得最优的那个词(就是预测的对于给定词的下一词),而只需能做到在几个词中找到对的那个词就行,这几个词包括一个正例(即直接给定的下一词),和随机产生的噪声词(采样抽取的几个负例),就是说训练一个sigmoid二分类器,只要模型能够从中找出正确的词就认为完成任务。

5.总结

在得到中间产物embedding矩阵 W W W后,可以查询每个单词对应的300-500维不等的词嵌入表示,下面就是下游NLP任务了,即针对不用的NLP任务,对得到的向量进行编码,利用RNN或者LSTM进行编码。下面有一个表格
在这里插入图片描述

6.缺点与不足

word2vec有一个很明显的缺点,即得到的词嵌入的向量是静态static的,即不同文章中的该词其词向量都是一样的。例如:“我从小就爱吃苹果”和“小明新买的苹果手机非常好用”,二者中的苹果在word2vec看来是一样的。这一点在Elmo模型中得到了解决。

Elmo

1.原理

Elmo(Embeddings from Language Models)于2018年3月份提出,该论文被评为NAACL18 Best Paper,它解决了2013年提出的Word2vec和2014年提出的Glove的每个词只对应一个词嵌入向量,对于多义词无能为力的问题,具体做法为ELMo训练的不再只是一个词向量,而是一个包含多层BiLstm的模型,然后对于每一个句子,都需要传入该模型,分别拿到每个时间步在每个层的输出,最后在下游具体的NLP任务中,再单独训练每一层的权重向量,对每一层的向量进行线性加权作为每个词汇的最终向量表示。这样一来,每个词汇在不同的上下文语境中,都可以得到不同的向量表示,因此,在一定意义上可以解决一词多义的问题。

2.结构

Elmo最大的改进就是它采用了双层双向LSTM模型,最终是把前向的结果和后向的结果进行拼接,最大化该似然概率。
这里介绍ELMo的两方面,一个是它的encoder模型Bi-LSTM,另一个是它和下游具体NLP任务的接口(迁移策略)。

Bi-LSTM做encoder实现上下文相关(context):

这里就是之前说的把下游具体NLP任务放到预训练产生词向量里面,从而达到获得一个根据context不同不断变化的dynamic词向量。具体实现方法是使用双向语言模型Bi-LSTM来实现,如下面左图所示。从前到后和后到前分别做一遍LSTM的encoding操作,从而获得两个方向的token联系,进而获得句子的context。

但这里有两个潜在问题,姑且称作“不完全双向”和“自己看见自己”。

首先,“不完全双向”是指模型的前向和后向LSTM两个模型是分别训练的,从图中也可以看出,对于一个序列,前向遍历一遍获得左边的LSTM,后向遍历一遍获得右边的LSTM,最后得到的隐层向量直接拼接得到结果向量(前向的hidden state1 + 后向的hidden state2 = 总的hidden state,+是concat),并且在最后的Loss function中也是前向和后向的loss function直接相加,并非完全同时的双向计算。

另外,“自己看见自己”是指要预测的下一个词在给定的序列中已经出现的情况。传统语言模型的数学原理决定了它的单向性。从公式
p ( s ) = p ( w 0 ) ⋅ p ( w 1 ∣ w 0 ) ⋅ p ( w 2 ∣ w 1 , w 0 ) ⋅ p ( w 3 ∣ w 2 , w 1 , w 0 ) … p ( w n ∣ c o n t e x t ) p(s) = p(w_{0}) · p(w_{1}|w_{0}) · p(w_{2}|w_{1},w_{0}) · p(w_{3}|w_{2},w_{1},w_{0}) \dots p(w_{n}|context) p(s)=p(w0)p(w1w0)p(w2w1,w0)p(w3w2,w1,w0)p(wncontext)
可以看出,传统语言模型的目标是获得在给定序列从头到尾条件概率相乘后概率最大的下一词,而双向模型会导致预测的下一词已经在给定序列中出现了的问题,这就是“自己看见自己”。如下面右图所示(图片从下往上看),最下行是训练数据A B C D,经过两个bi-lstm操作,需要预测某个词位置的内容。比如第二行第二列A|CD这个结果是第一层bi-lstm在B位置输出内容,包括正向A和反向CD,直接拼接成A|CD。比如第三行第二例ABCD这个结果是前向BCD和反向AB|D拼接结果,而当前位置需要预测的是B,已经在ABCD中出现了,这就会有问题。因而对于Bi-LSTM,只要层数增加,就是会存在“自己看见自己”的问题。

与下游具体NLP任务接口:

ELMo模型将context的encoding操作从下游具体NLP任务转换到了预训练词向量这里,但在具体应用时要做出一些调整。当bilstm有多层时,由于每层会学到不同的特征,而这些特征在具体应用中侧重点不同,每层的关注度也不同。ELMo的微调从严格意义上来说,不是真正的微调,预训练网络结果是fix的。 整体来说,是把句子输入到预训练网络的embedding,与下游任务word embedding做concat,concat的结果整体作为下游NLP任务的输出。
在这里插入图片描述
比如,原本论文中设定了两个隐层,第一隐层可以学到对词性、句法等信息,对此有明显需求的任务可以对第一隐层参数学到比较大的值;第二隐层更适合对词义消歧有需求的任务,从而分配更高权重。

下面是ELMo的比较表格。
在这里插入图片描述

优点和缺点

优点
  1. ELMo着重解决一词多义,相比较于传统的word2vec,仅能表达一种含义(词向量是固定的);
  2. ELMo生成的词向量利用了上下文的信息,根据下游任务,能够通过权值来调整词向量以适应不同任务;
缺点

Elmo采用的是LSTM作为特征提取器,而不是Transformer,后者已经被证明了在特征提取方面的效果是远好于LSTM的,并且Elmo采取双向拼接这种融合特征的能力可能比Bert一体化的融合特征方式弱。

BERT原理

Bert(Bidirectional Encoder Representation from Transformers)由google团队于2018年10月底公布,BERT模型进一步增加词向量模型泛化能力,充分描述字符级、词级、句子级甚至句间关系特征。其有三大亮点,分别为:

一、Masked LM——真正的双向encoding

Masked LM(原本叫cloze test),类似完形填空,尽管仍旧看到所有位置信息,但需要预测的词已被特殊符号代替,可以放心双向encoding。具体做法为:

随机mask掉语料中15%的token,然后将masked token位置输出的最终隐层向量送入softmax,来预测masked token。这样输入一个句子,每次只预测句子中大概15%的词,所以BERT训练很慢。示意图如下:
在这里插入图片描述
对于这15%被mask掉的词,即要预测的词,做三种特殊的处理。e.g:my dog is hairy

  • 有80%的概率用“[MASK]”标记来替换——my dog is [MASK]
  • 有10%的概率用随机采样的一个单词来替换——my dog is apple
  • 有10%的概率不做替换——my dog is hairy

二、Transformer做encoder实现上下文相关(context)

使用transformer而不是bi-LSTM做encoder,可以有更深的层数、具有更好并行性。并且线性的Transformer比lstm更易免受mask标记影响,只需要通过self-attention减小mask标记权重即可,而lstm类似黑盒模型,很难确定其内部对于mask标记的处理方式。

Transformer模型是2018年5月提出的,可以替代传统RNN和CNN的一种新的架构,用来实现机器翻译,论文名称是《attention is all you need》。无论是RNN还是CNN,在处理NLP任务时都有缺陷。CNN是其先天的卷积操作不很适合序列化的文本,RNN是其没有并行化,很容易超出内存限制(比如50tokens长度的句子就会占据很大的内存)。

下面左图是transformer模型一个结构,分成左边 N × N\times N×框框的encoder和右边 N × N\times N×框框的decoder,相较于传统RNN+attention常见的encoder-decoder之间的attention,还多出encoder和decoder内部的self-attention(即encoder和decoder内部的橙色框)。每个attention都有multi-head特征。最后,通过position encoding加入没考虑过的位置信息。
在这里插入图片描述
下面从multi-head attention,self-attention以及position encoding几个角度介绍Transformer。

A.multi-head attention

将一个词的vector切分成h个维度,求attention相似度时每个h维度单独计算。由于单词映射在高维空间作为向量形式,每一维空间都可以学到不同的特征,相邻空间所学结果更相似,相较于全体空间放到一起对应更加合理。比如对于 v e c t o r _ s i z e = 512 vector\_size=512 vector_size=512的词向量,取 h = 8 h=8 h=8,即每64个空间做一个attention,学到结果更细化。

B.self-attention

每个词位的词都可以无视方向和距离,有机会直接和句子中的每个词encoding。比如下图这个句子,每个单词和同句其他单词之间都有一条边作为联系,边的颜色越深表明联系越强,而一般意义模糊的词语所连的边都比较深。比如:Law、application,missing,opinion等等
在这里插入图片描述

C.position encoding:

因为Transformer既没有RNN的循环(recurrence)也没有CNN的卷积(convolution),但序列顺序信息很重要,比如明天你来我家吃饭明天我来你家吃饭意义完全不一样

一般的Transformer结构计算token的位置信息的时候使用正弦波,类似模拟信号传播周期性变化。即奇数位置是一套编码,偶数位置是另外一套编码,如下图公式所示。这样的循环函数可以一定程度上增加模型的泛化能力。
P E ( p o s , 2 i ) = s i n ( p o s / 1000 0 2 i / d m o d e l ) , 偶数位置 P E ( p o s , 2 i + 1 ) = c o s ( p o s / 1000 0 2 i / d m o d e l ) , 奇数位置 PE_{(pos,2i)} = sin(pos / 10000^{2i/d_{model}}),\text{偶数位置}\\ PE_{(pos,2i+1)} = cos(pos / 10000^{2i/d_{model}}),\text{奇数位置} PE(pos,2i)=sin(pos/100002i/dmodel),偶数位置PE(pos,2i+1)=cos(pos/100002i/dmodel),奇数位置

但BERT中的Transfomer没有这样做,它直接训练一个position embedding来保留位置信息,每个位置随机初始化一个向量,加入模型训练,最后就得到一个包含位置信息的embedding。最后这个position embedding和word embedding的结合方式上,BERT选择直接拼接

三、提升至句子级别

在很多任务中,仅仅靠encoding是不足以完成任务的(这个只是学到了一堆token级的特征,即word-level),还需要捕捉一些句子级的模式,来完成SLI、QA、dialogue等需要句子表示、句间交互与匹配的任务(即输入一个句子,找跟它匹配的其他句子)。对此,BERT又引入了另一个极其重要却又极其轻量级的任务,来试图把这种模式也学习到,即Sentence-level。

在这里插入图片描述

A.句子级负采样

句子级别的连续性预测任务,即预测输入BERT的两端文本是否为连续的文本。训练的时候,输入模型的第二个片段会以50%的概率从全部文本中随机选取(negative sampling),剩下50%的概率选取第一个片段的后续的文本(positive sampling)。 即首先给定的一个句子(相当于CBOW中给定context),它下一个句子即为正例(相当于word2vec中的正确词),随机采样一个句子作为负例(相当于word2vec中随机采样的词),然后在该sentence-level上来做二分类(即判断句子是当前句子的下一句还是噪声)。

B.句子级表示

在这里插入图片描述
BERT是一个句子级别的语言模型,不像ELMo模型在与下游具体NLP任务拼接时需要每层加上权重做全局池化,BERT可以直接获得一整个句子的唯一向量表示。它在每个input前面加一个特殊的记号[CLS],然后让Transformer对[CLS]进行深度encoding,由于Transformer是可以无视空间和距离的把全局信息encoding进每个位置的,而[CLS]的最高隐层作为句子/句对的表示直接跟softmax的输出层连接,因此其作为梯度反向传播路径上的“关卡”,可以学到整个input的上层特征。

C.segment embedding

对于句对来说,EA和EB分别代表左句子和右句子;对于句子来说,只有EA。这个EA和EB也是随模型训练出来的。

综上,最终输入结果会变成下面3个embedding拼接的表示,如下图所示。
在这里插入图片描述

BERT迁移策略——下游NLP具体任务

下游具体NLP任务主要分为4大类

  • 序列标注:分词、命名实体识别、语义标注
  • 分类任务:文本分类、情感分析
  • 句子关系判断:entailment、QA、自然语言推理
  • 生成式任务:机器翻译、文本摘要

BERT将传统大量在下游具体NLP任务中做的操作转移到预训练词向量中,在获得使用BERT词向量后,最终只需在词向量上加简单的MLP(Multilayer Perceptron,多层感知机)或线性分类器即可。比如论文中所给的几类任务:

在这里插入图片描述
对于(a)文本匹配和(b)文本分类任务(文本匹配其实也是一种文本分类任务,只不过输入是文本对)来说,只需要用得到的表示(即encoder在[CLS]词位的顶层输出)加上一层MLP就好。

要特殊说明的是,BERT无法做NLP第四类任务,即文本生成任务

  • 5
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值