Task 4: Contextual Word Embeddings (附代码)(Stanford CS224N NLP with Deep Learning Winter 2019)

Task 4: Contextual Word Embeddings


理论部分:

  • 回顾 Word2Vec, GloVe, fastText 模型
  • 介绍contextual word representation
  • 介绍 ELMO,GPT与BERT模型

在这里插入图片描述

词向量的表示

  目前为止,我们已经学过了Word2vec, GloVe, fastText等词向量的表示。通过这些词向量能在神经网络的训练中起到一个很好的效果,如图所示:

在这里插入图片描述
  但是这三个方法都普遍存在在一些问题,就是无法解决一词多义的问题,即对于同一个词无论上下文的词是否相同,训练出来的词向量都是一样的
  当我们语料不足时,训练出来的词向量效果不会很理想,这时我们可以使用其他人已经训练好的词向量,并且以预训练的词向量来作为初始值,在训练过程中进行微调。下图是2011年Collobert, Weston等人使用预训练的词向量进行NLP任务的精度和F1值,模型使用了预训练词向量之后,得分得到了提升:

在这里插入图片描述
  但是,我们训练好的词向量是不可能涵盖所有词的(这里主要有两个原因,一是训练语料中本来就不存在这些词,二是这些词在训练语料中出现次数过少),这就会存在一个未知词(unknown words)的问题,遇到这个问题的时候我们怎么处理呢?
  常见的解决方案是:

  • 首先,最简单和最普遍的解决方法就是将所有未知词映射为,并且为它训练一个词向量。但是这种方法存在缺点,它把这些未知词都视为相同,不能区分它们的区别。
  • 训练字符级词向量
  • 此外,你可以将其视为新的词,并为其分配一个随机向量,将它们添加到你的词汇表。

  不过,对于这样的解决方案存在着一定的问题,即:我们没有办法区分不同的unknown words。此外,还有一些问题,比如词向量唯一表示词而不考虑词在文章中出现的位置,比如一个词在不同的句子中有不同的含义等。
  针对这些问题,有人想到词向量表示应该结合词所在的句子进行考虑。但是标准的RNN训练只在 task-labeled 的小数据上,后来有人想能不能用词向量的编码,比如LSTM的编码来表示单词,并且在大型的无标签的数据上进行训练,于是就产生了Contextual Word Representations。如图:

在这里插入图片描述

一、Peters et al. (2017): TagLM – “Pre-ELMo”

论文地址:https://arxiv.org/pdf/1705.00108.pdf

  核心思想:通过上下文中获取单词的含义,但只在task-labeled的任务(例如,NER)上使用RNN来进行训练算法的核心步骤如下:

  • 在未标记的数据上预训练词向量和语言模型
  • 在输入序列中准备好单词嵌入和语言模型嵌入。
  • 在序列标记模型中同时使用单词嵌入和语言模型嵌入。

  模型结构图如下:

扫描二维码关注公众号,回复: 11573998 查看本文章

在这里插入图片描述
  详细的过程如图所示:

在这里插入图片描述
  论文得出的结论如下:

  • 通过对语言模型观察我们得出:使用有监督数据集来训练的语言模型效果甚微,使用双向语言模型仅对向前有利,网络结构越复杂效果越好。
  • 通过对任务特定Bi-LSTM观察可知:仅使用LM嵌入来预测并不好。

二、Peters et al. (2018): ELMo: Embeddings from Language Models

论文名称及地址:
Deep contextualized word representations. NAACL 2018.
https://arxiv.org/abs/1802.05365

  在2018年,Peters等人提出的ELMo模型在非常多的NLP任务上都提高了state-of-the-art 方法的performance, 被一些人称为新的word2vec。这篇文章同时被ICLR 2018 和NAACL 2018 接收, 后来获得了NAACL best paper award
  ELMo是第一个使用双向语言模型来获得词向量的方法。这里使用长上下文而不是上下文窗口学习词标记向量,使用双向的深层NLM进行训练并使用其所有层进行预测。
  我们来简要介绍下这个模型:首先,它训练了一个双向的语言模型,其次,其性能很好并且模型不大。具体步骤——使用2个Bi-LSTM层,使用字符级的CNN建立初始单词表示(2048 char n-gram过滤器和2个HighWay层,512 dim投影),使用4096 dim hidden/cell LSTM状态,512dim投影到下一个输入,使用残差网络连接token输入和输出(SoftMax)的参数,并将这些参数连接在正向和反向语言模型之间。
  具体如图所示:

