图解BERT模型结构输入输出
本文首先介绍BERT模型要做什么,即:模型的输入、输出分别是什么,以及模型的预训练任务是什么;然后,分析模型的内部结构,图解如何将模型的输入一步步地转化为模型输出;最后,我们在多个中/英文、不同规模的数据集上比较了BERT模型与现有方法的文本分类效果。1. 模型的输入/输出BERT模型的全称是:BidirectionalEncoderRepresentationsfrom Transformer。从名字中可以看出,BERT模型的目标是利用大规模无标注语料训练、获得文本的包含丰富语义信息的Representation,即:文本的语义表示,然后将文本的语义表示在特定NLP任务中作微调,最终应用于该NLP任务。煮个栗子,BERT模型训练文本语义表示的过程就好比我们在高中阶段学习语数英、物化生等各门基础学科,夯实基础知识;而模型在特定NLP任务中的参数微调就相当于我们在大学期间基于已有基础知识、针对所选专业作进一步强化,从而获得能够应用于实际场景的专业技能。在基于深度神经网络的NLP方法中,文本中的字/词通常都用一维向量来表示(一般称之为“词向量”);在此基础上,神经网络会将文本中各个字或词的一维词向量作为输入,经过一系列复杂的转换后,输出一个一维词向量作为文本的语义表示。特别地,我们通常希望语义相近的字/词在特征向量空间上的距离也比较接近,如此一来,由字/词向量转换而来的文本向量也能够包含更为准确的语义信息。因此,BERT模型的主要输入是文本中各个字/词的原始词向量,该向量既可以随机初始化,也可以利用Word2Vector等算法进行预训练以作为初始值;输出是文本中各个字/词融合了全文语义信息后的向量表示,如下图所示(为方便描述且与BERT模型的当前中文版本保持一致,本文统一以字向量作为输入):从上图中可以看出,BERT模型通过查询字向量表将文本中的每个字转换为一维向量,作为模型输入;模型输出则是输入各字对应的融合全文语义信息后的向量表示。此外,模型输入除了字向量,还包含另外两个部分:1. 文本向量:该向量的取值在模型训练过程中自动学习,用于刻画文本的全局语义信息,并与单字/词的语义信息相融合2. 位置向量:由于出现在文本不同位置的字/词所携带的语义信息存在差异(比如:“我爱你”和“你爱我”),因此,BERT模型对不同位置的字/词分别附加一个不同的向量以作区分最后,BERT模型将字向量、文本向量和位置向量的加和作为模型输入。特别地,在目前的BERT模型中,文章作者还将英文词汇作进一步切割,划分为更细粒度的语义单位(WordPiece),例如:将playing分割为play和##ing;此外,对于中文,目前作者尚未对输入文本进行分词,而是直接将单字作为构成文本的基本单位。对于不同的NLP任务,模型输入会有微调,对模型输出的利用也有差异,例如:根据具体任务的不同,在实际应用中我们可以脑洞大开,通过调整模型的输入、输出将模型适配到真实业务场景中。2. 模型的预训练任务BERT实际上是一个语言模型。语言模型通常采用大规模、与特定NLP任务无关的文本语料进行训练,其目标是学习语言本身应该是什么样的,这就好比我们学习语文、英语等语言课程时,都需要学习如何选择并组合我们已经掌握的词汇来生成一篇通顺的文本。回到BERT模型上,其预训练过程就是逐渐调整模型参数,使得模型输出的文本语义表示能够刻画语言的本质,便于后续针对具体NLP任务作微调。为了达到这个目的,BERT文章作者提出了两个预训练任务:Masked LM和Next Sentence Prediction。2.1 Masked LMMasked LM的任务描述为:给定一句话,随机抹去这句话中的一个或几个词,要求根据剩余词汇预测被抹去的几个词分别是什么,如下图所示。这不就是我们高中英语常做的完形填空么!所以说,BERT模型的预训练过程其实就是在模仿我们学语言的过程。具体来说,文章作者在一句话中随机选择15%的词汇用于预测。对于在原句中被抹去的词汇,80%情况下采用一个特殊符号[MASK]替换,10%情况下采用一个任意词替换,剩余10%情况下保持原词汇不变。这么做的主要原因是:在后续微调任务中语句中并不会出现[MASK]标记,而且这么做的另一个好处是:预测一个词汇时,模型并不知道输入对应位置的词汇是否为正确的词汇(10%概率),这就迫使模型更多地依赖于上下文信息去预测词汇,并且赋予了模型一定的纠错能力。2.2 NextSentence PredictionNext Sentence Prediction的任务描述为:给定一篇文章中的两句话,判断第二句话在文本中是否紧跟在第一句话之后,如下图所示。当年大学考英语四六级的时候,大家应该都做过段落重排序,即:将一篇文章的各段打乱,让我们通过重新排序把原文还原出来,这其实需要我们对全文大意有充分、准确的理解。Next Sentence Prediction任务实际上就是段落重排序的简化版:只考虑两句话,判断是否是一篇文章中的前后句。在实际预训练过程中,文章作者从文本语料库中随机选择50%正确语句对和50%错误语句对进行训练,与Masked LM任务相结合,让模型能够更准确地刻画语句乃至篇章层面的语义信息。BERT模型通过对Masked LM任务和Next Sentence Prediction任务进行联合训练,使模型输出的每个字/词的向量表示都能尽可能全面、准确地刻画输入文本(单句或语句对)的整体信息,为后续的微调任务提供更好的模型参数初始值。3. 模型结构了解了BERT模型的输入/输出和预训练过程之后,我们来看一下BERT模型的内部结构。前面提到过,BERT模型的全称是:BidirectionalEncoder Representations fromTransformer,也就是说,Transformer是组成BERT的核心模块,而Attention机制又是Transformer中最关键的部分,因此,下面我们从Attention机制开始,介绍如何利用Attention机制构建Transformer模块,在此基础上,用多层Transformer组装BERT模型。3.1 Attention机制**Attention: **Attention机制的中文名叫“注意力机制”,顾名思义,它的主要作用是让神经网络把“注意力”放在一部分输入上,即:区分输入的不同部分对输出的影响。这里,我们从增强字/词的语义表示这一角度来理解一下Attention机制。我们知道,一个字/词在一篇文本中表达的意思通常与它的上下文有关。比如:光看“鹄”字,我们可能会觉得很陌生(甚至连读音是什么都不记得吧),而看到它的上下文“鸿鹄之志”后,就对它立马熟悉了起来。因此,字/词的上下文信息有助于增强其语义表示。同时,上下文中的不同字/词对增强语义表示所起的作用往往不同。比如在上面这个例子中,“鸿”字对理解“鹄”字的作用最大,而“之”字的作用则相对较小。为了有区分地利用上下文字信息增强目标字的语义表示,就可以用到Attention机制。Attention机制主要涉及到三个概念:Query、Key和Value。在上面增强字的语义表示这个应用场景中,目标字及其上下文的字都有各自的原始Value,Attention机制将目标字作为Query、其上下文的各个字作为Key,并将Query与各个Key的相似性作为权重,把上下文各个字的Value融入目标字的原始Value中。如下图所示,Attention机制将目标字和上下文各个字的语义向量表示作为输入,首先通过线性变换获得目标字的Query向量表示、上下文各个字的Key向量表示以及目标字与上下文各个字的原始Value表示,然后计算Query向量与各个Key向量的相似度作为权重,加权融合目标字的Value向量和各个上下文字的Value向量,作为Attention的输出,即:目标字的增强语义向量表示。Self-Attention:对于输入文本,我们需要对其中的每个字分别增强语义向量表示,因此,我们分别将每个字作为Query,加权融合文本中所有字的语义信息,得到各个字的增强语义向量,如下图所示。在这种情况下,Query、Key和Value的向量表示均来自于同一输入文本,因此,该Attention机制也叫Self-Attention。Multi-head Self-Attention:为了增强Attention的多样性,文章作者进一步利用不同的Self-Attention模块获得文本中每个字在不同语义空间下的增强语义向量,并将每个字的多个增强语义向量进行线性组合,从而获得一个最终的与原始字向量长度相同的增强语义向量,如下图所示。这里,我们再给出一个例子来帮助理解Multi-head Self-Attention(注:这个例子仅用于帮助理解,并非严格正确)。看下面这句话:“南京市长江大桥”,在不同语义场景下对这句话可以有不同的理解:“南京市/长江大桥”,或“南京市长/江大桥”。对于这句话中的“长”字,在前一种语义场景下需要和“江”字组合才能形成一个正确的语义单元;而在后一种语义场景下,它则需要和“市”字组合才能形成一个正确的语义单元。我们前面提到,Self-Attention旨在用文本中的其它字来增强目标字的语义表示。在不同的语义场景下,Attention所重点关注的字应有所不同。因此,Multi-head Self-Attention可以理解为考虑多种语义场景下目标字与文本中其它字的语义向量的不同融合方式。可以看到,Multi-head Self-Attention的输入和输出在形式上完全相同,输入为文本中各个字的原始向量表示,输出为各个字融合了全文语义信息后的增强向量表示。因此,Multi-head Self-Attention可以看作是对文本中每个字分别增强其语义向量表示的黑盒。3.2 Transformer Encoder在Multi-headSelf-Attention的基础上再添加一些“佐料”,就构成了大名鼎鼎的Transformer Encoder。实际上,Transformer模型还包含一个Decoder模块用于生成文本,但由于BERT模型中并未使用到Decoder模块,因此这里对其不作详述。下图展示了Transformer Encoder的内部结构,可以看到,Transformer Encoder在Multi-head Self-Attention之上又添加了三种关键操作:可以看到,Transformer Encoder的输入和输出在形式上还是完全相同,因此,Transformer Encoder同样可以表示为将输入文本中各个字的语义向量转换为相同长度的增强语义向量的一个黑盒。3.3 BERT model组装好TransformerEncoder之后,再把多个Transformer Encoder一层一层地堆叠起来,BERT模型就大功告成了!在论文中,作者分别用12层和24层Transformer Encoder组装了两套BERT模型,两套模型的参数总数分别为110M和340M。原文参考:https://cloud.tencent.com/developer/article/1389555

