精华内容
下载资源
问答
  • BERT

    2021-05-14 16:36:12
    bert模型常见问题 bert模型是现在机器学习里边一个非常经典的模型,多用于nip方向的模型处理 首先我们在GitHub上下载google已经训练好的模型,一定要下载完整的代码和数据集。由于数据集较大,可能不太好下载,...

    bert模型常见问题

    bert模型是现在机器学习里边一个非常经典的模型,多用于nlp方向的模型处理

    首先我们在GitHub上下载google已经训练好的模型,一定要下载完整的代码和数据集。由于数据集较大,可能不太好下载,大家可以在B站

    找视频,视频下的评论区会有大神分享数据集。视频课链接:https://www.bilibili.com/video/BV1NJ411o7u3?p=14&spm_id_from=pageDriver

    评论区大神云集,相信会有方法解决你的数据集问题。

    然后就是在讲bert在pycharm中打开,复制GitHub中提供的参数,

    该图片的run_classifier.py 下面的部分

    导入到pycharm中,一定要注意环境的配置,需要修改路径,把--data_dir和--output_dir的路径修改成自己的路径。这些在视频课下面的评论区会评论。

    要求tensorflow版本为1.1x,python的版本为3.6或者3.7

    跑结果时会遇到的问题:

    首先是版本问题,然后是下面的报错问题

    Windows fatal exception: access violation

    解决办法是再次降低tensorflow的环境,我原先使用的是tensorflow2.3,然后这个bert模型是利用tensorflow1.x写出来的,所以就一直报错。于是就选择降低tensorflow和python的版本

    首先创建一个虚拟的环境:

    conda create py36 python=3.6 

    然后是进入虚拟环境:

    conda activate py36

    接着在虚拟环境下下载tensorflow1.12(使用1.14.0表示失败,仍然出现问题,所以直接下载1.12.0版本的最好):

    pip install tensorflow==1.12.0

    会有一段时间的下载,需要等候。下载完之后会显示done

    成功之后进如python环境

    输入:import tensorflow as tf

    没有报错就说明tensorflow安装成功

    输入:tf.__version__

    可以查看tensorflow的版本问题

    之后就可以在pycharm上跑bert模型的训练结果了

     

     

     

    展开全文
  • 修改官方bert以便执行下游任务 支持OQMRC,LCQMC,知识提炼,对抗性干扰和bert + esim进行多项选择,分类和语义匹配 对于OQMRC,对于LCQMC,我们可以在开发集上获得0.787%,对于测试集,我们可以得到0.864。 支持...
  • BERTBERTBERT!

    千次阅读 2020-12-20 21:46:25
    BERT的基本原理、模型架构、迁移特性、细节说明。BERT详解!

    从ELMO说起的预训练语言模型

    我们先来看一张图:

    image-20201215101643989

    从图中可以看到,ELMO其实是NLP模型发展的一个转折点,从ELMO开始,Pre-training+finetune的模式开始崭露头角并逐渐流行起来。最初的ELMO也只是为了解决word2vec不能表达”一词多义“的问题提出来的,它所代表的动态词向量的思想更是被不少任务拿来借鉴。它最大的贡献还是提出的预训练+微调的模式,这种迁移学习的思想几乎是它作为NLP模型发展转折点的一个重要原因。

    我们简单地看一下ELMO的模型结构(我加了红色标注便于直观理解):

    image-20201217003923670

    ELMO有一个很明显的特征就是它使用的是双层双向的LSTM,最后网络会产生一个动态词向量,它来自于不同的层输出的组合,由于不同层学习到的特征不一样,最后通过权重的调整向量表征的含义侧重点也不一样。与CV中的模型类似,越靠近输入层的层级学习到的特征越简单,比如W1可能是一些词性或字的特征;越靠近输出层的层级学习到的特征越高级,比如W3可能就是学习到一些句子级的特征。动态词向量偏重于哪一层取决于下游的任务,举个例子,序列标注任务多偏重于底层级一般效果就会更好一点。

    ELMO在预训练阶段得到的网络参数再拿到具体任务中进行微调,这种迁移学习的思想大大降低了一些任务对大数据量的依赖性,在节约成本的同时效果也很不错,这为后面的BERT的出现铺平了道路,也慢慢引领了一个时代的潮流。

    ELMO的缺点在其他文章中也有提及:ELMO 使用了 LSTM ,特征提取能力没有Transformer好;ELMO采取双向拼接这种融合特征的能力可能比 Bert 一体化的融合特征方式弱。但这都是事后视角了,了解即可。

    BERT详解

    BERT的总体结构

    先来看看BERT的结构框架:

    image-20201217014110062

    上面就是BERT的模型结构图了,是不是和ELMO长的有点像,模型的核心由BERT Encoder组成,BERT Encoder由多层BERT Layer组成,每一层的BERT Layer其实都是Transformer中的Encoder Block。再来回顾一下图:

    image-20201217015348332

    说到这里其实我们就已经了解到了BERT的一个大体形貌了,对于Transformer中的Encoder Block有点生疏的话可以再去回顾一下:Transformer 看这一篇就够了,相信可以回忆起来的。

    由于BERT使用的是Transformer中的Encoder Block,所以其本质还是一个特征提取器,只不过由于网络较深和Self-Attention机制的帮衬,它的特征提取/模型学习能力更强。也正是由于它只是Encoder的缘故,所以BERT也不具备生成能力,没法单独用BERT来解决NLG的问题,只能解决NLU的问题。

    BERT的输入

    还是老规矩,对着图说:

    image-20201217152751053

    如图所示,BERT模型输入的Embedding由Token Embeddings、Segment Embeddings和Position Embeddings相加而成,如下图。我们分别来看一下这三部分:

    • Token Embeddings:最传统的词向量,与之前我们一起学习的语言模型的输入一样,它是将token嵌入到一个高维空间中表示的结果。对这一部分的Embeddings,有几点需要注意:
    • token的选取与之前的Transformer不太一样,在这里采用的一种新的token形式,是一种子词粒度的表现形式,称之为subword。说的大白话一点就是中文还是字符级别的token,英文不再按照传统的空格分词,而是将部分单词再拆分成字根的形式,比如playing拆成play+ing。这样做最大的好处就是字典变小了,计算量也变小了,同时也在一定程度上解决了OOV的问题。

      常用的subword的方法可参见:深入理解NLP Subword算法:BPE、WordPiece、ULM

    • 输入token时,第一个token是一个[CLS]的特殊字符,可以用于下游的任务,比如分类任务。句子和句子的中间,以及句子的末尾会有一个特殊的符号[SEP];

    • Segment Embeddings:用来区别两种句子,因为预训练不光做LM还要做以两个句子为输入的分类任务,即主要给NSP任务使用。

    • Position Embeddings:和Transformer不一样,0-10的位置编码只能表示绝对位置,而Transformer中的正余弦函数还可以表示相对位置。(为什么不用正余弦了?因为BERT模型学习能力强。)

    对于BERT输入部分还有几点需要补充:

    1. 上图中标注了各个Embeddings对应的维度,768是BERT-base的词向量维度,BERT-Large与BERT-base的参数对比贴在这:

      【L:网络层数,H:隐藏层维度,A:Multi-Head Attention 多头头数】

      Bert-base: (L=12, H=768,A=12, Total Parameters=110M).(使用GPU内存:7G+)

      BERT-large: (L=24, H=1024,A=16, Total Parameters=340M).(使用GPU内存:32G+)

    2. BERT中输入的tokens的长度不能超过512,即一个句子最大的长度加上[CLS]和[SEP]不能超过512,这里可能就涉及到句子截取等工作。

    3. 一个思考:[CLS]或[SEP]多几个或者少几个可以吗?

      可以,因为网络用到的Transformer中有Self-Attention,每一个位置都可以学习到其他位置词的信息,所以在这一点上他们是一样的。多几个或少几个都是可以的,甚至可以一个token后面跟一个[SEP],训练完后拿出来做NER任务。

    How to Pre-training

    BERT的预训练过程主要分为两个部分:MLM(Mask Language Model,完形填空)和NSP(Next Sentence Prediction,句对预测)。接下来我们分别来看这两部分:

    MLM

    MLM本质还是一个语言模型,那么既然是一个语言模型,那它干的事必然就是【预测一句话合理性的概率】,换句话说就是利用上下文预测可能出现的词。由于LM是单向的,要不从左到右要不从右到左,很难做到结合上下文语义。为了改进LM,实现双向的学习,MLM通过对输入文本序列随机的mask,然后通过上下文来预测这个mask应该是什么词,至此解决了双向的问题。所以人们称之为完形填空,不同于之前LM是自回归问题,这里的MLM是一个自编码问题。目的就是学习语料中的各种特征。

    那么这个mask又是怎么做的呢?

    具体的做法是,对输入句子中的token以15%的概率进行随机选取(如选中"bed"这个token),再将选取出来的token以80%的概率替换成[MASK],10%的概率替换成替换成其他token(如“dad”),最后10%保持不变(依然是“bed”)。

    这样大费周章地做的目的是什么呢?

    其实是提高了模型的泛化能力,因为后面的微调阶段并不会做mask的操作,为了减少预训练和微调阶段输入分布不一致的问题导致的模型表达能力差的现象,故采用了这种策略。

    NSP

    NSP任务主要做的就是一件事:预测句子1与句子2挨在一起的概率。构建数据的方法是,对于句子1,句子2以50%的概率为句子1相连的下一句,以50%的概率在语料库里随机抽取一句。以此构建了一半正样本一半负样本。再用输出的CLS进行二分类,以此来判断输入的两个句子是不是前后相连的关系。

    How to finetune

    之前说过,迁移学习的思想是要将Pre-training阶段的主要成果应用在 finetune阶段,finetune充分应用了大规模预训练模型的优势,只在下游任务上再进行一些微调训练,就可以达到非常不错的效果。

    下面是BERT原文BERT:Pre-trainingofDeepBidirectionalTransformersfor LanguageUnderstanding中提及的微调阶段的四种不同类型的下游任务:

    image-20201219012436766

    在这里简述一下四种任务对应微调阶段的基本方法:

    • 句子对匹配(sentence pair classification):文本匹配类任务的输入是两个不同的句子,最终其实要实现的仍然是一个二分类的问题,若要用BERT实现,基本代码和流程与分类问题一致,全连接层输出维度是2。但实际工程应用上,直接采用BERT来做文本匹配问题的话最终效果不一定会好,一般解决文本匹配问题可以采用一些类似孪生网络的结构去解决,这块可以另外再去探究。
    • 文本分类(single sentence classification):文本分类是BERT最擅长做的事情了,最基本的做法就是将预训练的BERT加载后,同时在输出[CLS]的基础上加一个全连接层来做分类,全连接层输出的维度就是我们要分类的类别数。当然也可以在分类之前加一个其他的网络层以达到对应的目的。
    • 抽取式问答(question answering):注意由于BERT没有生成能力,所以只能做抽取式的问答。可以这样理解:这个回答其实是在一篇文章中找答案的过程,通过预测答案开始与结束位置在文中的id来进行训练。
    • 序列标注(single sentence tagging):由于一般的分词任务、词性标注和命名体识别任务都属于序列标注问题。这类问题因为输入句子的每一个token都需要预测它们的标签,所以序列标注是一个单句多label分类任务,BERT模型的所有输出(除去特殊符号)都要给出一个预测结果。

    BERT微调模型的设计

    针对不同的任务我们可以继续在bert的预训练模型基础上加一些网络的设计,比如文本分类上加一些cnn;比如在序列标注上加一些crf等等。

    下面只记录几点提要,具体使用还需深究代码。

    BERT+CNN:由于BERT中Attention能捕捉长距离的语义特征,而CNN中的滤波器与卷积操作更能捕捉局部特征,故BERT+CNN(+池化层)也是一个能很好互补的组合。相比之下就不太建议加RNN或者Attention之类的结构了,因为BERT里就带了类似的结构了。

    BERT+CRF:NER问题很好的一种解决方案。

    BERT的输出

    之前我们看到了BERT的输入是三种Embeddings的组合,那BERT模型的输出是什么呢。通过下图能够看出会有两种输出,一个对应的是红色框,也就是对应的[CLS]的输出,输出的shape是[batch size,hidden size];另外一个对应的是蓝色框,是所有输入的token对应的输出,它的shape是[batch size,seq length,hidden size],这其中不仅仅有[CLS]对于的输出,还有其他所有token对应的输出。

    image-20201220003953882

    在使用代码上就要考虑到底是使用第一种还是第二种作为输出了。大部分情况是是会选择[CLS]的输出,再进行微调的操作。不过有的时候使用所有token的输出也会有一些意想不到的效果。

    其他一些疑问与细节

    预训练模型为何会有输入长度512的限制?

    BERT模型要求输入句子的长度不能超过512,同时还要考虑[CLS]这些特殊符号的存在,实际文本的长度会更短。究其原因,随着文本长度的不断增加,计算所需要的显存也会成线性增加,运行时间也会随着增长。所以输入文本的长度是需要加以控制的

    在实际的任务中我们的输入文本一般会有两个方面,要不就是特别长,比如文本摘要、阅读理解任务,它们的输入文本是有可能超过512;另外一种就是一些短文本任务,如短文本分类任务。

    长文本该如何处理?

    说到长文本处理,最直接的方法就是截断

    由于 Bert 支持最大长度为 512 个token,那么如何截取文本也成为一个很关键的问题。How to Fine-Tune BERT for Text Classification?中给出了几种解决方法

    • head-only: 保存前 510 个 token (留两个位置给 [CLS] 和 [SEP] )
    • tail-only: 保存最后 510 个token
    • head + tail : 选择前128个 token 和最后382个 token

    作者是在IMDB和Sogou News数据集上做的试验,发现head+tail效果会更好一些。但是在实际的问题中,我们还是要人工的筛选一些数据观察数据的分布情况,视情况选择哪种截断的方法。

    除了上述截断的方法之外,还可以采用sliding window的方式做。

    用划窗的方式对长文本切片,分别放到BERT里,得到相对应的CLS,然后对CLS进行融合,融合的方式也比较多,可以参考以下方式:

    • max pooling最大池化
    • avg pooling平均池化
    • attention注意力融合
    • transformer等

    短文本该如何处理?

    在遇到一些短文本的NLP任务时,我们需要根据输入文本长度的分布情况重新选取max_sequence_length,最大输入文本长度的取值可以通过正态分布得出。

    什么是warmup?为什么要在设置学习率的时候采用的warmup策略?

    warmup是一种学习率优化方法(最早出现在ResNet论文中)。在模型训练之初选用较小的学习率,训练一段时间之后(如:10epoches或10000steps)使用预设的学习率进行训练,或逐渐减小。(BERT原文中前10000步会增长到1e-4, 之后再线性下降。)

    如下图的Linner Warmup:

    image-20201220010210086

    感性分析为何要使用warmup策略:

    1. 刚开始模型对数据完全不了解,这个时候步子太大,loss容易跑飞,此时需要使用小学习率摸着石头过河;
    2. 对数据了解了一段时间之后,可以使用大学习率朝着目标大步向前;
    3. 快接近目标时,使用小学习率进行精调探索,此时步子太大,容易错过目标点;

    不同学习率的设置

    在 fine-tune阶段使用过大的学习率,会打乱 pretrain 阶段学习到的句子信息,造成“灾难性遗忘”。BERT没有下游微调结构的,是直接用BERT去fine-tune时,BERT模型的训练和微调学习率取2e-5和5e-5效果会好一些。那如果微调的时候接了更多的结构,比如BERT+TextCNN,BERT+BiLSTM+CRF,此种情况下BERT的fine-tune学习率可以设置为5e-5, 3e-5, 2e-5。而下游任务结构的学习率可以设置为1e-4,让其比bert的学习更快一些。至于这么做的原因也很简单:BERT本体是已经预训练过的,即本身就带有权重,所以用小的学习率很容易fine-tune到最优点,而下接结构是从零开始训练,用小的学习率训练不仅学习慢,而且也很难与BERT本体训练同步。为此,我们将下游任务网络结构的学习率调大,争取使两者在训练结束的时候同步:当BERT训练充分时,下游任务结构也能够训练充分。

    BERT与GPT的区别?BERT可以做生成任务吗?

    BERT与GPT最大的区别是:BERT用的是Transformer中的Encoder部分,而GPT用的是Transformer中的Decoder部分。

    BERT加上Transformer中的Decoder部分就可以做生成任务了。

    BERT中的weight decay权重衰减是什么?作用?

    权重衰减等价于L2范数正则化。正则化通过为模型损失函数添加惩罚项使得学习的模型参数值较小,是常用的过拟合的常用手段。

    权重衰减并不是所有的权重参数都需要衰减,比如bias,和LayerNorm.weight就不需要衰减。

    BERT不同层的含义

    BERT Rediscovers the Classical NLP Pipeline中对于BERT不同层所学习到的不同信心做了一定的研究,总体来说会有以下发现:

    • BERT会在较低层编码更多语法信息,在较高层编码更多语义信息(像句法分析、实体识别这些比较简单的NLP任务更倾向于使用BERT底层的信息。而像关系分类等复杂的NLP任务更倾向于BERT的高层信息)。
    • 语法信息的体现比较局部化(Locolizable),语义信息的体现在各层中分布的比较均匀。
    • 该文章定性地分析证明在较低层产生的一些有歧义的决定可以在较高层被修正。

    BERT模型的迁移

    迁移特性

    《Linguistic Knowledge and Transferability of Contextual Representations》一文所做的工作提到部分关于BERT模型迁移特性的结论:

    对于难度比较低的任务,仅仅需要BERT的前几层就能得到更好的迁移学习能力。所以适当减少层数是有助于获得更好的迁移学习基础。在不去微调预训练模型的基础上,合理的选择层是有必要的。如果对于BERT-base(12层)来说,最佳的迁移层数经常在6-12层之间,对于比较难的任务,需要的层数会多一些。

    迁移策略

    那拿到一个BERT预训练模型后,我们会有两种选择:

    1. 把BERT当做特征提取器或者句向量,不在下游任务中微调。
    2. 把BERT做为下游业务的主要模型,在下游任务中微调。

    基于BERT模型的改进型模型简介

    Roberta模型:更具鲁棒性的、优化后的BERT模型。采用动态Mask策略,Roberta是把数据复制10份,每一份中采用不同的静态Mask操作,使得预训练的每条数据有了10种不同的Mask数据。在Roberta中,采用的是full-sentence的形式,每一个训练样本都是从一个文档中连续sample出来的,并且不采用NSP损失。从结论中发现效果会更好,说明NSP任务不是必须的。

    BERT-WWM:核心是全词Mask。主要更改了原预训练阶段的训练样本生成策略。在全词Mask中,如果一个完整的词的部分WordPiece子词被Mask,则同属该词的其他部分也会被Mask,即全词Mask。(例如“这个模型真好用”可能会被Mask成"这个模[MASK]真好用",而在WWM下会被Mask成“这个[MASK] [MASK]真好用”)。需要注意的是,这里的Mask指的是广义的Mask(替换成[MASK];保持原词汇;随机替换成另外一个词),并非只局限于单词替换成[MASK]标签的情况。

    芝麻街的初心

    自ELMO出来之后,后续又有例如BERT这样革命性的模型出现,再到后来,更多优秀的模型也被提出来,他们中有好多都像BERT致敬ELMO一样致敬了前面的模型,起的名字好多都来自于动画节目《芝麻街》,以下列举了这几个模型对应的人物形象以及论文链接(看了半天BERT着实是好看啊,哈哈)。致敬一群群推动NLP发展的创造者们,希望自己也能保持一颗孩童时代的好奇心,保持出发时的初心,一路向前。加油!

    ELMOBERTERNIEGroverKERMITBig Bird
    image-20201217011825930image-20201217011915777image-20201217012124932image-20201217012049764image-20201217013122001image-20201217012323262

    除文中已提及文章外其他参考文章:

    The Bright Future of ACL/NLP

    Deep contextualized word representations

    ELMo原理解析及简单上手使用

    关于ELMo你不知道的一些细节

    深入理解NLP Subword算法:BPE、WordPiece、ULM

    Bert输入输出是什么

    BERT 详解

    展开全文
  • 一文读懂BERT(原理篇)

    万次阅读 多人点赞 2019-04-19 08:37:17
    一文读懂BERT(从原理到实践) 2018年的10月11日,Google发布的论文《Pre-training of Deep Bidirectional Transformers for Language Understanding》,成功在 11 项 NLP 任务中取得 state of the art 的结果,赢得...

    一文读懂BERT(原理篇)

    2018年的10月11日,Google发布的论文《Pre-training of Deep Bidirectional Transformers for Language Understanding》,成功在 11 项 NLP 任务中取得 state of the art 的结果,赢得自然语言处理学界的一片赞誉之声。

    本文是对近期关于BERT论文、相关文章、代码进行学习后的知识梳理,仅为自己学习交流之用。因笔者精力有限,如果文中因引用了某些文章观点未标出处还望作者海涵,也希望各位一起学习的读者对文中不恰当的地方进行批评指正。

    1)资源梳理

    • BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding

    • 论文原文:
      BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding

    • 官方代码和预训练模型
      Github: https://github.com/google-research/bert

    • Google AI Blog:
      Open Sourcing BERT: State-of-the-Art Pre-training for Natural Language Processing

    • 第三方代码

      1. pytorch-pretrained-BERT
        Google官方推荐的PyTorch BERB版本实现,可加载Google预训练的模型:PyTorch version of Google AI’s BERT model with script to load Google’s pre-trained models

      2. BERT-pytorch
        另一个Pytorch版本实现:Google AI 2018 BERT pytorch implementation

      3. BERT-tensorflow
        Tensorflow版本:BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding

      4. bert-chainer
        Chanier版本: Chainer implementation of “BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding”

      5. bert-as-service
        将不同长度的句子用BERT预训练模型编码,映射到一个固定长度的向量上:Mapping a variable-length sentence to a fixed-length vector using pretrained BERT model
        进一步是否可以做一个句子相似度计算服务?有没有同学一试?

      6. bert_language_understanding
        BERT实战:Pre-training of Deep Bidirectional Transformers for Language Understanding: pre-train TextCNN

      7. sentiment_analysis_fine_grain
        BERT实战,多标签文本分类,在 AI Challenger 2018 细粒度情感分析任务上的尝试:Multi-label Classification with BERT; Fine Grained Sentiment Analysis from AI challenger

      8. BERT-NER
        BERT实战,命名实体识别: Use google BERT to do CoNLL-2003 NER !

      9. BERT-keras
        Keras版: Keras implementation of BERT with pre-trained weights

      10. tbert
        PyTorch port of BERT ML model

    2)NLP发展史

    关于NLP发展史,特别推荐weizier大佬的NLP的巨人肩膀。学术性和文学性都很棒,纵览NLP近几年的重要发展,对各算法如数家珍,深入浅出,思路清晰,文不加点,一气呵成。
    现对NLP发展脉络简要梳理如下:
    在这里插入图片描述

    • 2001 - Neural language models(神经语言模型)
    • 2008 - Multi-task learning(多任务学习)
    • 2013 - Word embeddings(词嵌入)
    • 2013 - Neural networks for NLP(NLP神经网络)
    • 2014 - Sequence-to-sequence models
    • 2015 - Attention(注意力机制)
    • 2015 - Memory-based networks(基于记忆的网络)
    • 2018 - Pretrained language models(预训练语言模型)

    2001 - 神经语言模型

    第一个神经语言模型是Bengio等人在2001年提出的前馈神经网络,如图所示:
    在这里插入图片描述这个模型将从表C中查找到的n个单词作为输入向量表征。这种向量被现在的学者们称做“词嵌入”。这些词嵌入级联后被输入到一个隐藏层中,该隐藏层的输出又被输入到softmax层。更多关于模型的信息

    语言建模通常是应用RNN时的第一步,是一种非监督学习形式。尽管它很简单,但却是本文后面讨论的许多技术发展的核心:

    • 词嵌入:word2vec 的目标是简化语言建模。

    • sequence-to-sequence 模型:这种模型通过一次预测一个单词生成一个输出序列。

    • 预训练语言模型:这些方法使用来自语言模型的表述进行迁移学习。

    反过来讲,这意味着近年来 NLP 的许多重要进展都可以归结为某些形式的语言建模。为了“真正”理解自然语言,仅仅从文本的原始形式中学习是不够的。我们需要新的方法和模型。

    2008- 多任务学习

    多任务学习是在多个任务上训练的模型之间共享参数的一种通用方法。在神经网络中,可以通过给不同层施以不同的权重,来很容易地实现多任务学习。多任务学习的概念最初由Rich Caruana 在1993年提出,并被应用于道路跟踪和肺炎预测(Caruana,1998)。直观地说,多任务学习鼓励模型学习对许多任务有用的表述。这对于学习一般的、低级的表述形式、集中模型的注意力或在训练数据有限的环境中特别有用。详情请看这篇文章

    在2008年,Collobert 和 Weston 将多任务学习首次应用于 NLP 的神经网络。在他们的模型中,查询表(或单词嵌入矩阵)在两个接受不同任务训练的模型之间共享,如下面的图所示。
    在这里插入图片描述

    2013- 词嵌入

    用稀疏向量表示文本,即所谓的词袋模型在 NLP 有着悠久的历史。正如上文中介绍的,早在 2001年就开始使用密集向量表示词或词嵌入。Mikolov等人在2013年提出的创新技术是通过去除隐藏层,逼近目标,进而使这些单词嵌入的训练更加高效。虽然这些技术变更本质上很简单,但它们与高效的word2vec配合使用,便能使大规模的词嵌入训练成为可能。

    Word2vec有两种风格,如下面的图所示:连续字袋 CBOW 和 skip-gram。不过他们的目标不同:一个是根据周围的单词预测中心单词,而另一个则相反。
    在这里插入图片描述虽然这些嵌入在概念上与使用前馈神经网络学习的嵌入在概念上没有区别,但是在一个非常大的语料库上训练之后,它们就能够捕获诸如性别、动词时态和国家-首都关系等单词之间的特定关系,如下图所示。
    !

    2013 - NLP 神经网络

    2013 年和 2014 年是 NLP 问题开始引入神经网络模型的时期。使用最广泛的三种主要的神经网络是:循环神经网络、卷积神经网络和递归神经网络。

    循环神经网络(RNNs) 循环神经网络是处理 NLP 中普遍存在的动态输入序列的一个最佳的技术方案。Vanilla RNNs (Elman,1990)很快被经典的长-短期记忆网络(Hochreiter & Schmidhuber,1997)所取代,它被证明对消失和爆炸梯度问题更有弹性。在 2013 年之前,RNN 仍被认为很难训练;Ilya Sutskever 的博士论文为改变这种现状提供了一个关键性的例子。下面的图对 LSTM 单元进行了可视化显示。双向 LSTM(Graves等,2013)通常用于处理左右两边的上下文。
    在这里插入图片描述卷积神经网络(CNNs) 卷积神经网络本来是广泛应用于计算机视觉领域的技术,现在也开始应用于语言(Kalchbrenner等,2014;Kim等,2014)。文本的卷积神经网络只在两个维度上工作,其中滤波器(卷积核)只需要沿着时间维度移动。下面的图显示了NLP中使用的典型 CNN。
    在这里插入图片描述卷积神经网络的一个优点是它们比 RNN 更可并行化,因为其在每个时间步长的状态只依赖于本地上下文(通过卷积运算),而不是像 RNN 那样依赖过去所有的状态。使用膨胀卷积,可以扩大 CNN 的感受野,使网络有能力捕获更长的上下文(Kalchbrenner等,2016)。CNN 和 LSTM 可以组合和叠加(Wang等,2016),卷积也可以用来加速 LSTM(Bradbury等, 2017)。

    递归神经网络 RNN 和 CNN 都将语言视为一个序列。然而,从语言学的角度来看,语言本质上是层次化的:单词被组合成高阶短语和从句,这些短语和从句本身可以根据一组生产规则递归地组合。将句子视为树而不是序列的语言学启发思想产生了递归神经网络(Socher 等人, 2013),如下图所示
    在这里插入图片描述递归神经网络从下到上构建序列的表示,这一点不同于从左到右或从右到左处理句子的 RNN。在树的每个节点上,通过组合子节点的结果来计算新的结果。由于树也可以被视为在 RNN 上强加不同的处理顺序,所以 LSTM 自然地也被扩展到树上(Tai等,2015)。

    RNN 和 LSTM 可以扩展到使用层次结构。单词嵌入不仅可以在本地学习,还可以在语法语境中学习(Levy & Goldberg等,2014);语言模型可以基于句法堆栈生成单词(Dyer等,2016);图卷积神经网络可以基于树结构运行(Bastings等,2017)。

    2014-sequence-to-sequence 模型

    2014 年,Sutskever 等人提出了 sequence-to-sequence 模型。这是一个使用神经网络将一个序列映射到另一个序列的通用框架。在该框架中,编码器神经网络逐符号处理一个句子,并将其压缩为一个向量表示;然后,一个解码器神经网络根据编码器状态逐符号输出预测值,并将之前预测的符号作为每一步的输入,如下图所示。
    !
    机器翻译是对这个框架比较成功的应用。2016 年,谷歌宣布将开始用神经 MT 模型取代基于单片短语的 MT 模型(Wu等,2016)。根据 Jeff Dean 的说法,这意味着用 500 行神经网络模型替换 50 万行基于短语的MT代码。

    由于其灵活性,这个框架现在是自然语言生成任务的首选框架,其中不同的模型承担了编码器和解码器的角色。重要的是,解码器模型不仅可以解码一个序列,而且可以解码任意表征。例如,可以基于图像生成标题(Vinyals等,2015)(如下图所示)、基于表生成文本(Lebret等,2016)和基于应用程序中源代码更改描述(Loyola等,2017)。
    在这里插入图片描述sequence-to-sequence 学习甚至可以应用于 NLP 中输出具有特定结构的结构化预测任务。为了简单起见,输出被线性化,如下面的图所示,用于进行选区解析。神经网络已经证明了在有足够数量的训练数据进行选区分析(Vinyals等,2015)和命名实体识别(Gillick等, 2016)的情况下,直接学习可以产生这种线性化输出的能力。
    在这里插入图片描述

    2015- 注意力机制

    注意力机制(Bahdanau 等,2015)是神经网络机器翻译(NMT)的核心创新之一,也是使 NMT模型胜过经典的基于短语的MT系统的关键思想。sequence-to-sequence模型的主要瓶颈是需要将源序列的全部内容压缩为一个固定大小的向量。注意力机制通过允许解码器回头查看源序列隐藏状态来缓解这一问题,然后将其加权平均作为额外输入提供给解码器,如下面的图所示
    在这里插入图片描述
    注意力机制有很多不同的形式(Luong等,2015)。这里有一个简短的概述。注意力机制广泛适用于任何需要根据输入的特定部分做出决策的任务,并且效果不错。它已被应用于一致性解析(Vinyals等,2015)、阅读理解(Hermann等,2015)和一次性学习(Vinyals等,2016)等诸多领域。输入甚至不需要是一个序列,即可以包含其他表示,如图像字幕(Xu等,2015),如下图所示。注意力机制的一个额外的功能是,它提供了一种少见的功能,我们可以通过检查输入的哪些部分与基于注意力权重的特定输出相关来了解模型的内部工作方式。
    在这里插入图片描述

    2015 - 基于记忆的网络

    注意力机制可以看作是模糊记忆的一种形式。记忆由模型的隐藏状态组成,模型选择从记忆中检索内容。研究者们提出了许多具有更明确记忆的模型。这些模型有不同的变体,如神经图灵机(Graves等,2014)、记忆网络(Weston等,2015)和端到端记忆网络(Sukhbaatar等,2015)、动态记忆网络(Kumar等,2015)、神经微分计算机(Graves等,2016)和循环实体网络(Henaff等,2017)。

    记忆的访问通常基于与当前状态的相似度,类似于注意力,通常可以写入和读取。模型在如何实现和利用内存方面有所不同。例如,端到端记忆网络多次处理输入,并更新记忆以实现多个推理步骤。神经图灵机也有一个基于位置的寻址,这允许他们学习简单的计算机程序,如排序。基于记忆的模型通常应用于一些特定任务中,如语言建模和阅读理解。在这些任务中,长时间保存信息应该很有用。记忆的概念是非常通用的:知识库或表可以充当记忆,而记忆也可以根据整个输入或它的特定部分填充。

    2018 - 预训练语言模型

    预训练的词嵌入与上下文无关,仅用于初始化模型中的第一层。一系列监督型任务被用于神经网络的预训练。相反,语言模型只需要无标签的文本;因此,训练可以扩展到数十亿个tokens, new domains, new languages。预训练语言模型于 2015 年被首次提出(Dai & Le,2015);直到最近,它们才被证明在各种任务中效果还是不错的。语言模型嵌入可以作为目标模型中的特征(Peters等,2018),或者使用语言模型对目标任务数据进行微调(Ramachandranden等,2017; Howard & Ruder,2018)。添加语言模型嵌入可以在许多不同的任务中提供比最先进的技术更大的改进,如下面的图所示。

    在这里插入图片描述
    预训练的语言模型已经被证明可以用更少的数据进行学习。由于语言模型只需要无标记的数据,因此对于标记数据稀缺的低资源语言尤其有用。

    其他里程碑事件

    其他一些技术发展没有上面提到的那样流行,但仍然有广泛的影响。

    • 基于字符的表示
      在字符上使用 CNN 或 LSTM 以获得基于字符的词表示的做法现在相当普遍,特别是对于形态信息重要或有许多未知单词的丰富的语言和任务,效果更加明显。据我所知,序列标签使用基于字符的表示(Lample 等人,2016;普兰克等人,2016),可以减轻在计算成本增加的情况下必须处理固定词汇表的需要,并支持完全基于字符的 NMT (Ling 等人, 2016;Lee 等人,2017)。

    • 对抗学习
      对抗学习方法已经在 ML 领域掀起了风暴,在 NLP 中也有不同形式的应用。对抗性的例子越来越被广泛使用,它不仅是作为一种工具来探究模型和理解它们的失败案例,而且也使自身更加鲁棒(Jia & Liang, 2017)。(虚拟)对抗性训练,即最坏情况扰动(Miyato 等人,2017)和领域对抗性损失(Ganin 等人, 2016;Kim 等人,2017),同样可以使模型更加鲁棒。生成对抗网络(GANs)对于自然语言生成还不是很有效(Semeniuta 等人, 2018),但在匹配分布时很有用(Conneau 等人, 2018)。

    • 强化学习
      强化学习已被证明对具有时间依赖性的任务有效,例如在训练期间选择数据(Fang 等人, 2017;Wu 等人, 2018)和建模对话(Liu 等人, 2018)。RL 对于直接优化不可微的末端度量(如 ROUGE 或 BLEU)也有效,反而在汇总中优化替代损失(如交叉熵)(Paulus 等人, 2018;Celikyilmaz 等人,2018)和机器翻译场景效果就不明显了(Ranzato 等人,2016)。类似地,逆向强化学习在过于复杂而无法指定数据的情况下也很有用,比看图说话任务(Wang 等人, 2018)。

    3)BERT:一切过往, 皆为序章

    Attention机制讲解

    attention是一种能让模型对重要信息重点关注并充分学习吸收的技术,它不算是一个完整的模型,应当是一种技术,能够作用于任何序列模型中。本文较多引用了本篇文章思路,如感兴趣可以跳转学习。

    Seq2Seq

    在开始讲解Attention之前,我们先简单回顾一下Seq2Seq模型,传统的机器翻译基本都是基于Seq2Seq模型来做的,该模型分为encoder层与decoder层,并均为RNN或RNN的变体构成,如下图所示:
    在这里插入图片描述
    在encode阶段,第一个节点输入一个词,之后的节点输入的是下一个词与前一个节点的hidden state,最终encoder会输出一个context,这个context又作为decoder的输入,每经过一个decoder的节点就输出一个翻译后的词,并把decoder的hidden state作为下一层的输入。该模型对于短文本的翻译来说效果很好,但是其也存在一定的缺点,如果文本稍长一些,就很容易丢失文本的一些信息,为了解决这个问题,Attention应运而生。

    Attention

    Attention,正如其名,注意力,该模型在decode阶段,会选择最适合当前节点的context作为输入。Attention与传统的Seq2Seq模型主要有以下两点不同。

    1)encoder提供了更多的数据给到decoder,encoder会把所有的节点的hidden state提供给decoder,而不仅仅只是encoder最后一个节点的hidden state。
    在这里插入图片描述
    2)decoder并不是直接把所有encoder提供的hidden state作为输入,而是采取一种选择机制,把最符合当前位置的hidden state选出来,具体的步骤如下

    • 确定哪一个hidden state与当前节点关系最为密切

    • 计算每一个hidden state的分数值(具体怎么计算我们下文讲解)

    • 对每个分数值做一个softmax的计算,这能让相关性高的hidden state的分数值更大,相关性低的hidden state的分数值更低

    这里我们以一个具体的例子来看下其中的详细计算步骤:
    在这里插入图片描述
    把每一个encoder节点的hidden states的值与decoder当前节点的上一个节点的hidden state相乘,如上图,h1、h2、h3分别与当前节点的上一节点的hidden state进行相乘(如果是第一个decoder节点,需要随机初始化一个hidden state),最后会获得三个值,这三个值就是上文提到的hidden state的分数,注意,这个数值对于每一个encoder的节点来说是不一样的,把该分数值进行softmax计算,计算之后的值就是每一个encoder节点的hidden states对于当前节点的权重,把权重与原hidden states相乘并相加,得到的结果即是当前节点的hidden state。可以发现,其实Atttention的关键就是计算这个分值。

    明白每一个节点是怎么获取hidden state之后,接下来就是decoder层的工作原理了,其具体过程如下:

    第一个decoder的节点初始化一个向量,并计算当前节点的hidden state,把该hidden state作为第一个节点的输入,经过RNN节点后得到一个新的hidden state与输出值。注意,这里和Seq2Seq有一个很大的区别,Seq2Seq是直接把输出值作为当前节点的输出,但是Attention会把该值与hidden state做一个连接,并把连接好的值作为context,并送入一个前馈神经网络,最终当前节点的输出内容由该网络决定,重复以上步骤,直到所有decoder的节点都输出相应内容。
    在这里插入图片描述

    Attention模型并不只是盲目地将输出的第一个单词与输入的第一个词对齐。实际上,它在训练阶段学习了如何在该语言对中对齐单词(示例中是法语和英语)。Attention函数的本质可以被描述为一个查询(query)到一系列(键key-值value)对的映射。
    在这里插入图片描述
    在计算attention时主要分为三步,第一步是将query和每个key进行相似度计算得到权重,常用的相似度函数有点积,拼接,感知机等;然后第二步一般是使用一个softmax函数对这些权重进行归一化;最后将权重和相应的键值value进行加权求和得到最后的attention。目前在NLP研究中,key和value常常都是同一个,即key=value。
    在这里插入图片描述

    Transrofmer模型讲解

    接下来我将介绍《Attention is all you need》这篇论文。这篇论文是google机器翻译团队在2017年6月放在arXiv上,最后发表在2017年nips上,到目前为止google学术显示引用量为2203,可见也是受到了大家广泛关注和应用。这篇论文主要亮点在于
    1)不同于以往主流机器翻译使用基于RNN的seq2seq模型框架,该论文用attention机制代替了RNN搭建了整个模型框架。
    2)提出了多头注意力(Multi-headed attention)机制方法,在编码器和解码器中大量的使用了多头自注意力机制(Multi-headed self-attention)。
    3)在WMT2014语料中的英德和英法任务上取得了先进结果,并且训练速度比主流模型更快。

    《Attention Is All You Need》是一篇Google提出的将Attention思想发挥到极致的论文。这篇论文中提出一个全新的模型,叫 Transformer,抛弃了以往深度学习任务里面使用到的 CNN 和 RNN ,Bert就是基于Transformer构建的,这个模型广泛应用于NLP领域,例如机器翻译,问答系统,文本摘要和语音识别等等方向。关于Transrofmer模型的理解特别推荐一位国外博主文章《The Illustrated Transformer》

    Transformer总体结构

    和Attention模型一样,Transformer模型中也采用了 encoer-decoder 架构。但其结构相比于Attention更加复杂,论文中encoder层由6个encoder堆叠在一起,decoder层也一样。
    在这里插入图片描述每一个encoder和decoder的内部简版结构如下图
    在这里插入图片描述
    对于encoder,包含两层,一个self-attention层和一个前馈神经网络,self-attention能帮助当前节点不仅仅只关注当前的词,从而能获取到上下文的语义。decoder也包含encoder提到的两层网络,但是在这两层中间还有一层attention层,帮助当前节点获取到当前需要关注的重点内容。

    现在我们知道了模型的主要组件,接下来我们看下模型的内部细节。首先,模型需要对输入的数据进行一个embedding操作,(也可以理解为类似w2c的操作),enmbedding结束之后,输入到encoder层,self-attention处理完数据后把数据送给前馈神经网络,前馈神经网络的计算可以并行,得到的输出会输入到下一个encoder。
    在这里插入图片描述

    Self-Attention

    接下来我们详细看一下self-attention,其思想和attention类似,但是self-attention是Transformer用来将其他相关单词的“理解”转换成我们正常理解的单词的一种思路,我们看个例子:
    The animal didn't cross the street because it was too tired
    这里的it到底代表的是animal还是street呢,对于我们来说能很简单的判断出来,但是对于机器来说,是很难判断的,self-attention就能够让机器把it和animal联系起来
    在这里插入图片描述
    接下来我们看下详细的处理过程。

    1、首先,self-attention会计算出三个新的向量,在论文中,向量的维度是512维,我们把这三个向量分别称为Query、Key、Value,这三个向量是用embedding向量与一个矩阵相乘得到的结果,这个矩阵是随机初始化的,维度为(64,512)注意第二个维度需要和embedding的维度一样,其值在BP的过程中会一直进行更新,得到的这三个向量的维度是64低于embedding维度的。

    在这里插入图片描述
    那么Query、Key、Value这三个向量又是什么呢?这三个向量对于attention来说很重要,当你理解了下文后,你将会明白这三个向量扮演者什么的角色。

    2、计算self-attention的分数值,该分数值决定了当我们在某个位置encode一个词时,对输入句子的其他部分的关注程度。这个分数值的计算方法是Query与Key做点乘,以下图为例,首先我们需要针对Thinking这个词,计算出其他词对于该词的一个分数值,首先是针对于自己本身即q1·k1,然后是针对于第二个词即q1·k2
    在这里插入图片描述
    3、接下来,把点成的结果除以一个常数,这里我们除以8,这个值一般是采用上文提到的矩阵的第一个维度的开方即64的开方8,当然也可以选择其他的值,然后把得到的结果做一个softmax的计算。得到的结果即是每个词对于当前位置的词的相关性大小,当然,当前位置的词相关性肯定会会很大
    在这里插入图片描述
    4、下一步就是把Value和softmax得到的值进行相乘,并相加,得到的结果即是self-attetion在当前节点的值。
    在这里插入图片描述
    在实际的应用场景,为了提高计算速度,我们采用的是矩阵的方式,直接计算出Query, Key, Value的矩阵,然后把embedding的值与三个矩阵直接相乘,把得到的新矩阵Q与K相乘,乘以一个常数,做softmax操作,最后乘上V矩阵
    在这里插入图片描述
    在这里插入图片描述
    这种通过 query 和 key 的相似性程度来确定 value 的权重分布的方法被称为scaled dot-product attention。其实scaled dot-Product attention就是我们常用的使用点积进行相似度计算的attention,只是多除了一个(为K的维度)起到调节作用,使得内积不至于太大。
    在这里插入图片描述

    Multi-Headed Attention

    这篇论文更厉害的地方是给self-attention加入了另外一个机制,被称为“multi-headed” attention,该机制理解起来很简单,就是说不仅仅只初始化一组Q、K、V的矩阵,而是初始化多组,tranformer是使用了8组,所以最后得到的结果是8个矩阵。
    在这里插入图片描述
    在这里插入图片描述
    这给我们留下了一个小的挑战,前馈神经网络没法输入8个矩阵呀,这该怎么办呢?所以我们需要一种方式,把8个矩阵降为1个,首先,我们把8个矩阵连在一起,这样会得到一个大的矩阵,再随机初始化一个矩阵和这个组合好的矩阵相乘,最后得到一个最终的矩阵。
    在这里插入图片描述
    这就是multi-headed attention的全部流程了,这里其实已经有很多矩阵了,我们把所有的矩阵放到一张图内看一下总体的流程。
    在这里插入图片描述
    多头attention(Multi-head attention)整个过程可以简述为:Query,Key,Value首先进过一个线性变换,然后输入到放缩点积attention(注意这里要做h次,其实也就是所谓的多头,每一次算一个头,而且每次Q,K,V进行线性变换的参数W是不一样的),然后将h次的放缩点积attention结果进行拼接,再进行一次线性变换得到的值作为多头attention的结果。可以看到,google提出来的多头attention的不同之处在于进行了h次计算而不仅仅算一次,论文中说到这样的好处是可以允许模型在不同的表示子空间里学习到相关的信息,后面还会根据attention可视化来验证。
    在这里插入图片描述
    那么在整个模型中,是如何使用attention的呢?如下图,首先在编码器到解码器的地方使用了多头attention进行连接,K,V,Q分别是编码器的层输出(这里K=V)和解码器中都头attention的输入。其实就和主流的机器翻译模型中的attention一样,利用解码器和编码器attention来进行翻译对齐。然后在编码器和解码器中都使用了多头自注意力self-attention来学习文本的表示。Self-attention即K=V=Q,例如输入一个句子,那么里面的每个词都要和该句子中的所有词进行attention计算。目的是学习句子内部的词依赖关系,捕获句子的内部结构。

    在这里插入图片描述
    对于使用自注意力机制的原因,论文中提到主要从三个方面考虑(每一层的复杂度,是否可以并行,长距离依赖学习),并给出了和RNN,CNN计算复杂度的比较。可以看到,如果输入序列n小于表示维度d的话,每一层的时间复杂度self-attention是比较有优势的。当n比较大时,作者也给出了一种解决方案self-attention(restricted)即每个词不是和所有词计算attention,而是只与限制的r个词去计算attention。在并行方面,多头attention和CNN一样不依赖于前一时刻的计算,可以很好的并行,优于RNN。在长距离依赖上,由于self-attention是每个词和所有词都要计算attention,所以不管他们中间有多长距离,最大的路径长度也都只是1。可以捕获长距离依赖关系。
    在这里插入图片描述
    现在我们已经接触了attention的header,让我们重新审视我们之前的例子,看看例句中的“it”这个单词在不同的attention header情况下会有怎样不同的关注点(这里不同颜色代表attention不同头的结果,颜色越深attention值越大)。
    在这里插入图片描述
    当我们对“it”这个词进行编码时,一个注意力的焦点主要集中在“animal”上,而另一个注意力集中在“tired”(两个heads)
    但是,如果我们将所有注意力添加到图片中,可能有点难理解:
    在这里插入图片描述

    Positional Encoding

    到目前为止,transformer模型中还缺少一种解释输入序列中单词顺序的方法。为了处理这个问题,transformer给encoder层和decoder层的输入添加了一个额外的向量Positional Encoding,维度和embedding的维度一样,这个向量采用了一种很独特的方法来让模型学习到这个值,这个向量能决定当前词的位置,或者说在一个句子中不同的词之间的距离。这个位置向量的具体计算方法有很多种,论文中的计算方法如下
    在这里插入图片描述
    其中pos是指当前词在句子中的位置,i是指向量中每个值的index,可以看出,在偶数位置,使用正弦编码,在奇数位置,使用余弦编码。最后把这个Positional Encoding与embedding的值相加,作为输入送到下一层。
    在这里插入图片描述
    为了让模型捕捉到单词的顺序信息,我们添加位置编码向量信息(POSITIONAL ENCODING),位置编码向量不需要训练,它有一个规则的产生方式(上图公式)。

    如果我们的嵌入维度为4,那么实际上的位置编码就如下图所示:
    在这里插入图片描述
    那么生成位置向量需要遵循怎样的规则呢?

    观察下面的图形,每一行都代表着对一个矢量的位置编码。因此第一行就是我们输入序列中第一个字的嵌入向量,每行都包含512个值,每个值介于1和-1之间。我们用颜色来表示1,-1之间的值,这样方便可视化的方式表现出来:
    在这里插入图片描述
    这是一个20个字(行)的(512)列位置编码示例。你会发现它咋中心位置被分为了2半,这是因为左半部分的值是一由一个正弦函数生成的,而右半部分是由另一个函数(余弦)生成。然后将它们连接起来形成每个位置编码矢量。

    Layer normalization

    在transformer中,每一个子层(self-attetion,ffnn)之后都会接一个残差模块,并且有一个Layer normalization
    在这里插入图片描述
    在进一步探索其内部计算方式,我们可以将上面图层可视化为下图:
    在这里插入图片描述
    残差模块相信大家都很清楚了,这里不再讲解,主要讲解下Layer normalization。Normalization有很多种,但是它们都有一个共同的目的,那就是把输入转化成均值为0方差为1的数据。我们在把数据送入激活函数之前进行normalization(归一化),因为我们不希望输入数据落在激活函数的饱和区。

    说到 normalization,那就肯定得提到 Batch Normalization。BN的主要思想就是:在每一层的每一批数据上进行归一化。我们可能会对输入数据进行归一化,但是经过该网络层的作用后,我们的数据已经不再是归一化的了。随着这种情况的发展,数据的偏差越来越大,我的反向传播需要考虑到这些大的偏差,这就迫使我们只能使用较小的学习率来防止梯度消失或者梯度爆炸。

    BN的具体做法就是对每一小批数据,在批这个方向上做归一化。如下图所示:
    在这里插入图片描述
    可以看到,右半边求均值是沿着数据 batch_size的方向进行的,其计算公式如下:
    在这里插入图片描述
    那么什么是 Layer normalization 呢?它也是归一化数据的一种方式,不过 LN 是在每一个样本上计算均值和方差,而不是BN那种在批方向计算均值和方差!在这里插入图片描述
    下面看一下 LN 的公式:
    在这里插入图片描述
    到这里为止就是全部encoders的内容了,如果把两个encoders叠加在一起就是这样的结构,在self-attention需要强调的最后一点是其采用了残差网络中的short-cut结构,目的是解决深度学习中的退化问题。
    在这里插入图片描述

    Decoder层

    在这里插入图片描述
    上图是transformer的一个详细结构,相比本文一开始结束的结构图会更详细些,接下来,我们会按照这个结构图讲解下decoder部分。

    可以看到decoder部分其实和encoder部分大同小异,不过在最下面额外多了一个masked mutil-head attetion,这里的mask也是transformer一个很关键的技术,我们一起来看一下。

    Mask

    mask 表示掩码,它对某些值进行掩盖,使其在参数更新时不产生效果。Transformer 模型里面涉及两种 mask,分别是 padding mask 和 sequence mask。

    其中,padding mask 在所有的 scaled dot-product attention 里面都需要用到,而 sequence mask 只有在 decoder 的 self-attention 里面用到。

    Padding Mask

    什么是 padding mask 呢?因为每个批次输入序列长度是不一样的也就是说,我们要对输入序列进行对齐。具体来说,就是给在较短的序列后面填充 0。但是如果输入的序列太长,则是截取左边的内容,把多余的直接舍弃。因为这些填充的位置,其实是没什么意义的,所以我们的attention机制不应该把注意力放在这些位置上,所以我们需要进行一些处理。

    具体的做法是,把这些位置的值加上一个非常大的负数(负无穷),这样的话,经过 softmax,这些位置的概率就会接近0!

    而我们的 padding mask 实际上是一个张量,每个值都是一个Boolean,值为 false 的地方就是我们要进行处理的地方。

    Sequence mask

    文章前面也提到,sequence mask 是为了使得 decoder 不能看见未来的信息。也就是对于一个序列,在 time_step 为 t 的时刻,我们的解码输出应该只能依赖于 t 时刻之前的输出,而不能依赖 t 之后的输出。因此我们需要想一个办法,把 t 之后的信息给隐藏起来。

    那么具体怎么做呢?也很简单:产生一个上三角矩阵,上三角的值全为0。把这个矩阵作用在每一个序列上,就可以达到我们的目的。

    • 对于 decoder 的 self-attention,里面使用到的 scaled dot-product attention,同时需要padding mask 和 sequence mask 作为 attn_mask,具体实现就是两个mask相加作为attn_mask。
    • 其他情况,attn_mask 一律等于 padding mask。

    编码器通过处理输入序列启动。然后将顶部编码器的输出转换为一组注意向量k和v。每个解码器将在其“encoder-decoder attention”层中使用这些注意向量,这有助于解码器将注意力集中在输入序列中的适当位置:
    在这里插入图片描述
    完成编码阶段后,我们开始解码阶段。解码阶段的每个步骤从输出序列(本例中为英语翻译句)输出一个元素。
    以下步骤重复此过程,一直到达到表示解码器已完成输出的符号。每一步的输出在下一个时间步被送入底部解码器,解码器像就像我们对编码器输入所做操作那样,我们将位置编码嵌入并添加到这些解码器输入中,以表示每个字的位置。
    在这里插入图片描述

    输出层

    当decoder层全部执行完毕后,怎么把得到的向量映射为我们需要的词呢,很简单,只需要在结尾再添加一个全连接层和softmax层,假如我们的词典是1w个词,那最终softmax会输入1w个词的概率,概率值最大的对应的词就是我们最终的结果。
    在这里插入图片描述

    BERT原理详解

    从创新的角度来看,bert其实并没有过多的结构方面的创新点,其和GPT一样均是采用的transformer的结构,相对于GPT来说,其是双向结构的,而GPT是单向的,如下图所示
    在这里插入图片描述
    elmo:将上下文当作特征,但是无监督的语料和我们真实的语料还是有区别的,不一定的符合我们特定的任务,是一种双向的特征提取。

    openai gpt就做了一个改进,也是通过transformer学习出来一个语言模型,不是固定的,通过任务 finetuning,用transfomer代替elmo的lstm。
    openai gpt其实就是缺少了encoder的transformer。当然也没了encoder与decoder之间的attention。

    openAI gpt虽然可以进行fine-tuning,但是有些特殊任务与pretraining输入有出入,单个句子与两个句子不一致的情况,很难解决,还有就是decoder只能看到前面的信息。
    其次bert在多方面的nlp任务变现来看效果都较好,具备较强的泛化能力,对于特定的任务只需要添加一个输出层来进行fine-tuning即可。

    结构

    先看下bert的内部结构,官网最开始提供了两个版本,L表示的是transformer的层数,H表示输出的维度,A表示mutil-head attention的个数
    在这里插入图片描述
    如今已经增加了多个模型,中文是其中唯一一个非英语的模型。
    在这里插入图片描述
    从模型的层数来说其实已经很大了,但是由于transformer的残差(residual)模块,层数并不会引起梯度消失等问题,但是并不代表层数越多效果越好,有论点认为低层偏向于语法特征学习,高层偏向于语义特征学习。

    预训练模型

    首先我们要了解一下什么是预训练模型,举个例子,假设我们有大量的维基百科数据,那么我们可以用这部分巨大的数据来训练一个泛化能力很强的模型,当我们需要在特定场景使用时,例如做文本相似度计算,那么,只需要简单的修改一些输出层,再用我们自己的数据进行一个增量训练,对权重进行一个轻微的调整。

    预训练的好处在于在特定场景使用时不需要用大量的语料来进行训练,节约时间效率高效,bert就是这样的一个泛化能力较强的预训练模型。

    BERT的预训练过程

    接下来我们看看BERT的预训练过程,BERT的预训练阶段包括两个任务,一个是Masked Language Model,还有一个是Next Sentence Prediction。

    Masked Language Model

    MLM可以理解为完形填空,作者会随机mask每一个句子中15%的词,用其上下文来做预测,例如:my dog is hairy → my dog is [MASK]

    此处将hairy进行了mask处理,然后采用非监督学习的方法预测mask位置的词是什么,但是该方法有一个问题,因为是mask15%的词,其数量已经很高了,这样就会导致某些词在fine-tuning阶段从未见过,为了解决这个问题,作者做了如下的处理:

    • 80%的时间是采用[mask],my dog is hairy → my dog is [MASK]

    • 10%的时间是随机取一个词来代替mask的词,my dog is hairy -> my dog is apple

    • 10%的时间保持不变,my dog is hairy -> my dog is hairy

    那么为啥要以一定的概率使用随机词呢?这是因为transformer要保持对每个输入token分布式的表征,否则Transformer很可能会记住这个[MASK]就是"hairy"。至于使用随机词带来的负面影响,文章中解释说,所有其他的token(即非"hairy"的token)共享15%*10% = 1.5%的概率,其影响是可以忽略不计的。Transformer全局的可视,又增加了信息的获取,但是不让模型获取全量信息。
    注意:

    • 有参数dupe_factor决定数据duplicate的次数。
    • 其中,create_instance_from_document函数,是构造了一个sentence-pair的样本。对每一句,先生成[CLS]+A+[SEP]+B+[SEP],有长(0.9)有短(0.1),再加上mask,然后做成样本类object。
    • create_masked_lm_predictions函数返回的tokens是已经被遮挡词替换之后的tokens
    • masked_lm_labels则是遮挡词对应位置真实的label。

    Next Sentence Prediction

    选择一些句子对A与B,其中50%的数据B是A的下一条句子,剩余50%的数据B是语料库中随机选择的,学习其中的相关性,添加这样的预训练的目的是目前很多NLP的任务比如QA和NLI都需要理解两个句子之间的关系,从而能让预训练的模型更好的适应这样的任务。
    个人理解:

    • Bert先是用Mask来提高视野范围的信息获取量,增加duplicate再随机Mask,这样跟RNN类方法依次训练预测没什么区别了除了mask不同位置外;

    • 全局视野极大地降低了学习的难度,然后再用A+B/C来作为样本,这样每条样本都有50%的概率看到一半左右的噪声;

    • 但直接学习Mask A+B/C是没法学习的,因为不知道哪些是噪声,所以又加上next_sentence预测任务,与MLM同时进行训练,这样用next来辅助模型对噪声/非噪声的辨识,用MLM来完成语义的大部分的学习。
      在这里插入图片描述

    输入

    bert的输入可以是单一的一个句子或者是句子对,实际的输入值是segment embedding与position embedding相加,具体的操作流程可参考上面的transformer讲解。

    BERT的输入词向量是三个向量之和:

    Token Embedding:WordPiece tokenization subword词向量。
    Segment Embedding:表明这个词属于哪个句子(NSP需要两个句子)。
    Position Embedding:学习出来的embedding向量。这与Transformer不同,Transformer中是预先设定好的值。

    在这里插入图片描述

    总结

    在这里插入图片描述
    BERT的去除实验表明,双向LM和NSP带了的提升最大。

    在这里插入图片描述
    另一个结论是,增加模型参数数量可以提升模型效果。

    在这里插入图片描述
    BERT预训练模型的输出结果,无非就是一个或多个向量。下游任务可以通过精调(改变预训练模型参数)或者特征抽取(不改变预训练模型参数,只是把预训练模型的输出作为特征输入到下游任务)两种方式进行使用。BERT原论文使用了精调方式,但也尝试了特征抽取方式的效果,比如在NER任务上,最好的特征抽取方式只比精调差一点点。但特征抽取方式的好处可以预先计算好所需的向量,存下来就可重复使用,极大提升下游任务模型训练的速度。
    在这里插入图片描述
    后来也有其他人针对ELMo和BERT比较了这两种使用方式的精度差异。下面列出基本结论:

    在这里插入图片描述
    在这里插入图片描述
    总结下BERT的主要贡献:

    • 引入了Masked LM,使用双向LM做模型预训练。
    • 为预训练引入了新目标NSP,它可以学习句子与句子间的关系。
    • 进一步验证了更大的模型效果更好: 12 --> 24 层。
    • 为下游任务引入了很通用的求解框架,不再为任务做模型定制。
    • 刷新了多项NLP任务的记录,引爆了NLP无监督预训练技术。

    BERT是谷歌团队糅合目前已有的NLP知识集大成者,刷新11条赛道彰显了无与伦比的实力,且极容易被用于多种NLP任务。宛若一束烟花点亮在所有NLP从业者心中。更为可贵的是谷歌选择了开源这些,让所有从业者看到了在各行各业落地的更多可能性。

    BERT优点

    • Transformer Encoder因为有Self-attention机制,因此BERT自带双向功能

    • 因为双向功能以及多层Self-attention机制的影响,使得BERT必须使用Cloze版的语言模型Masked-LM来完成token级别的预训练

    • 为了获取比词更高级别的句子级别的语义表征,BERT加入了Next Sentence Prediction来和Masked-LM一起做联合训练

    • 为了适配多任务下的迁移学习,BERT设计了更通用的输入层和输出层

    • 微调成本小

    BERT缺点

    • task1的随机遮挡策略略显粗犷,推荐阅读《Data Nosing As Smoothing In Neural Network Language Models》

    • [MASK]标记在实际预测中不会出现,训练时用过多[MASK]影响模型表现;

    • 每个batch只有15%的token被预测,所以BERT收敛得比left-to-right模型要慢(它们会预测每个token)

    • BERT对硬件资源的消耗巨大(大模型需要16个tpu,历时四天;更大的模型需要64个tpu,历时四天。

    关于BERT最新的各领域应用推荐张俊林的Bert时代的创新(应用篇)

    思考

    • 个人并不认为文章是模型的改进,更认可为任务的设计改进。

    • 论文作者只比较了有没有task1的影响,并没有针对task2对比试验。提升是否来自好的预训练任务设计没有明说。

    • bert对nlp领域目前已有知识的有效“整合”,在硬件配置足够的情况下能提高nlp多领域性能

    BERT适用场景

    第一,如果NLP任务偏向在语言本身中就包含答案,而不特别依赖文本外的其它特征,往往应用Bert能够极大提升应用效果。典型的任务比如QA和阅读理解,正确答案更偏向对语言的理解程度,理解能力越强,解决得越好,不太依赖语言之外的一些判断因素,所以效果提升就特别明显。反过来说,对于某些任务,除了文本类特征外,其它特征也很关键,比如搜索的用户行为/链接分析/内容质量等也非常重要,所以Bert的优势可能就不太容易发挥出来。再比如,推荐系统也是类似的道理,Bert可能只能对于文本内容编码有帮助,其它的用户行为类特征,不太容易融入Bert中。

    第二,Bert特别适合解决句子或者段落的匹配类任务。就是说,Bert特别适合用来解决判断句子关系类问题,这是相对单文本分类任务和序列标注等其它典型NLP任务来说的,很多实验结果表明了这一点。而其中的原因,我觉得很可能主要有两个,一个原因是:很可能是因为Bert在预训练阶段增加了Next Sentence Prediction任务,所以能够在预训练阶段学会一些句间关系的知识,而如果下游任务正好涉及到句间关系判断,就特别吻合Bert本身的长处,于是效果就特别明显。第二个可能的原因是:因为Self Attention机制自带句子A中单词和句子B中任意单词的Attention效果,而这种细粒度的匹配对于句子匹配类的任务尤其重要,所以Transformer的本质特性也决定了它特别适合解决这类任务。

    从上面这个Bert的擅长处理句间关系类任务的特性,我们可以继续推理出以下观点:

    既然预训练阶段增加了Next Sentence Prediction任务,就能对下游类似性质任务有较好促进作用,那么是否可以继续在预训练阶段加入其它的新的辅助任务?而这个辅助任务如果具备一定通用性,可能会对一类的下游任务效果有直接促进作用。这也是一个很有意思的探索方向,当然,这种方向因为要动Bert的第一个预训练阶段,所以属于NLP届土豪们的工作范畴,穷人们还是散退、旁观、鼓掌、叫好为妙。

    第三,Bert的适用场景,与NLP任务对深层语义特征的需求程度有关。感觉越是需要深层语义特征的任务,越适合利用Bert来解决;而对有些NLP任务来说,浅层的特征即可解决问题,典型的浅层特征性任务比如分词,POS词性标注,NER,文本分类等任务,这种类型的任务,只需要较短的上下文,以及浅层的非语义的特征,貌似就可以较好地解决问题,所以Bert能够发挥作用的余地就不太大,有点杀鸡用牛刀,有力使不出来的感觉。

    这很可能是因为Transformer层深比较深,所以可以逐层捕获不同层级不同深度的特征。于是,对于需要语义特征的问题和任务,Bert这种深度捕获各种特征的能力越容易发挥出来,而浅层的任务,比如分词/文本分类这种任务,也许传统方法就能解决得比较好,因为任务特性决定了,要解决好它,不太需要深层特征。

    第四,Bert比较适合解决输入长度不太长的NLP任务,而输入比较长的任务,典型的比如文档级别的任务,Bert解决起来可能就不太好。主要原因在于:Transformer的self attention机制因为要对任意两个单词做attention计算,所以时间复杂度是n平方,n是输入的长度。如果输入长度比较长,Transformer的训练和推理速度掉得比较厉害,于是,这点约束了Bert的输入长度不能太长。所以对于输入长一些的文档级别的任务,Bert就不容易解决好。结论是:Bert更适合解决句子级别或者段落级别的NLP任务。

    如果有小伙伴坚持看到这里的话深表感谢,本来要继续写源码分析和具体的实践了。时间关系,等下周再抽时间写源码分析与实践部分吧。本文仅用于笔者自己总结自己BERT学习之路,期间引用很多专家学者的观点思路,深表感谢。第一次驾驭这么长的技术文章,每个知识点都想写点,感觉越写越乱。若有读者在阅读本文期间有不好的阅读体验深表歉意。

    展开全文
  • 解析BERT

    千次阅读 2019-07-26 14:38:45
    什么是BERTBERT是Transformer的双向编码器表示的缩写。它是由Google在2018年末开发和发布的一种新型语言模型。像BERT这样的预训练语言模型在许多自然语言处理任务中发挥着重要作用,例如问答,命名实体识别,自然...

    什么是BERT?

    BERT是Transformer的双向编码器表示的缩写。它是由Google在2018年末开发和发布的一种新型语言模型。像BERT这样的预训练语言模型在许多自然语言处理任务中发挥着重要作用,例如问答,命名实体识别,自然语言推理,文本分类等等
    BERT是一种基于微调的多层双向变压器编码器。此时,介绍Transformer架构非常重要。

    什么是变压器?

    2017年,谷歌发表了一篇题为“注意力都是你需要的”的论文,该论文提出了一种基于注意力的结构来处理与序列模型相关的问题,例如机器翻译。传统的神经机器翻译大多使用RNN或CNN作为编码器 - 解码器的模型库。然而,谷歌的基于注意力的变形金刚模型放弃了传统的RNN和CNN公式。该模型高度并行运行,因此在提高翻译性能的同时,培训速度也非常快。
    让我们退后一步,理解注意力。

    什么是注意力?

    注意机制可以看作是模糊记忆的一种形式。内存由模型的隐藏状态组成,模型选择从内存中检索内容。在我们深入了解Attention之前,让我们简要回顾一下Seq2Seq模型。传统的机器翻译基本上是基于Seq2Seq模型。该模型分为编码器层和解码器层,并由RNN或RNN变体(LSTM,GRU等)组成。编码器矢量是从模型的编码器部分产生的最终隐藏状态。该向量旨在封装所有输入元素的信息,以帮助解码器进行准确的预测。它充当模型的解码器部分的初始隐藏状态。Seq2Seq模型的主要瓶颈是需要将源序列的全部内容压缩为固定大小的矢量。如果文本稍长,则很容易丢失文本的某些信息。为了解决这个问题,注意力应运而生。注意机制通过允许解码器回顾源序列隐藏状态,然后将其加权平均值作为附加输入提供给解码器来缓解该问题。使用Attention,顾名思义,模型在解码阶段选择最适合当前节点的上下文作为输入。注意与传统的Seq2Seq模型有两个主要区别。首先,编码器向解码器提供更多数据,编码器将所有节点的隐藏状态提供给解码器,

    https://jalammar.github.io/images/seq2seq_7.mp4

    其次,解码器不直接使用所有编码器提供的隐藏状态作为输入,而是采用选择机制来选择与当前位置最匹配的隐藏状态。为此,它尝试通过计算每个隐藏状态的得分值并对得分进行softmax计算来确定哪个隐藏状态与当前节点最密切相关,这允许隐藏状态的更高相关性具有更大小数值,不太相关的隐藏状态具有较低的小数值。然后它将每个隐藏状态乘以其softmaxed得分,从而放大具有高分数的隐藏状态,并淹没具有低分数的隐藏状态。该评分练习在解码器侧的每个时间步骤完成。
    https://jalammar.github.io/images/attention_process.mp4
    现在让我们在下面的可视化中将整个事物放在一起,看看注意过程是如何工作的:

    • 注意解码器RNN接收令牌的嵌入和初始解码器隐藏状态。
    • RNN处理其输入,产生输出和新的隐藏状态向量(h4)。输出被丢弃。
    • 注意步骤:我们使用编码器隐藏状态和h4向量来计算该时间步长的上下文向量(C4)。
    • 我们将h4和C4连接成一个向量。
    • 我们通过前馈神经网络(与模型共同训练的一个)传递此向量。
    • 前馈神经网络的输出指示该时间步长的输出字。
    • 重复下一步的步骤
      https://jalammar.github.io/images/attention_tensor_dance.mp4

    回到transformer

    变压器模型使用编码器 - 解码器架构。在Google发表的论文中,编码器层由6个编码器堆叠,解码器层相同。每个编码器和解码器的内部结构如下 -

    在这里插入图片描述

    编码器由两层组成,一个自注意层和一个前馈神经网络。自我关注有助于当前节点不仅关注当前单词,而且还获得上下文的语义。解码器还包含编码器提到的双层网络,但在两层中间还有一个关注层,以帮助当前节点获得需要注意的关键内容。
    以下是Transformer架构的详细结构 -
    在这里插入图片描述

    让我们分解各个组件。

    自我关注

    自我关注是Transformer将其他相关单词的“理解”转换为我们正在处理的单词的一种方式。
    首先,自我关注计算三个新的向量。在论文中,向量的维度是512维。我们分别将这三个向量称为Query,Key和Value。这三个向量是通过将字嵌入向量与随机初始化矩阵(文中的维数为(64,512))相乘而产生的,其值在反向传播过程中被更新。

    在这里插入图片描述

    接下来,我们计算自我关注的分数值,它确定当我们在某个位置编码单词时对输入句子的其余部分的注意力。该小数值的计算方法使用Query和Key向量。然后我们将结果除以常数。这里我们除以8.这个值通常是上面提到的矩阵的第一维的平方根,也就是64的平方根8.然后我们对所有得分进行softmax计算。结果是每个单词与当前位置的单词的相关性。当然,当前位置的相关性一词肯定会很大。最后一步是将Value向量与softmax结果相乘并添加它们。结果是当前节点处的自我关注的价值。

    在这里插入图片描述

    这种通过查询和密钥之间的相似度来确定值的权重分布的方法被称为缩放的点积注意。

    多头注意力

    本文中更强大的部分是增加了另一种自我关注机制,称为“多头”关注,它不仅仅初始化了一组Q,K,V矩阵。相反,初始化多个组,变换器使用8个组,因此最终结果是8个矩阵。

    在这里插入图片描述

    前馈神经网络不能接受8个矩阵,因此我们需要一种方法将8个矩阵减少到1.为此,我们首先将8个矩阵连接在一起得到一个大矩阵,然后将这个组合矩阵与一个随机初始化矩阵相乘得到最后的矩阵。让我们来看看整个过程。

    在这里插入图片描述

    Transformer以三种不同的方式使用多头注意力:
    在“编码器 - 解码器关注”层中,查询来自先前的解码器层,并且存储器键和值来自编码器的输出。这允许解码器中的每个位置都参与输入序列中的所有位置。这模拟了序列到序列模型中典型的编码器 - 解码器注意机制。
    编码器包含自我关注层。在自我关注层中,所有键,值和查询来自相同的位置,在这种情况下,是编码器中前一层的输出。编码器中的每个位置都可以处理编码器前一层中的所有位置。
    类似地,解码器中的自注意层允许解码器中的每个位置参与解码器中的所有位置直到并包括该位置。我们需要防止解码器中的向左信息流以保持自回归属性。我们通过屏蔽(设置为-∞)softmax输入中与非法连接相对应的所有值来实现缩放点产品注意内部。这将在解码器部分中更详细地探讨,我们将讨论掩蔽。

    位置编码

    到目前为止,我们没有办法解释变换器模型中输入序列中的单词顺序。为了解决这个问题,变换器在编码器和解码器层的输入端增加了一个额外的矢量位置编码。尺寸与嵌入尺寸相同。此位置编码的值将添加到嵌入值中,并作为输入发送到下一层。有许多位置编码选项,包括学习和修复。
    在这里插入图片描述

    残差连接和图层规范化

    在编码器和解码器中,在两个子层中的每一个周围采用残余连接,然后进行层标准化。跳过连接或剩余连接用于允许梯度直接流过网络,而不通过非线性激活功能。非线性激活函数本质上是非线性的,导致梯度爆炸或消失(取决于权重)。从概念上说,跳过连接形成一条“总线”,它在网络中流动,反过来,梯度也可以沿着它向后流动。标准化有助于解决称为内部协变量偏移的问题。内部协变量移位是指在神经网络中发生的协变量移位,即从(例如)第2层到第3层。这是因为,当网络学习并且权重被更新时,网络中特定层的输出分布发生变化。这迫使较高层适应该漂移,这减慢了学习速度。在对神经网络中的输入进行归一化后,我们不必担心输入特征的规模差别很大。要了解图层规范化,将其与批量标准化进行对比非常有用。小批量包含具有相同数量功能的多个示例。小批量是矩阵 - 如果每个输入是多维的,则为张量 - 其中一个轴对应于批次,另一个轴 - 或轴 - 对应于特征尺寸。批量标准化规范化批次维度中的输入要素。图层规范化的关键特性是它可以对要素之间的输入进行标准化。在批量标准化中,统计数据是在批次中计算的,并且对于批次中的每个示例都是相同的。相反,在层规范化中,统计数据是跨每个特征计算的,并且与其他示例无关。

    在这里插入图片描述

    将剩余连接和层规范化结合在一起。

    在这里插入图片描述

    解码器

    回到Transformer体系结构图,我们可以看到解码器部分类似于编码器部分,但底部有一个掩盖的多头注意。Mask表示屏蔽某些值的掩码,以便在更新参数时它们不起作用。Transformer模型中有两种掩码 - 填充掩码和序列掩码。填充掩码用于所有缩放的点积注意,并且序列掩码仅用于解码器的自我注意。
    填充掩码解决了输入序列具有可变长度的问题。具体来说,我们在较短的序列后填0。但是如果输入序列太长,则会截取左侧的内容,并直接丢弃多余的内容。因为这些填充的位置实际上没有意义,我们的注意机制不应该集中在这些位置,所以我们需要做一些处理。具体方法是在这些位置的值上加一个非常大的负数(负无穷大),这样这些位置的概率在softmax之后将接近0!填充掩码实际上是一个张量,每个值都是一个布尔值,false值是我们想要处理的值。
    序列掩码旨在确保解码器无法查看将来的信息。也就是说,对于序列,在time_step t,我们的解码输出应该仅取决于t之前的输出,而不取决于t之后的输出。这特定于Transformer架构,因为我们没有RNN,我们可以按顺序输入序列。在这里,我们一起输入所有内容,如果没有掩码,多头注意力将考虑每个位置的整个解码器输入序列。我们通过生成上三角矩阵来实现这一点,上三角形的值全为零,并将该矩阵应用于每个序列。
    为了解码器的自我关注,使用缩放的点积注意,并且添加填充掩码和序列掩码作为attn_mask。在其他情况下,attn_mask等于填充掩码。
    另一个细节是解码器输入将向右移动一个位置。这样做的一个原因是我们不希望我们的模型在训练期间学习如何复制我们的解码器输入,但我们想要了解给定编码器序列和模型已经看到的特定解码器序列,预测下一个单词/字符。如果我们不移位解码器序列,则模型学习简单地“复制”解码器输入,因为位置i的目标字/字符将是解码器输入中的字/字符i。因此,通过将解码器输入移位一个位置,我们的模型需要预测仅看到单词/字符1,…,i-1的位置i的目标字/字符在解码器序列中。这可以防止我们的模型学习复制/粘贴任务。我们用句子开头令牌填充解码器输入的第一个位置,因为由于右移,该位置将是空的。类似地,我们将一个句末结尾标记附加到解码器输入序列以标记该序列的结尾,并且它还附加到目标输出语句。

    输出层

    在完全执行解码器层之后,为了将得到的矢量映射到来自词汇表的单词,最后添加全连接层和
    s​​oftmax层。
    线性层是一个简单的完全连接的神经网络,它将解码器堆栈产生的矢量投影到一个更大,更大的矢量中,称为logits矢量。让我们假设我们的模型知道从训练数据集中学到的10,000个独特的英语单词(我们的模型的“输出词汇表”)。这将使logits矢量10,000个细胞宽 - 每个细胞对应于一个唯一单词的得分。这就是我们如何解释模型的输出,然后是线性层。然后,softmax层将这些分数转换为概率(所有正数,所有加起来都为1.0)。选择具有最高概率的单元,并且将与其相关联的单词作为该时间步的输出。

    在这里插入图片描述

    回到BERT

    BERT基于Transformer架构。它是一种深度,双向深度神经网络模型。Google最初发布了两个版本,如下图所示。这里L表示变压器的层数,H表示输出的维数,A表示多头注意的数量。在这两个版本中,前馈大小设置为4层。
    BERTBASE:L = 12,H = 768,A = 12,总参数= 110M
    BERTLARGE:L = 24,H = 1024,A = 16,总参数= 340M
    使用BERT有两个阶段:预训练和微调。在预训练期间,模型在不同的预训练任务上训练未标记的数据。对于微调,首先使用预先训练的参数初始化BERT模型,并使用来自下游任务的标记数据对所有参数进行微调。每个下游任务都有单独的微调模型,即使它们使用相同的预先训练的参数进行初始化。BERT的一个显着特点是它跨越不同任务的统一架构。预训练架构与最终下游架构之间的差异很小。在微调期间,所有参数都经过微调。

    在这里插入图片描述

    BERT训练前流程

    BERT预训练阶段包括两个无监督预测任务,一个是掩蔽语言模型,另一个是下一句预测。
    蒙面语言模型 - 由于双向功能(双向性)和BERT使用的多层自我关注机制的效果,为了训练深度双向表示,一些百分比(本文中为15%)输入令牌的输入被简单地随机掩盖,然后预测那些被屏蔽的令牌。对应于掩模标记的最终隐藏向量被馈送到词汇表上的输出softmax,如在标准LM中。与从左到右的语言模型预训练不同,MLM目标允许表示融合的左侧和右侧的上下文,这使得可以预先训练深度双向变换器。虽然这允许获得双向预训练模型,但缺点是预训练和微调之间存在不匹配,因为在微调期间不会出现[MASK]标记。为了缓解这种情况,作者并不总是用实际的[MASK]令牌替换“蒙面”单词。训练数据生成器随机选择15%的令牌位置进行预测。如果选择了第i个令牌,则将其替换为(1)[MASK]令牌80%的时间(2)随机令牌10%的时间(3)未更改的第i个令牌10%时间。
    下一句话预测 - 。为了训练理解句子关系以及单词之间的语义关系的模型,BERT还预先训练二进制化的下一句预测任务,该任务可以从任何文本语料库中非常容易地生成。为A和B选择一些句子,其中50%的数据B是A的下一个句子,剩余的50%的数据B是在语料库中随机选择的,并学习相关性。添加这种预训练的目的是许多NLP任务(如QA和NLI)需要理解两个句子之间的关系,以便预训练模型能够更好地适应这些任务。

    标记化 - BERT不会将单词视为标记。相反,它看着WordPieces。这意味着一个单词可以分解为多个子单词。这种标记化在处理词汇单词时是有益的,它可以帮助更好地表示复杂的单词。

    BERT模型输入

    BERT的输入可以是单词序列中的单个句子或句子对(例如,[问题,答案])。对于给定的单词,其输入表示可以由三部分嵌入求和组成。嵌入的可视化表示如下所示:

    在这里插入图片描述

    令牌嵌入表示单词向量。第一个字是CLS标志,可用于后续分类任务。对于非分类任务,可以忽略CLS标志。段嵌入用于区分两个句子,因为预训练不仅是语言模型,而且是具有两个句子作为输入的分类任务。位置嵌入编码字顺序。

    用于下游NLP任务的BERT微调

    对于每个下游NLP任务,我们只需将特定于任务的输入和输出插入BERT并对端到端的所有参数进行微调。在输入处,来自预训练的句子A和句子B可以类似于释义中的句子对,蕴涵中的假设前提对,问题回答中的问题 - 通道对等。在输出处,令牌表示被馈送到用于令牌级别任务的输出层,例如序列标记或问题回答,并且[CLS]表示被馈送到输出层以进行分类,例如蕴涵或情绪分析。与预训练相比,微调相对便宜。

    在这里插入图片描述

    BERT用于特征提取

    微调方法不是使用BERT的唯一方法。您可以使用预先训练的BERT创建语境化词嵌入。然后,您可以将这些嵌入提供给您现有的模型 - 这个过程本文显示了在命名实体识别等任务上微调BERT的产量结果。

    在这里插入图片描述

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

    在这里插入图片描述

    展开全文
  • BERT家族:族长BERT

    2020-05-25 16:32:32
    自18年底谷歌BERT问世以后,NLP便逐渐步入bert时代,bert家族儿孙满堂,如RoBERTa、ALBert、ERNIE等等,这些bert们正在给并持续给nlp领域输入无限生机,让人工智能皇冠上的明珠更加光彩夺目,在其光芒的照耀下,人类...
  • bert简介_BERT简介

    2020-08-10 06:10:13
    bert简介BERT, Bi-directional Encoder Representation from Transformer, is a state of the art language model by Google which can be used for cutting-edge natural language processing (NLP) tasks. BERT是...
  • ①AR AE方式结合,通过随机取一句话排列的一种,然后将末尾一定量的词给“遮掩”(和 BERT 里的直接替换 “[MASK]” 有些不同)掉,最后用 AR 的方式来按照这种排列方式依此预测被“遮掩”掉的词。 ②在 BERT 这样...
  • BERT简述

    千次阅读 2018-12-27 11:11:41
    本文从词嵌入出发,一步步介绍Bert出现的背景,故文章前一部分的介绍可能与Bert的相关性不强,但是必不可少。 1、词向量  词向量一直是领先的NLP模型处理语言的主要能力。Word2Vec、Glove等方法已广泛应用于此类...
  • BERT算法

    2020-07-14 02:04:42
    它基于谷歌2017年发布的Transformer架构,通常的Transformer使用一组编码器和解码器网络,而BERT只需要一个额外的输出层,对预训练进行fine-tune,就可以满足各种任务,根本没有必要针对特定任务对模型进行修改。...
  • BERT家族:K-BERT

    2020-05-26 11:24:57
    K-BERT 论文:《K-BERT: Enabling Language Representation with Knowledge Graph》 论文地址:https://arxiv.org/pdf/1909.07606v1 作者/机构:北京大学+腾讯 年份:2019.9 K-BERT主要是为了提升BERT在知识...
  • (作者:陈玓玏 data-master) 一直以来,我自己处理文本分类都是用的正则,但正则需要经常去维护,短信模板如果更新了,就需要考虑把新模板加到正则表达式中。这样其实挺费神的,虽然我们可以...但是关于bert,网上
  • BERT模型

    2020-08-03 20:24:43
    BERT是基于Vaswani et al(2017)的论文"Attention is all you need"中提出的transformer模型构建的多层双向transformoer encoder。就是说BERT只是一个NLP方向的编码器。他能对单独句子进行表征,也可以对问答等进行...
  • bert模型

    2019-03-19 10:14:41
    BERT官方Github地址:https://github.com/google-research/bert,其中对BERT模型进行了详细的介绍,更详细的可以查阅原文献:https://arxiv.org/abs/1810.04805。 BERT本质上是一个两段式的NLP模型。第一个阶段叫做...
  • sentence-BERT

    2021-02-17 15:55:54
    sentence-BERT Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks 工程论文,应用效果很好 在文本相似性任务上,之前的bert系列已经可以达到sota,但是bert要求句对拼接到一起传入模型,这样会造成...
  • 然而,如果想要在加载官方预训练权重的基础上,对bert的内部结构进行修改,那么keras-bert就比较难满足我们的需求了,因为keras-bert为了代码的复用性,几乎将每个小模块都封装为了一个单独的库,比如keras-bert依赖...
  • BERT介绍

    2020-02-20 14:20:31
    BERT模型来自谷歌团队的paper——BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding,它在11个NLP任务中刷新了成绩,效果非常好,非常惊人。但是,这项工作不是很好复现,如果没有...
  • BERT面试

    千次阅读 2020-03-13 22:49:48
    1. BERT 的基本原理是什么? BERT整体是一个自编码语言模型(Autoencoder LM),并且其设计了两个任务来预训练该模型。 第一个任务是采用 MaskLM 的方式来训练语言模型,通俗地说就是在输入一句话的时候,随机地选...
  • BERT原理

    2019-11-07 20:23:13
    BERT使用双向Transformer。OpenAI GPT使用left-to-right的Transformer。ELMo使用训练好的left-to-right和right-to-left的LSTM的拼接为下游任务形成特征。在这3方面中,只有BERT表示在所有层中同时受坐上下文和右上...
  • bert实践:关系抽取解读

    万次阅读 多人点赞 2019-07-31 16:42:46
    前言 bert模型是谷歌2018年10月底公布的,反响巨大,效果不错,在各大比赛上面出类拔萃,...而近一两年提出的ULMFiT,GPT,BERT等都属于模型迁移,说白了BERT 模型是将预训练模型和下游任务模型结合在一起的,核心...
  • BERT微调

    2021-05-11 22:01:28
    bert微调步骤: 首先从主函数开刀: copy run_classifier.py 随便重命名 my_classifier.py 先看主函数: if __name__ == "__main__": flags.mark_flag_as_required("data_dir") flags.mark_flag_as_required...
  • 图解BERT模型:从零开始构建BERT

    千次阅读 多人点赞 2020-06-05 21:07:25
    本文首先介绍BERT模型要做什么,即:模型的输入、输出分别是什么,以及模型的预训练任务是什么;然后,分析模型的内部结构,图解如何将模型的输入一步步地转化为模型输出;最后,我们在多个中/英文、不同规模的数据...
  • bert学习

    2019-09-03 16:51:32
    Bert中文提取词向量GPU 参考网址:https://blog.csdn.net/jufengada9/article/details/90229931 1、环境安装 安装conda 1) 下载 https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh ...
  • BERT小试

    2020-06-16 21:31:58
    2020年6月16日 初次实践,尝试在自己的数据上简单跑Bert fine-tune; 过程参考:https://zhuanlan.zhihu.com/p/50774647 试验设置:将每个triple转化为形如"ptext : vtext"的文本,要求判断两triple间相似程度...
  • Bert预训练模型的使用

    2021-07-07 16:31:16
    pytorch_pretrained_bert的配置使用 pytorch_pretrained_bert ...修改源码 从亚马逊站点下载非常慢,可以将源码中的地址更换为本地文件。 pytorch_pretrained_bert/modeling.py的 40-51行 pytorch_pretraine
  • K-BERT

    2021-02-17 15:57:10
    K-BERT K-BERT: Enabling Language Representation with Knowledge Graph bert在特定领域表现不好 融合KG 借鉴并改进ERNIE 1、知识图谱中的关系信息没有被用到 2、实体向量和词向量是使用不同的方法得到的,...
  • 如何讲解BERT

    2019-12-07 18:59:39
    目录第一点: BERT 预训练词向量模型。Word2vec和GloveELMo 和 ULMFiTOpenAI 的GPT第二点: BERT构架在Transformer之上Transformer 里面的几个关键点: self-attention 机制 如何进行特征提取?第三点: BERT对文本编码...
  • 原博客地址:一文读懂BERT(原理篇) 一、什么是Bert? 二,bert的原理 从创新的角度来看,bert其实并没有过多的结构方面的创新点,其和GPT一样均是采用的transformer的结构,相对于GPT来说,其是双向结构的,而...
  • 基于tensorflow官方代码修改。 环境 Tensorflow:1.13 的Python:3.6 tensorflow2.0会报错。 搜狐比赛 在搜狐这个文本比赛中写了一个基准,使用了bert以及bert + lstm + crf来进行实体识别。 其后只使用BERT的结果...
  • Bert-实战

    2019-09-18 17:08:41
    参考BERT fine-tune 终极实践教程 Bert 实战 bert在主要分为两个任务:一、训练语言模型和预训练部分(run_pretraining.py),二、训练具体任务的fine-turning部分(run_classifier.py适用于分类情况/run_squad.py...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,941
精华内容 2,376
关键字:

bert修改