在这里插入图片描述
  ELMo模型一个比较重要的特点是,它不仅使用了LSTM最上面的一层隐藏层,也使用其他隐藏层,对所有的隐藏层做一个权重的求和,得到ebeding的结果,公式如图所示:

在这里插入图片描述
  使用ELMo完成task

  1. 首先,预训练bi-LM模型得到单词的 representations
  2. 冻结上一步得到的bi-LM的参数
  3. 将得到的ELMo权重应用于特定的任务

  以下给出了将ELMo模型应与sequence tagger任务,如图所示:

在这里插入图片描述
  ELMo模型在NLP的很多应用都取得很好的效果,对普通的基准模型,应用了ELMo后,都取得了一定水平的提升,如图所示:

在这里插入图片描述
  ELMo的bi-LSTM NLM层各有特点,也适合不同的NLP任务:低层的权重更适合低层次的语法任务,比如词性标注、句法依赖、NER等;高层的权重更适合层次更好的语义任务,比如情感分析、语义角色标注、问答、SN等

三、ULMfit

论文名称及地址:
Deep contextualized word representations. NAACL 2018.
https://arxiv.org/abs/1802.05365

  Howard and Ruder (2018)提出了== Universal Language Model Fine-tuning for Text Classification==。ULMfit主要是使用迁移学习来进行文本分类迁移学习示意图如下:

在这里插入图片描述
  对于模型的处理,UML采用了如下三步:

  1. 首先,在一个非常大的数据集(和任务数据集不相关)上训练一个LM模型。
  2. 接着,使用任务相关的数据集,对模型进行fine-tune(进行训练,在前一个模型的基础上对参数进行微调)
  3. 使用classifier任务继续fine-tune

  模型结构图如下:

在这里插入图片描述
  ULMfit取得的效果也非常的明显,如图:

在这里插入图片描述
  该模型在训练时有一些细节:

  • 每层使用不同的学习率,即Slanted triangular learning rate (STLR) schedule,开始学习率逐渐增大,后面逐渐变小
  • 在学习分类器时逐步解冻并且采用STLR策略
  • 分类时使用下图拼接的方法:
    在这里插入图片描述

  这其中迁移学习的方法在NLP中开了一个头,从此网络越来越复杂,训练的规模也越来越大
在这里插入图片描述

四、Transformer

  transformer的出现主要是为了利用纯attention来解决RNN系列网络无法并行计算的问题模型结构图如下所示:
在这里插入图片描述

  • 使用非循环结构的encoder-decoder模型
  • 可以进行并行的机器翻译的计算
  • 预测每一个翻译的word
  • 代价函数是标准的softmax输出下的交叉熵代价函数

如果我们要详细地了解transformer,可以参考下面地资源:
http://nlp.seas.harvard.edu/2018/04/03/attention.html
这是一个使用pytorch在jupyter notebook上来解释transformer的教程。

  我们从图中可以看到:和大多数seq2seq模型一样,transformer的结构也是由encoder和decoder组成。最初应用于使用并行语料库进行机器翻译并预测每个单词的翻译。

1.Encoder

  Encoder由N=6个相同的layer组成,layer指的就是上图左侧的单元,最左边有个“Nx”,这里是x6个。每个Layer由两个sub-layer组成,分别是multi-head self-attention mechanism和fully connected feed-forward network。其中每个sub-layer都加了residual connection和normalisation,因此可以将sub-layer的输出表示为:

在这里插入图片描述
  首先我们先看一下Multi-head self-attention。对于普通的attention机制,可以用以下形式表示:

在这里插入图片描述
  multi-head attention则是通过h个不同的线性变换对Q,K,V进行投影,最后将不同的attention结果拼接起来并通过线性层传输,可以用以下公式表达:

在这里插入图片描述
  与CNN和传统的Attention相比,Multi-head attention还是有很多特性的。下面以这句话为例子:The cat stuck out its tongue and licked its owner当使用CNN处理这段话时,体现的是相对位置的不同线性变换。

在这里插入图片描述
  当使用普通的Attention时,体现的是权重的平均,如下图所示:

在这里插入图片描述
  当使用Multi-Attention时,在输入和输出上具有不同线性变换的并行行Attention层,如下图所示:

在这里插入图片描述
  其次是Position-wise feed-forward networks。这层主要是提供非线性变换。

2.Decoder

  Decoder和Encoder的结构差不多,但是多了一个attention的sub-layer,这里先明确一下decoder的输入输出和解码过程:

  • 输入:encoder的输出和对应i-1位置decoder的输出。所以中间的attention不是self-attention,它的K,V来自encoder,Q来自上一位置decoder的输出
  • 输出:对应i位置的输出词的概率分布
  • 解码:这里要特别注意一下,编码可以并行计算,一次性全部encoding出来,但解码不是一次把所有序列解出来的,而是像RNN一样一个一个解出来的,因为要用上一个位置的输入当作attention的query

  明确了解码过程之后最上面的图就很好懂了,这里主要的不同就是新加的另外要说一下新加的attention多加了一个mask,因为训练时的output都是ground truth,这样可以确保预测第i个位置时不会接触到未来的信息。

3.Positional Encoding

  截止目前为止,我们介绍的Transformer模型并没有捕捉顺序序列的能力,也就是说无论句子的结构怎么打乱,Transformer都会得到类似的结果。换句话说,Transformer只是一个功能更强大的词袋模型而已
  为了解决这个问题,论文中在编码词向量时引入了位置编码(Position Embedding)的特征。具体地说,位置编码会在词向量中加入了单词的位置信息,这样Transformer就能区分不同位置的单词了。那么怎么编码这个位置信息呢?常见的模式有:a. 根据数据学习;b. 自己设计编码规则。在这里作者采用了第二种方式。那么这个位置编码该是什么样子呢?通常位置编码是一个特征向量,这样便于和词向量进行单位加的操作。论文给出的编码公式如下:

在这里插入图片描述
  在上式中,pos表示单词的位置,i表示单词的维度。关于位置编码的实现可在Google开源的算法中get_timing_signal_1d()函数找到对应的代码。
  作者这么设计的原因是考虑到在NLP任务重,除了单词的绝对位置,单词的相对位置也非常重要。根据公式sin(α+β)=sinαcosβ+cosαsinβ以及cos(α+β)=cosαcosβ-sinαsinβ,这表明位置k+p的位置向量可以表示为位置k的特征向量的线性变化,这为模型捕捉单词之间的相对位置关系提供了非常大的便利。
  Transformer是第一个用纯attention搭建的模型,算法的并行性非常好,并且在翻译任务上也获得了更好的结果,因此Transformer也可以用在NLP的其他任务上。但是,Transformer一味的去除掉了RNN,因此RNN和Transformer的结合也许会更好

五、BERT

论文地址: https://arxiv.org/abs/1810.04805

  Bert模型是Google在2018年10月发布的语言表示模型,全称:Bidirectional Encoder Representations from Transformers,它采用双向的transformer结构,进行Encoder Representations。Bert在NLP领域横扫了11项任务的最优结果,可以说是最近NLP中最重要的突破。
  语言模型通常是单向的,通常由左到右或者从右到左进行,但是语言的理解通常是一个双向的过程。所以需要建立一个双向的网络,但是通常的双向编码是会造成Words “see themselves”,如图所示:

在这里插入图片描述
  这样会造成上层进行编码的效果不是很好,针对这个问题,BERT在预训练时,对数据进行mask操作,如图所示:

在这里插入图片描述
  BERT模型的目标是利用大规模无标注语料训练、获得文本的包含丰富语义信息的Representation,即:文本的语义表示,然后将文本的语义表示在特定NLP任务中作微调,最终应用于该NLP任务

在这里插入图片描述
  BERT模型的主要输入是文本中各个字/词的原始词向量,该向量既可以随机初始化,也可以利用Word2Vector等算法进行预训练以作为初始值;输出是文本中各个字/词融合了全文语义信息后的向量表示
  BERT将多个transformer编码器堆叠在一起。BERT卓越的性能基于两点。首先创新预训练任务Masked Language Model (MLM)以及Next Sentence Prediction (NSP);其次训练BERT使用了大量数据和算力
  MLM使得BERT能够从文本中进行双向学习,也就是说这种方式允许模型从单词的前后单词中学习其上下文关系。此前的模型这是做不到的。此前最优的算法称为Generative Pre-training (GPT) ,该方法采用了从左到右的训练方式,另外ELMo 采用浅双向学习(shallow bidirectionality)
 &emsp**;BERT和ELMo和GPT三种结构**如图所示:

在这里插入图片描述
  ELMo采用的是双向的LSTM,GPT采用的是单向的transformer,BERT采用的是双向的transformer
  BERT complication: Next sentence prediction:BERT为了在预训练是更好的获得句子间的关系,不仅仅进行mask词汇的预测,还预测句子,预测一句子是否会紧挨着另外一个句子出现,如图所示:

在这里插入图片描述
  sentence pair encoding:BERT提供了多种encoding的方式,如图所示:

在这里插入图片描述
  Bert只学习一个建立在顶层的分类器,微调每个任务,如图所示:

在这里插入图片描述
  而近日,百度提出知识增强的语义表示模型== ERNIE==(Enhanced Representation from kNowledge IntEgration),并发布了基于 PaddlePaddle 的开源代码与模型,在语言推断、语义相似度、命名实体识别、情感分析、问答匹配等自然语言处理(NLP)各类中文任务上的验证显示,模型效果全面超越 BERT。由此可以看出,预训练模型已成为近来NLP领域的潮流

六、补充知识点:GPT

1.OpenAI GPT(开放式GPT)

论文地址:
Improving Language Understanding by Generative Pre-Training(Radford等人,2018年)
https://s3-us-west-2.amazonaws.com/openai-assets/research-covers/language-unsupervised/language_understanding_paper.pdf

  与ELMo的想法类似,OpenAI GPT,Generative Pre-training Transformer的缩写,通过在大量免费文本语料库上进行训练,将无监督语言模型扩展到更大的规模。

1)OpenAI GPT

  GPT与ELMo有两个主要区别:

  • 模型体系结构不同:ELMO模型通过独立训练的从左到右和从右到左多层LSTMs的简单级联构成,而GPT是一个多层单向的Transformer
    decoder。
  • 在下游任务使用带上下文信息的Embedding的方式不同:ELMO需要为特定的任务训练特定模型,然后把embedding当作特征提供给特地任务使用,而GPT对所有任务都是相同的模型。

2)Transformer decoder作为语言模型

  与传统的Transformer架构相比,Transformer解码器模型丢弃了encoder部分,因此模型只有一个输入。输入句子embedding经过多层Transfomer处理。每一层都由一个multi-head self-attention层和一个pointwise feed-forward层构成。最终经过softmax层输出在目标词条上的概率分布。

在这里插入图片描述
  Loss是负对数似然度(negative log-likelihood),与ELMO相同,但没有反向计算(序列从后往前的计算)。比方说,k大小的上下文窗口位于目标单词之前,损失如下:
在这里插入图片描述

3)BPE(Byte Pair Encoding)

 &emsp**;字节对编码(BPE)用于编码输入序列。 BPE最初在20世纪90年代被提出作为数据压缩算法,然后被用来解决机器翻译中的开放词汇问题**,因为在翻译成新语言时很容易遇到罕见和未知的单词。受到由于稀有和未知单词通常可以分解为多个子词的情况所启发,BPE通过迭代和贪婪地合并频繁的字符对来找到最佳的单词分词。

4)有监督的微调

  OpenAI GPT提出的最实质性的升级是摆脱task-specific模型,直接使用预先训练的语言模型!
  以分类为例。比方说,在带标签的数据集中,每个输入都有n个标签,x=(x1,…,xn),还有一个标签y。GPT首先通过预先训练的Transformer解码器处理输入序列x,最后一个tokenxn的最后一层输出是hL(n)。然后,只有一个新的可训练权重矩阵Wy,它可以预测类别标签上的分布。

在这里插入图片描述
  Loss是最小化真实标签的负对数似然度。此外,添加LMloss作为辅助loss被认为是有益的,因为:

  • 它有助于在训练期间加快收敛速度。
  • 有望提高监督模型的泛化能力。

在这里插入图片描述
  基于类似的设计,对于其他任何下游任务不需要更改网络结构。如果任务输入包含多个句子,则在每对句子之间添加一个特殊的分隔符( $ )。这个定界符标签的embedding是一个我们需要学习的新参数,但是它应该非常小。
  对于句子相似性任务,因为排序无关紧要,所以两个排序都包括在内。对于多项选择任务,上下文与每个答案候选项配对