BERT关系抽取之R-BERT模型
前期知识准备:RNN, CNN, BERT, SemEval-2010 Task 8数据集, F1值关系分类是一个重要的NLP任务,其主要目标是提取出实体之间的关系。最先进的关系分类方法主要是基于CNN或RNN。最近,预训练BERT模型在许多NLP的分类和序列标注任务中都获得了非常好的结果。关系分类不同于其他NLP任务的主要原因是它既依赖于句子的信息,又依赖于两个目标实体的信息。在本文中,我们提出了一个用来解决关系分类任务的模型,它既利用了预训练的BERT语言模型,又结合来自目标实体的信息。我们定位目标实体并通过预训练结构传递信息,同时还结合了两个实体的相关编码。在SemEval-2010 Task 8任务上,相比目前的最优模型我们的方法获得了有效的提升。R-BERT的预训练完全采用BERT模型,输入句子为单句,因此不需要添加[SEP]。其输出分为三部分,分别是[CLS]隐含状态向量和两个实体的隐含状态向量。作者认为第一部分可以保存句子的语义内容,后两个部分可以保存两个实体的信息。其中,i ,j分别为第一个实体的首、尾字符位置;k,m分别为第二个实体的首、尾字符位置。神经网络中,权重系数和偏置系数均共享,即 W0 = W1 = W2,b0 = b1 = b2。该数据集包含9类语义关系和一个Other类别,规定某关系如果不属于9类语义关系中的一种,则其属于Other类别。9类关系分别是:Cause-Effect、Component-Whole、Content-Container、Entity-Destination、Entity-Origin、Instrument-Angency、Member-Collection、Message-Topic和Product-Producer。数据集中共有10717个句子,8000个句子为训练集,2717个句子为测试集,每个句子包含e1和e2两个名词以及与该句子相关的关系类型。需要注意的是,关系是有向的,即关系(e1, e2)和关系(e2, e1)不同。作者还在相同的数据集上比较了其他多种模型,其中包括:SVM、RNN、MVRNN、CNN+Softmax、FCM、CR-CNN、Attention CNN、Att-Pooling-CNN和Entity Attention Bi-LSTM,以F1值作为评测标准,其结果如下:可见,R-BERT的F1值达到了89.25,相比于其他方法有着明显的优势。为了探究BERT模型之外的部分对最后识别结果的影响,作者分别进行了如下额外实验,并得到结论:(1)去除了实体前后的标识符,这种做法会使模型的F1值从89.25%降到87.98%,说明了标识符可以帮助提供实体信息。(2)在BERT输出层仅使用[CLS]句子向量而不利用实体向量,这样会使得模型F1值从89.25%降到87.99%,说明主动明确实体信息对模型是有帮助的。想办法给模型明确实体的位置对于关系抽取问题精度的提升是有帮助的。https://zhuanlan.zhihu.com/p/78445887https://blog.csdn.net/qq_36426650/article/details/96629835

