zoukankan      html  css  js  c++  java
  • NLP中的预训练语言模型(二)—— Facebook的SpanBERT和RoBERTa

      本篇带来Facebook的提出的两个预训练模型——SpanBERT和RoBERTa。

    一,SpanBERT

      论文:SpanBERT: Improving Pre-training by Representing and Predicting Spans 

      GitHub:https://github.com/facebookresearch/SpanBERT

      这篇论文中提出了一种新的mask的方法,以及一个新损失函数对象。并且讨论了bert中的NSP任务是否有用。接下来SpanBERT是如何预训练的,具体如下图所示:

        

       如上图所示,首先这里的mask策略是span mask。具体的做法是首先从一个几何分布中采样span的长度,且限制最大长度为10,然后再随机采样(如均匀分布) span的初始位置。整个训练任务就是预测mask的token,另外mask的比例问题和bert中类似。但是在这里引入了两个损失对象,$L_{MLM}$ 和$L_{SBO}$,$L_{MLM}$和bert中的一样,而这个$L_{SBO}$是只通过span的边界处的两个token来预测span中mask的词,公式表示如下:

        

       函数$f(.)$表示如下:

        

      除了这些之外还有两个策略,一是动态mask,在bert中是在数据预处理阶段对一条序列随机不同的mask 10次,而在这里是每次epoch时对序列使用不同的mask。二是bert中会在数据预处理阶段生成10%的长度短于512的序列,而在这里不做这样的操作,只是对一个document一直截取512长度的序列,但最后一个序列长度可能会小于512。另外将adam中的$epsilon$设置为1e-8。作者根据这两个策略从新训练了一个bert模型,同时去除NSP任务只使用单条序列训练了一个bert模型。因此作者给出了四个模型的性能对比:

      Google BERT:谷歌开源的bert

      Our BERT:基于上面两个策略训练出来的bert

      Our BERT-1seq:基于上面两个策略,且去除NSP任务的bert

      SpanBERT:本篇论文提出的模型

      作者给出的第一个性能测试的表格是在SQuAD数据集上,

        

       SpanBERT是有很大的提升的,另外去除NSP任务也有提升,作者认为NSP任务使得单条序列的长度不够,以至于模型无法很好的捕获长距离信息。另外在其他的抽取式QA任务上也有很大的提升

        

       个人认为SpanBERT在抽取式QA任务上能取得如此大的提升,是因为SpanBERT中构造的任务,尤其是SBO任务实际上是有点贴合抽取式QA任务的。

      在其他任务上SpanBERT也有一些提升,但是没有在抽取式QA任务上提升这么大,此外作者也做实验表示随机mask span的效果是要优于mask 实体或者短语的。

      综合来说,SpanBERT在抽取式QA上的效果表现优异,在抽取式QA上是值得尝试的。

    二,RoBERTa

      论文:RoBERTa: A Robustly Optimized BERT Pretraining Approach

      GitHub:https://github.com/brightmart/roberta_zh

      本篇论文主要是在bert的基础上做精细化调参,可以看作是终极调参,最后性能不仅全面碾压bert,且在大部分任务上超越了XL-Net。

       总结下,主要有以下六处改变的地方:

      1)Adam算法中的参数调整,$epsilon$由1e-6改成1e-8,$eta_2$由0.999改成0.98。

      2)使用了更多的数据,从16GB增加到160GB。

      3)动态mask取代静态mask。

      4)去除NSP任务,并采用full-length 序列。

      5)更大的batch size,更多的训练步数。

      6)用byte-level BPE取代character-level BPE。

      接下来我们来结合作者的实验看看。首先作者任务调整adam的参数是可以使得训练更加稳定且也能取得更好的性能,但并没有给出实验数据。增加数据提升性能是毋庸置疑的。

      动态mask

      在bert中是在数据预处理时做不同的mask 10次,这样在epochs为40的时候,平均每条mask的序列会出现4次,作者在这里使用动态mask,即每次epochs时做一次不同的mask。结果对比如下:

        

       说实话,没觉得有多大提升,毕竟我们在训练模型的时候,一条数据也会被模型看到多次。

      模型输入

      对比了有无NSP任务的性能,以及不同的序列输入的性能,作者在这里给出了四种输入形式:

      1)SEGMENT-PAIR + NSP:两个segment组成句子对,并且引入NSP任务

      2)SENTENCE-PAIR + NSP:两个sentence组成句子对,并且引入NSP任务,总长可能会比512小很多。

      3)FULL-SENTENCES:有多个完成的句子组成,对于跨文档的部分,用一个标识符分开,但是总长不超过512,无NSP任务

      4)DOC-SENTENCES:有多个完整的句子组成,但是不跨文档,总长不超过512

      性能如下:

        

       显然直接用句子对效果最差,作者认为主要时序列长度不够,导致模型无法捕捉长距离信息。并且去除NSP任务效果也有所提升。

      更大的batch size,更多的训练次数

      作者认为适当的加大batch size,既可以加速模型的训练,也可以提升模型的性能。

        

       之后作者在8k的batch size下又增大训练次数

        

      从实验中可以看出采用更大的训练次数,性能也是有不小的提升的。并且可以看到即使在训练数据差不多的情况下,RoBERTa也是要优于BERT的。

      总之RoBERTa是一个调参成功的BERT,在诸多任务上全面超越bert,大部分超越XL-Net。

        

  • 相关阅读:
    Java多线程编程核心技术---对象及变量的并发访问(二)
    Java多线程编程核心技术---对象及变量的并发访问(一)
    Java多线程编程核心技术---Java多线程技能
    普通浏览器GET请求与Ajax的GET请求的区别
    【python】-- 面向对象引子、概念
    【python】-- json & pickle、xml、requests、hashlib、shelve、shutil、configparser、subprocess
    【python】-- 内置函数、软件目录开发规范(代码编码风格)
    【python】-- 装饰器、迭代器、生成器
    【python】-- 递归函数、高阶函数、嵌套函数、匿名函数
    【python】-- 函数非固定参数,返回值(return)
  • 原文地址:https://www.cnblogs.com/jiangxinyang/p/11528215.html
Copyright © 2011-2022 走看看