在这里插入图片描述

5)总结

  OpenAI GPT在第一阶段,语言模型的生成性预训练可以吸收尽可能多的自由文本(free text)。然后在第二个阶段,利用小的带标注数据集和一组最小的新参数对模型进行微调,以适应特定的任务
  GPT的一个局限性是它的单向特性—该模型只被训练来预测未来left-to-right context,这限制了GPT的学习能力。

2.OpenAI GPT-2

论文地址: Language Models are Unsupervised Multitask Learners
https://d4mucfpksywv.cloudfront.net/better-language-models/language_models_are_unsupervised_multitask_learners.pdf

  OpenAI GPT-2语言模型是GPT的直接继承者。与GPT-2与GPT-1相比,模型结构基本一致,任然采用多层单向Transformer模型,主要是在训练数据方面有很大不同

  • 数据量更大、更广泛的训练数据,Reddit上抓取了800万各种类型的数据。
  • 对训练数据进行筛选,选择更高质量的数据训练网络。
  • GPT-2层数增加一倍,有1.5B的参数,比原始GPT多10倍,并且在Zero-Shot Transfer场景下,在8个测试语言建模数据集中的7个数据集上,获得了SOTA结果。
  • 一些细微的网络结构上的修改。

  正是因为拥有了更加丰富、更大量的训练数据,模型结构也比GPT-1更加复杂,学习到的Feature更加广泛和准确。因此,OpenAI GPT-2的巨大改进在小数据集和用于测量长期相关性的数据集上尤为显著

1)Zero-Shot Transfer

  GPT-2的预训练任务仅仅包含第一步预训练语言模型。所有下游语言任务都被构建为预测条件概率,没有任务特定的微调。
  LM模型非常适合处理文本生成任务(Text Generation)。

  • 机器翻译任务,比如,从英语到汉语,被构造出如下的条件LM:“英语句子=汉语句子”和“目标英语句子=”。 例如,条件概率的预测看起来像: P (?|I like green apples. =我喜欢绿苹果。A cat meows at him. =一只猫对他喵。It is
    raining cats and dogs. = " )
  • QA任务的格式与机器翻译类似,把问题和答案放在一起构成Context。
  • 摘要抽取任务是在抽取完文章的上下文信息之后,通过添加 TL:DR: 来触发的。

2)字节序列上的BPE介绍

  与最初的GPT相同,GPT-2输入采用BPE处理使用UTF-8字节序列。每个字节可以在8bits中表示256个不同的值,而UTF-8中一个字符最多可以使用4个字节,总共支持最多2的31次方个字符。因此,对于字节序列表示,只需要大小为256的词汇表,不需要担心预处理、分词等。尽管有这些好处,当前字节级(byte-level)的LMs与SOTA词级别(word-level)的LMs的性能差距仍然不可忽略
  BPE通过贪心的方式合并频繁共现的字节对。以防止它生成多个版本的常用词(比如对于dog,生成dog. dog! dog?),GPT-2防止BPE跨类别合并字符(因此dog不会与标点符号合并,如。,!还有?)。这些技巧有助于提高最终字节分段的质量。
  使用字节序列表示,GPT-2能够为任何Unicode字符串分配概率,而不需要任何预处理步骤。

3)模型修改

  与GPT相比,GPT-2除了具有更多的Transformer层和参数之外,只包含了很少的架构修改:

  • Layer normalization被移动到每个sub-block的输入,类似于一种“building block”类型的残差单元(不同于原始类型“bottleneck”,它在weight layers之前先进行batch
    normalization)。
  • 在最终的自self-attention块之后添加了额外的layer normalization。
  • 初始化被修改为与模型深度相关的函数。
  • Residual layer的参数最初按 1/N 的系数缩放,其中N是残余层的数量。
  • 使用更大的词汇量和上下文大小。

七、总结

  现有流行Contextual-Based LM的对比:
在这里插入图片描述

实战

【参考资料】

1.斯坦福cs224n-2019链接:https://web.stanford.edu/class/archive/cs/cs224n/cs224n.1194/
2.bilibili 视频:https://www.bilibili.com/video/BV1s4411N7fC?p=2
3.Generalized Language Models:https://lilianweng.github.io/lil-log/2019/01/31/generalized-language-models.html

猜你喜欢

转载自blog.csdn.net/weixin_42691585/article/details/107071763