05-ELMo/BERT/GPT-NLP预训练模型
这里可以参考CSDN上的文章-BERT原理和实践: https://blog.csdn.net/jiaowoshouzi/article/category/9060488在解释BERT,ELMO这些预训练模型之前,我们先看一下很久之前的计算机是如何读懂文字的?每个字都有自己的独特的编码。但是这样是有弊端的,字和字之间的关联关系是无法得知的,比如计算机无法知道dog和cat都是动物,它反而会觉得bag和dog是比较相近的。所以后来就有了Word Class,将一系列的词进行分类然后让一类词语和一类词语之间更有关联,但是这样的方法太过于粗糙,比如dog,cat,bird是一类,看不出哺乳动物鸟类的区别。在这个基础之上,我们有了Word Embedding,Word Embedding我们可以想象成是一种soft的word class,每个词都用向量来表示,它的向量维度可能表示这个词汇的某种意思,如图中dog,cat,rabbit的距离相比其他更近。那么word embendding是如何训练出来的,是根据每个词汇的上下文所训练的。每个句子都有bank的词汇,四个bank是不同的token,但是同样的type。(注:token-词例, type-词型, class-词类 or token是出现的总次数(还有种理解是token是具有一定的句法语义且独立的最小文本成分。 ),type是出现的不同事物的个数。)对于典型的Word Embedding认为,每个词type有一个embedding,所以就算是不同的token只要是一样的type那么word embedding就是一样的,语义也就是一样的。而事实上并非如此,1,2句bank指的是银行,3,4为水库。所以我们希望让机器给不同意思的token而且type还一致,给予不同的embedding。在这个问题上,之前的做法是从字典中去查找这个词包含几种意思,但是这样的做法显然跟不上现实中词语的一些隐含的含义。比如bank有银行的意思,与money一起是银行的意思,而与blood一起却是血库的意思。所以我们想让机器今天进一步做到每一个word token都可以有自己的embedding(之前是每个type有一个embedding或者有固定的一个或多个embedding),那么怎么知道一个word应该有怎样的embedding呢?我们可以取决于该词的上下文,上下文越相近的token它们就会越相近的embedding。比如之前提到的bank,下面两个句子它们的word token的embedding可能是相近的,而和上面的word token的embedding是相远的。所以我们想使用一种能够基于上下文的Contextual word Embedding来解决一词多义的问题。这里使用ELMO可以做到这件事情,即每个word token拥有不同的word embedding。(右上角动物是芝麻街(美国公共广播协会(PBS)制作播出的儿童教育电视节目)里的角色)。它是基于RNN的预训练模型,它只需要搜集大量语料(句子)且不需要做任何标注,就可以训练这个基于RNN的语言模型,预测下一个token是什么,学习完了之后就得到了上下文的embedding。因为我们可以将RNN的隐藏层中的某一节点拿出来(图中橙蓝色节点),它就是输入当前结点的词汇的word embedding。从当计算识别到,模型训练开始。首先输入"潮水",然后当作输入输出"退了",退了当做输入输出"就"。假设当前要得到”退了”这个词的上下文embedding,首先,因为前边的RNN只考虑到了前文而没有考虑到后文,所以这里就使用了同前文一样的反向的RNN。然后,它从句尾开始进行,比如给它喂”知道”,它就要预测”就”,给它喂”就”,它就要预测”退了”。这时候就不仅考虑每个词汇的前文,还会考虑每个词的后文。最后将正向和逆向得到的两个不同的上下文embedding(因为方向不同训练结果也不一样)拼接起来。现在我们训练的程度都会越来越深度,当层数增加,这样就会产生Deep的RNN,因为很多层,而且每一层都会产生上下文Embedding,那么我们到底应该使用哪一层?每一层这种深度LSTM中的每个层都可以生成潜在表示(方框处)。同一个词在不同的层上会产生不同的Embedding,那么我们应该使用哪一层呢?ELMo的策略是每一层得到的上下文embedding都要。在上下文embedding的训练模型中,每个词输入进去都会有一个embedding输出来。但是在ELMo中,每个词汇输入进去,都会得到不止一个embedding,因为每层的RNN都会给到一个embedding,ELMo将它们统统加起来一起使用。以图中为例,这里假设ELMo有两层RNN,这里是将α1(黄色,第一层得到的embedding)和α2(绿色,第二层得到embedding)加起来得到蓝色的embedding,并做为接下来要进行不同任务的输入。但是这里存在一些问题,α1和α2是学习得到的,而且它是根据当前要进行的任务(如QA,POS of tagging ),然后根据接下来要进行的这些任务一起被学习出来。所以就导致不同任务导向下的α1和α2也不一样。ELMo的论文中提到,在不同任务下(SRL,Coref,SNLI,SQuAD,SST-5)。蓝色的上下文embedding在经过token(这里为没有经过上下文的embedding),LSTM1,LSTM2后,它在不同阶段需要的weight也不一样。BERT相当于是Transformer的Encoder部分,它只需要搜集大量的语料去从中学习而不经过标注(不需要label),就可以将Encoder训练完成。如果之前要训练Encoder,我们需要通过一些任务来驱动学习(如机器翻译)。BERT就是句子给进去,每个句子给一个embedding。这里可以回忆下,Transformer的Enoder中有self-attention layer,就是给进去一个sequence,输出也得到一个sequence。虽然图中使用是用词作为单元进行输入,但是在使用BERT进行中文的训练时,字会是一个更好的选择。比如,我们在给BERT进行输入时,用one-hot给词进行编码,但是词在中文中数量庞大,会导致维度过高。但是,字的话相对会少很多,特别是中文(大约几千个,可以穷举)。这样以字为单位进行输入会占很大优势。共有两种方法,一种是Mask LM遮盖语言模型,另一种是Next Sentence Prediction下一句预测。下面用上图的例子来理解BERT是怎么样来进行填空的:1)这里假设在所有句子中的词汇的第2个位置上设置一个;2)接下来把所有的词汇输入BERT,然后每个输入的token都会得到一个embedding;3)接下来将设置为的embedding输入到Linear Multi-class Classifier中中,要求它预测被的词汇是哪个词汇?但是这个Linear Multi-class Classifier它仅仅是一个线性分类器,所以它的能力十分弱,这也就需要在之前的BERT模型中需要将它的层数等参数设计的相当好,然后得到非常出色的representation,便于线性分类器去训练。那么我们怎么知道最后得到的embedding是什么样的呢?如果两个下的词汇(输入时设置的和最后预测的)都放回原来的位置而且没有违和感(就是语句还算通顺),那它们就有类似的embedding(比如退下和落下)。如图中,给定两个句子1)醒醒吧和 2)你没有妹妹。其中特殊符号[SEP]是告诉BERT两个句子的分隔点在哪里。特殊符号[CLS]一般放在句子的开头,它用来告诉BERT从这开始分类任务,[CLS]输入BERT后得到embedding然后通过Linear Binary Classifier得出结果说明:经过BERT预测后现在我们要预测的两个句子是接在一起 or 不应该被接在一起。这里可能会有疑问,为什么不将[CLS]放在句尾,等BERT训练完两个句子再输出结果?对于上图中的任务,BERT现在要做的事情就是给定两个句子,让BERT输出结果这两个句子是不是应该接在一起?所以在语料库的大量句子中,我们是知道哪些句子是可以接在一起的,所以也需要我们告诉BERT哪些句子是接在一起的。Linear Binary Classifier和BERT是一起被训练的,通过预测下一句这个任务,我们就可以把将BERT部分的最优参数训练出来。现在我们知道了任务一和任务二,在原论文中两种任务是要同时进行的,这样才能将BERT的性能发挥到最佳。现在我们知道了BERT要做什么事情,那么我们要如何去使用它?共有四种方法。论文中是将【BERT模型和接下来你要进行的任务】结合在一起做训练。第一种,假设当前任务是Input一个sentence,out一个class,举例来说输入一句话来判断分类。训练流程:1)将做要分类的句子丢给BERT;2)需要在句子开始加上分类的特殊符号,这个特殊符号经过BERT输出的embedding经过线性分类器,输出结果为当前的句子属于的类别是真还是假。BERT和Linear Classifier的参数一起进行学习;3)这里的Linear Classifier是Trained from Scratch是白手起家从头开始,即它的参数随机初始化设置,然后开始训练;4)而BERT则是加上Fine-tune微调策略(一种迁移学习方式*),例如Generative Pre-trained Transformer(OpenAI GPT生成型预训练变换器)(Radford等,2018),引入了最小的任务特定参数,并通过简单地微调预训练参数在下游任务中进行训练。*这里不得不提一下迁移学习中的Fine-tune,这里可以参考csdn的一篇文章: https://blog.csdn.net/u013841196/article/details/80919857( https://arxiv.org/abs/1805.12471 )第二种,假设当前任务是input一个sentence,输出这个句子中的每个词汇属于正例还是负例。举例现在的任务是slot filling填槽任务(填槽指的是为了让用户意图转化为用户明确的指令而补全信息的过程)(另一种解释是从大规模的语料库中抽取给定实体(query)的被明确定义的属性(slot types)的值(slot fillers))(槽可以理解为实体已明确定义的属性),输入的句子是 arrive Taipei on November 2nd输出的槽是other dest on time time训练流程:1)将句子输入BERT,句子中的每个词汇都会映射出一个embedding;2)每个词汇的embedding输入Linear Classifier,输出结果;3)Linear Classifier 白手起家和Bert微调的方式一起去做学习。第三种,假设当前任务是input输入两个句子,输出class。举例现在要进行自然语言预测,让机器根据premise前提,预测这个hypothesis假设是True还是False还是unknown不知道。实际上,我们可以把这个任务当成三分类问题。训练过程:1)在一个sentence前设置特殊符号[CLS],然后在要输入的两个sentence中间设置[SEP]分隔符号;2)将两个sentence连同特殊符号一起输入到BERT中;3)将[CLS]输入BERT后得到的embedding,再把它输入linear Classifier中,得到class。如图所示,假设gravity的token序号是17,即,我们现在有一个问题通过QA Model后得到的s=17,e=17,那么答案就是为gravity;同理,假设within a cloud的序号顺序是77到79,即到,我们现在有一个问题通过QA Model后得到的s=77,e=79,那么答案就是为within a cloud。https://arxiv.org/abs/1905.05950https://openreview.net/pdf?id=SJzSgnRcKX这张图显示了BERT从0-24层的层数在针对不同的NLP任务上的表现。https://d4mucfpksywv.cloudfront.net/better-language-models/language_models_are_unsupervised_multitask_learners.pdf而所谓的GPT,它其实就是Transformer的Decoder。我们简单的描述下GPT的训练过程:这里我们input这个token和潮水,想要GPT预测输出“退了”这个词汇。1)首先输入[BOS](begin of sentence)和潮水,通过Word Embedding再乘上matrix W变成a 1到a 4,然后把它们丢进self-attention 层中,这时候每一个input都分别乘上3个不同的matrix产生3个不同的vector,分别把它们命名为q,k,v。q代表的是query (to match others用来去匹配其它的向量)k代表的是key (to be matched用来去被query匹配的向量)v代表的是value(information to be extracted用来被抽取的信息的向量)2)现在要做的工作就是用每个query q 去对每个 key k做attention(吃2个向量,输出就是告诉你这2个向量有多么匹配或者可以说输入两个向量输出一个分数alpha(而怎么去吃2个向量output一个分数,有很多不同的做法))。这里要预测潮水的下一个词,所以乘,乘上,乘上再经过soft-max分别得到到 。3)我们用和每一个v相乘,和相乘加上和相乘。以此类推并相加,最终得到。4)然后经过很多层的self-attention,预测得到”退了”这个词汇。同理,现在要预测”退了”的下一个词汇,按照前面的流程可以得到,然后经过很多层的self-attention层,得到”就”这个词汇。GPT的神奇之处在于它可以在完全没有训练数据的情况下,就可以做到阅读理解,摘要,翻译。折线图中显示了它在参数量上升的情况下,F1的值的效果。1.Transformer的问题:word Embedding 无上下文监督数据太少解决方法:Contextual Word Embedding2.ELMo(Embeddings fromLanguagesModel)- 多层双向的LSTM的NNLM- RNN-based language models(trained from lots of sentences)ELMo的问题:Contextual Word Embedding作为特征不适合特定任务3.OpenAI GPT的改进根据任务Fine-Tuning使用Transformer替代RNN/LSTMOpenAI GPT的问题:单向信息流的问题Pretraining(1)和Fine-Tuning(2)不匹配解决办法:Masked LMNSP Multi-task LearningEncoder againTips:-使用中文模型-max_seq_length可以小一点,提高效率-内存不够,需要调整train_batch_size-有足够多的领域数据,可以尝试Pretraining

预训练模型综述--Albert,xlnet,bert,word2vec
Albert,xlnet,bert,word2vec通过预训练模型实现迁移学习,迁移学习本质上是在一个数据集上训练模型,然后对该模型进行调整,以在不同的数据集上执行不同的自然语言处理功能。1. word2vec线性模型:很神奇的地方,从而也说明高维空间映射的词向量可以很好体现真实世界中token之间的关系。如:king-man = queen-woman负采样:由于训练词向量模型的目标不是为了得到一个多么精准的语言模型,而是为了获得它的副产物——词向量。所以要做到的不是在几万几十万个token中艰难计算softmax获得最优的那个词(就是预测的对于给定词的下一词),而只需能做到在几个词中找到对的那个词就行,这几个词包括一个正例(即直接给定的下一词),和随机产生的噪声词(采样抽取的几个负例),就是说训练一个sigmoid二分类器,只要模型能够从中找出正确的词就认为完成任务。这种负采样思想也应用到之后的BERT里,只不过从word-level变成sentence-level,这样能获取句子间关联关系。缺点是上下文无关(static):因而为了让句子有一个整体含义(context),大家会在下游具体的NLP任务中基与词向量的序列做encoding操作。下面是一个比较表格,模型不细讲了,预测目标这里的next word下一个词,是所有传统语言模型都做的事——寻找下一个词填什么。BERT模型进一步增加词向量模型泛化能力,充分描述字符级、词级、句子级甚至句间关系特征。真正的双向encoding:Masked LM,类似完形填空,尽管仍旧看到所有位置信息,但需要预测的词已被特殊符号代替,可以放心双向encoding。Transformer做encoder实现上下文相关(context):使用transformer而不是bi-LSTM做encoder,可以有更深的层数、具有更好并行性。并且线性的Transformer比lstm更易免受mask标记影响,只需要通过self-attention减小mask标记权重即可,而lstm类似黑盒模型,很难确定其内部对于mask标记的处理方式。提升至句子级别:学习句子/句对关系表示,句子级负采样。首先给定的一个句子,下一句子正例(正确词),随机采样一句负例(随机采样词),句子级上来做二分类(即判断句子是当前句子的下一句还是噪声),类似word2vec的单词级负采样。二、BERT细则这里主要介绍BERT的三个亮点Masked LM、transformer、sentence-level。1. Masked Language Model原本叫cloze test,是完形填空的意思。随机mask语料中15%的token,然后将masked token 位置输出的最终隐层向量送入softmax,来预测masked token。这样输入一个句子,每次只预测句子中大概15%的词,所以BERT训练很慢。。。(但是google设备NB。。)而对于盖住词的特殊标记,在下游NLP任务中不存在。因此,为了和后续任务保持一致,作者按一定的比例在需要预测的词位置上输入原词或者输入某个随机的词。如:my dog is hairy2. Transformer —— attention is all you needTransformer模型是2018年5月提出的,可以替代传统RNN和CNN的一种新的架构,用来实现机器翻译,论文名称是attention is all you need。无论是RNN还是CNN,在处理NLP任务时都有缺陷。CNN是其先天的卷积操作不很适合序列化的文本,RNN是其没有并行化,很容易超出内存限制(比如50tokens长度的句子就会占据很大的内存)。下面左图是transformer模型一个结构,分成左边Nx框框的encoder和右边Nx框框的decoder,相较于RNN+attention常见的encoder-decoder之间的attention(上边的一个橙色框),还多出encoder和decoder内部的self-attention(下边的两个橙色框)。每个attention都有multi-head特征。最后,通过position encoding加入没考虑过的位置信息。下面从multi-head attention,self-attention, position encoding几个角度介绍。multi-head attention:将一个词的vector切分成h个维度,求attention相似度时每个h维度计算。由于单词映射在高维空间作为向量形式,每一维空间都可以学到不同的特征,相邻空间所学结果更相似,相较于全体空间放到一起对应更加合理。比如对于vector-size=512的词向量,取h=8,每64个空间做一个attention,学到结果更细化。self-attention:每个词位的词都可以无视方向和距离,有机会直接和句子中的每个词encoding。比如上面右图这个句子,每个单词和同句其他单词之间都有一条边作为联系,边的颜色越深表明联系越强,而一般意义模糊的词语所连的边都比较深。比如:law,application,missing,opinion。。。position encoding:因为transformer既没有RNN的recurrence也没有CNN的convolution,但序列顺序信息很重要,比如你欠我100万明天要还和我欠你100万明天要还的含义截然不同。。。transformer计算token的位置信息这里使用正弦波↓,类似模拟信号传播周期性变化。这样的循环函数可以一定程度上增加模型的泛化能力。但BERT直接训练一个position embedding来保留位置信息,每个位置随机初始化一个向量,加入模型训练,最后就得到一个包含位置信息的embedding(简单粗暴。。),最后这个position embedding和word embedding的结合方式上,BERT选择直接相加。3. sentence-level representation在很多任务中,仅仅靠encoding是不足以完成任务的(这个只是学到了一堆token级的特征),还需要捕捉一些句子级的模式,来完成SLI、QA、dialogue等需要句子表示、句间交互与匹配的任务。对此,BERT又引入了另一个极其重要却又极其轻量级的任务,来试图把这种模式也学习到。句子级负采样句子级别的连续性预测任务,即预测输入BERT的两端文本是否为连续的文本。训练的时候,输入模型的第二个片段会以50%的概率从全部文本中随机选取,剩下50%的概率选取第一个片段的后续的文本。 即首先给定的一个句子(相当于word2vec中给定context),它下一个句子即为正例(相当于word2vec中的正确词),随机采样一个句子作为负例(相当于word2vec中随机采样的词),然后在该sentence-level上来做二分类(即判断句子是当前句子的下一句还是噪声)。句子级表示BERT是一个句子级别的语言模型,不像ELMo模型在与下游具体NLP任务拼接时需要每层加上权重做全局池化,BERT可以直接获得一整个句子的唯一向量表示。它在每个input前面加一个特殊的记号[CLS],然后让Transformer对[CLS]进行深度encoding,由于Transformer是可以无视空间和距离的把全局信息encoding进每个位置的,而[CLS]的最高隐层作为句子/句对的表示直接跟softmax的输出层连接,因此其作为梯度反向传播路径上的“关卡”,可以学到整个input的上层特征。segment embedding对于句对来说,EA和EB分别代表左句子和右句子;对于句子来说,只有EA。这个EA和EB也是随模型训练出来的。如下图所示,最终输入结果会变成下面3个embedding拼接的表示。首先,XLNet 是一个类似 BERT 的模型,而不是完全不同的模型。但这是一个非常有前途和潜力的。总之,XLNet是一种通用的自回归预训练方法。那么什么是自回归(AR)语言模型?AR语言模型是一种使用上下文词来预测下一个词的模型。但是在这里,上下文单词被限制在两个方向,前向或后向。AR 语言模型的优势是擅长生成式自然语言处理任务。 因为在生成上下文时,通常是前向的。AR 语言模型很自然地适用于此类 NLP 任务。但AR语言模型有一些缺点,它只能使用前向上下文或后向上下文,这意味着它不能同时使用前向和后向上下文。自回归语言模型有优点有缺点,缺点是只能利用上文或者下文的信息,不能同时利用上文和下文的信息,当然,貌似ELMO这种双向都做,然后拼接看上去能够解决这个问题,因为融合模式过于简单,所以效果其实并不是太好。它的优点,其实跟下游NLP任务有关,比如生成类NLP任务,比如文本摘要,机器翻译等,在实际生成内容的时候,就是从左向右的,自回归语言模型天然匹配这个过程。而Bert这种DAE模式,在生成类NLP任务中,就面临训练过程和应用过程不一致的问题,导致生成类的NLP任务到目前为止都做不太好。与 AR 语言模型不同,BERT 被归类为自动编码器(AE)语言模型。AE 语言模型旨在从损坏的输入重建原始数据。损坏的输入意味着我们在预训练阶段用[MASK]替换原始词into 。目标是预测into得到原始句子。AE 语言模型的优势是,它可以从向前和向后的方向看到上下文。但 AE 语言模型也有其缺点。它在预训练中使用[MASK] ,但这种人为的符号在调优时在真实数据中并不存在,会导致预训练-调优的差异。[MASK] 的另一个缺点是它假设预测(掩蔽的)词 在给定未屏蔽的 词 的情况下彼此独立。例如,我们有一句话“它表明住房危机已经变成银行危机”。我们掩蔽“银行业”和“危机”。在这里注意,我们知道掩蔽的“银行业”和“危机”包含彼此的隐含关系。但 AE 模型试图预测“银行业”给予未掩蔽的 词,并预测“危机”分别给出未掩蔽的 词。它忽略了“银行业”与“危机”之间的关系。换句话说,它假设预测(掩蔽)的标记彼此独立。但是我们知道模型应该学习预测(掩蔽)词之间的这种相关性来预测其中一个词。作者想要强调的是,XLNet 提出了一种让 AR 语言模型从双向上下文中学习的新方法,以避免 MASK 方法在 AE 语言模型中带来的缺点。XLNet的出发点就是:能否融合自回归LM和DAE LM两者的优点。就是说如果站在自回归LM的角度,如何引入和双向语言模型等价的效果;如果站在DAE LM的角度看,它本身是融入双向语言模型的,如何抛掉表面的那个[Mask]标记,让预训练和Fine-tuning保持一致。当然,XLNet还讲到了一个Bert被Mask单词之间相互独立的问题,我相信这个不太重要,原因后面会说。当然,我认为这点不重要的事情,纯粹是个人观点,出错难免,看看就完了,不用较真。AR 语言模型只能向前或向后使用上下文,那么如何让它从双向上下文中学习呢?语言模型包括两个阶段,即预训练阶段和调优阶段。XLNet 专注于预训练阶段。在预训练阶段,它提出了一个名为排列语言建模的新目标。我们可以从这个名称知道基本思想,它使用排列。这里我们举一个例子来解释。序列的次序是[x1, x2, x3, x4] 。这种序列的所有排列如下。因此对于这 4 个词的([图片上传失败...(image-c7a4e0-1570519576567)])句子,有 24([图片上传失败...(image-d738b7-1570519576567)])个排列。情景是我们想要预测x3 。因此在 24 个排列中有 4 种模式,分别x3位于第 1 位,第 2 位,第 3 位,第 4 位。当然,上面讲的仍然是基本思想。难点其实在于具体怎么做才能实现上述思想。首先,需要强调一点,尽管上面讲的是把句子X的单词排列组合后,再随机抽取例子作为输入,但是,实际上你是不能这么做的,因为Fine-tuning阶段你不可能也去排列组合原始输入。所以,就必须让预训练阶段的输入部分,看上去仍然是x1,x2,x3,x4这个输入顺序,但是可以在Transformer部分做些工作,来达成我们希望的目标。具体而言,XLNet采取了Attention掩码的机制,你可以理解为,当前的输入句子是X,要预测的单词Ti是第i个单词,前面1到i-1个单词,在输入部分观察,并没发生变化,该是谁还是谁。但是在Transformer内部,通过Attention掩码,从X的输入单词里面,也就是Ti的上文和下文单词中,随机选择i-1个,放到Ti的上文位置中,把其它单词的输入通过Attention掩码隐藏掉,于是就能够达成我们期望的目标(当然这个所谓放到Ti的上文位置,只是一种形象的说法,其实在内部,就是通过Attention Mask,把其它没有被选到的单词Mask掉,不让它们在预测单词Ti的时候发生作用,如此而已。看着就类似于把这些被选中的单词放到了上文Context_before的位置了)。具体实现的时候,XLNet是用“双流自注意力模型”实现的,细节可以参考论文,但是基本思想就如上所述,双流自注意力机制只是实现这个思想的具体方式,理论上,你可以想出其它具体实现方式来实现这个基本思想,也能达成让Ti看到下文单词的目标。上面说的Attention掩码,我估计你还是没了解它的意思,我再用例子解释一下。Attention Mask的机制,核心就是说,尽管当前输入看上去仍然是x1->x2->x3->x4,但是我们已经改成随机排列组合的另外一个顺序x3->x2->x4->x1了,如果用这个例子用来从左到右训练LM,意味着当预测x2的时候,它只能看到上文x3;当预测x4的时候,只能看到上文x3和x2,以此类推……这样,比如对于x2来说,就看到了下文x3了。这种在输入侧维持表面的X句子单词顺序,但是其实在Transformer内部,看到的已经是被重新排列组合后的顺序,是通过Attention掩码来实现的。如上图所示,输入看上去仍然是x1,x2,x3,x4,可以通过不同的掩码矩阵,让当前单词Xi只能看到被排列组合后的顺序x3->x2->x4->x1中自己前面的单词。这样就在内部改成了被预测单词同时看到上下文单词,但是输入侧看上去仍然维持原先的单词顺序了。关键要看明白上图右侧那个掩码矩阵,我相信很多人刚开始没看明白,因为我刚开始也没看明白,因为没有标出掩码矩阵的单词坐标,它的坐标是1-2-3-4,就是表面那个X的单词顺序,通过掩码矩阵,就能改成你想要的排列组合,并让当前单词看到它该看到的所谓上文,其实是掺杂了上文和下文的内容。这是attention mask来实现排列组合的背后的意思。ALBERT相比于BERT的改进ALBERT也是采用和BERT一样的Transformer的encoder结果,激活函数使用的也是GELU,在讲解下面的内容前,我们规定几个参数,词的embedding我们设置为E,encoder的层数我们设置为L,hidden size即encoder的输出值的维度我们设置为H,前馈神经网络的节点数设置为4H,attention的head个数设置为H/64。在ALBERT中主要有三个改进方向。1、对Embedding因式分解(Factorized embedding parameterization)在BERT中,词embedding与encoder输出的embedding维度是一样的都是768。但是ALBERT认为,词级别的embedding是没有上下文依赖的表述,而隐藏层的输出值不仅包括了词本生的意思还包括一些上下文信息,理论上来说隐藏层的表述包含的信息应该更多一些,因此应该让H>>E,所以ALBERT的词向量的维度是小于encoder输出值维度的。在NLP任务中,通常词典都会很大,embedding matrix的大小是E×V,如果和BERT一样让H=E,那么embedding matrix的参数量会很大,并且反向传播的过程中,更新的内容也比较稀疏。结合上述说的两个点,ALBERT采用了一种因式分解的方法来降低参数量。首先把one-hot向量映射到一个低维度的空间,大小为E,然后再映射到一个高维度的空间,说白了就是先经过一个维度很低的embedding matrix,然后再经过一个高维度matrix把维度变到隐藏层的空间内,从而把参数量从O(V×H) O(V×H)O(V×H)降低到了O(V×E+E×H) O(V×E+E×H)O(V×E+E×H),当E<

RoBERTa 和 ALBERT
BERT 模型是 2018 年提出的,并在很多自然语言处理任务有前所未有的提升。因此 2019 年就有很多工作是围绕着 BERT 展开的,其中出现了两个 BERT 的改进版模型,RoBERTa 和 ALBERT。RoBERTa 在更大的数据集和最优的参数中训练 BERT,使 BERT 的性能再次提升;ALBERT 主要是对 BERT 进行压缩,通过共享所有层的参数以及 Embedding 分解减少 BERT 的参数量。本文主要介绍 BERT 的两种改进模型 RoBERTa 和 ALBERT,关于 BERT 模型可以参考之前的文章《彻底理解 Google BERT 模型》 ,首先总体看一下 RoBERTa 和 ALBERT 的一些特点。RoBERTa:ALBERT:RoBERTa 主要试验了 BERT 中的一些训练设置 (例如 NSP Loss 是否有意义,batch 的大小等),并找出最好的设置,然后再更大的数据集上训练 BERT。原来的 BERT 只使用了 16G 的数据集,而 RoBERTa 在更大的数据集上训练 BERT,使用了 160G 的语料:BERT 在训练的过程中采用了 NSP Loss,原本用意是为了让模型能够更好地捕捉到文本的语义,给定两段语句 X = [x1, x2, ..., xN] 和 Y = [y1, y2, ...., yM],BERT 中的 NSP 任务需要预测 Y 是不是 出现在 X 的后面。但是 NSP Loss 受到不少文章的质疑 ,例如 XLNet,RoBERTa 采用了一个实验验证 NSP Loss 的实用性。实验中采用了四种组合:Segment-Pair + NSP:这个是原来 BERT 的训练方法,使用 NSP Loss,输入的两段文字 X 和 Y 可以包含多个句子,但是 X + Y 的长度要小于 512。Sentence-Pair + NSP:与上一个基本类似,也使用 NSP Loss,但是输入的两段文字 X 和 Y 都分别是一个句子,因此一个输入包含的 token 通常比 Segment-Pair 少,所以要增大 batch,使总的 token 数量和 Sentence-Pair 差不多。Full-Sentences:不使用 NSP,直接从一个或者多个文档中采样多个句子,直到总长度到达 512。当采样到一个文档末尾时,会在序列中添加一个文档分隔符 token,然后再从下一个文档采样。Doc-Sentences:与 Full-Sentences 类似,不使用 NSP,但是只能从一个文档中采样句子,所以输入的长度可能会少于 512。Doc-Sentences 也需要动态调整 batch 大小,使其包含的 token 数量和 Full-Sentences 差不多。上图是实验结果,最上面的两行是使用 NSP 的,可以看到使用 Segment-Pair (多个句子) 要好于 Sentence-Pair (单个句子),实验结果显示使用单个句子会使 BERT 在下游任务的性能下降,主要原因可能是使用单个句子导致模型不能很好地学习长期的依赖关系。中间两行是不使用 NSP Loss 的结果,可以看到两种方式都是比使用 NSP 效果要好的,这说明了 NSP Loss 实际上没什么作用,因此在 RoBERTa 中丢弃了 NSP Loss。原始的 BERT 在训练之前就把数据 Mask 了,然后在整个训练过程中都是保持数据不变的,称为 Static Mask。即同一个句子在整个训练过程中,Mask 掉的单词都是一样的。RoBERTa 使用了一种 Dynamic Mask 的策略,将整个数据集复制 10 次,然后在 10 个数据集上都 Mask 一次,也就是每一个句子都会有 10 种 Mask 结果。使用 10 个数据集训练 BERT。下图是实验结果,可以看到使用 Dynamic Mask 的结果会比原来的 Static Mask 稍微好一点,所以 RoBERTa 也使用了 Dynamic Mask。之前的一些关于神经网络翻译的研究显示了使用一个大的 batch 并相应地增大学习率,可以加速优化并且提升性能。RoBERTa 也对 batch 大小进行了实验,原始的 BERT 使用的 batch = 256,训练步数为 1M,这与 batch = 2K,训练步数 125K 的计算量是一样的,与 batch = 8K 和训练步数为 31K 也是一样的。下图是使用不同 batch 的实验结果,不同 batch 学习率是不同的,可以看到使用 batch = 2K 时的效果最好。BERT 的预训练模型参数量很多,训练时候的时间也比较久。ALBERT 是一个对 BERT 进行压缩后的模型,降低了 BERT 的参数量,减少了训练所需的时间。注意 ALBERT 只是减少 BERT 的参数量,而不减少其计算量。ALBERT 能减少训练时间,这是因为减少了参数之后可以降低分布式训练时候的通讯量;ALBERT 不能减少 inference 的时间,因为 inference 的时候经过的 Transformer 计算量和 BERT 还是一样的。下面介绍 ALBERT 的一些优化方法。这是对 Embedding 进行分解,从而减少参数。在 BERT 中,Embedding 的维度和 Transformer 隐藏层维度是一样的,都是 H。假设词库的大小为 V,则单词的 Embedding 矩阵参数量就有 VH,如果词库很大,则参数量会很多。因此,ALBERT 使用了一种基于 Factorized 的方法,不是直接把单词的 one-hot 矩阵映射到 H 维的向量,而是先映射到一个低维空间 (E 维),再映射到 H 维的空间,这个过程类似于做了一次矩阵分解。这个是参数共享机制,即所有 Transformer 层共享一套参数,Transformer 包括 Multi-Head Attention 的参数和 Feed-Forward 的参数。针对不同部分的参数,ALBERT 采用了四种方式实验。all-shared:共享所有的 Transformer 参数。shared-attention:只共享 Transformer 中 Multi-Head Attention 的参数。shared-FFN:只共享 Transformer 中 Feed-Forward 的参数。not-shared:不共享参数。上图显示了不同共享方式模型的参数量,可以看到共享所有参数之后的模型要远远小于不共享参数的模型。当 E = 768 时,not-shared 的参数量其实就是 BERT-base 的参数量,等于 108M,而共享所有参数后,模型的参数量变为 31M。通过共享参数可以有效地减少模型的参数量,另外共享参数还可以帮助模型稳定网络中的参数。作者对比了 ALBERT 和 BERT 每一层 Transformer 的输入和输出的 L2 距离,发现 ALBERT 的效果更加平滑,如下图所示。如 RoBERTa 结果显示的,NSP Loss 对于模型并没有什么用处,因此 ALBERT 也对 NSP 进行了一些思考。ALBERT 认为 BERT 中使用的 NSP 任务过于简单了,因为 NSP 的反例是随机采样得到的,这些反例的句子通常属于不同的主题,例如前面的句子是来自体育新闻,而后面的句子来自于娱乐新闻。因此 BERT 在进行 NSP 任务时,通常是不需要真正学习句子之间的语义以及顺序的,只需要判断它们的主题类型。ALBERT 将 NSP 替换成了 SOP (sentence order prediction),预测两个句子是否被交换了顺序。即输入的两个句子是来自同一文档的连续句子,并随机对这两个句子的顺序进行调换,让模型预测句子是否被调换过。这样可以让模型更好地学习句子语义信息和相互关系。RoBERTa 更像是一个经过仔细调参后得到的 BERT 模型,并且使用了更大的数据集进行训练。ALBERT 对 BERT 的参数量进行了压缩,并且能够减少分布式训练的开销。但是 ALBERT 并不能减少需要的计算量,因此模型在 inference 时的速度没有提升。RoBERTa: A Robustly Optimized BERT Pretraining ApproachALBERT: A LITE BERT FOR SELF-SUPERVISED LEARNING OF LANGUAGE REPRESENTATIONS

本文由 在线网速测试 整理编辑,转载请注明出处,原文链接:https://www.wangsu123.cn/news/42833.html。