深度学习笔记之BERT(三)RoBERTa

ops/2024/11/29 2:19:24/

深度学习笔记之RoBERTa

  • 引言
    • 回顾:BERT的预训练策略
    • RoBERTa训练过程分析
      • 静态掩码与动态掩码的比较
      • 模型输入模式与下一句预测
      • 使用大批量进行训练
      • 使用Byte-pair Encoding作为子词词元化算法
      • 更大的数据集和更多的训练步骤
    • RoBERTa配置

引言

本节将介绍一种基于 BERT \text{BERT} BERT改进优化的预训练方法—— RoBERTa \text{RoBERTa} RoBERTa

回顾:BERT的预训练策略

BERT \text{BERT} BERT的预训练策略包含两个:

  • 掩码语言模型训练 ( Masked Language Model,MLM ) (\text{Masked Language Model,MLM}) (Masked Language Model,MLM):将句子中一部分词语进行掩码标记,即使用 [ MASK ] [\text{MASK}] [MASK]对被掩码的词语进行替换。并将掩码部分的长度控制在总句子长度的 15 15 15%。对于一个已被预期处理的示例句子:
    [ [ CLS ] , P a r i s , i s , a , b e a u t i f u l , c i t y , [ SEP ] , I , l o v e , P a r i s ] [[\text{CLS}],Paris,is,a,beautiful,city,[\text{SEP}],I,love,Paris] [[CLS],Paris,is,a,beautiful,city,[SEP],I,love,Paris]
    掩码标记后的结果示例为:
    [ [ CLS ] , P a r i s , i s , a , [ MASK ] , c i t y , [ SEP ] , I , l o v e , [ MASK ] ] [[\text{CLS}],Paris,is,a,[\text{MASK}],city,[\text{SEP}],I,love,[\text{MASK}]] [[CLS],Paris,is,a,[MASK],city,[SEP],I,love,[MASK]]
    即便在 BERT \text{BERT} BERT中使用80-10-10规则对 BERT \text{BERT} BERT的预训练进行泛化,但实际上它依然是静态掩码:这些工作均是在数据预处理部分执行的,在训练过程中,每个 [ MASK ] [\text{MASK}] [MASK]部分在句子中的位置是固定的。

  • 下句预测 ( Next Sentence Prediction,NSP ) (\text{Next Sentence Prediction,NSP}) (Next Sentence Prediction,NSP):样本集是由两个连接的文档片段 Segment-1,Segment-2 \text{Segment-1,Segment-2} Segment-1,Segment-2组成,并以 50 50 50%的概率:

    • 在同一文档中连续采样
    • 不同的文档中采样;

    并对采样结果 Segment-1,Segment-2 \text{Segment-1,Segment-2} Segment-1,Segment-2对应的如下格式中:
    [ [ CLS ] , Segment-1 , [SEP] , Segment-2 , [SEP] ] [[\text{CLS}],\text{Segment-1},\text{[SEP]},\text{Segment-2},\text{[SEP]}] [[CLS],Segment-1,[SEP],Segment-2,[SEP]]
    [ CLS ] [\text{CLS}] [CLS]对应的 BERT \text{BERT} BERT输出 R [CLS] \mathcal R_{\text{[CLS]}} R[CLS]使用 Softmax \text{Softmax} Softmax进行二分类(有关联/无关联)任务。

RoBERTa_23">RoBERTa训练过程分析

静态掩码与动态掩码的比较

对于 BERT \text{BERT} BERT这种现象, RoBERTa \text{RoBERTa} RoBERTa先采用复制数据的方法进行补救:

  • 将一个句子复制 10 10 10份,并将 10 10 10个句子进行随机掩码标记
    S 1 : [ [ CLS ] , P a r i s , i s , a , [ MASK ] , c i t y , [ SEP ] , I , l o v e , [ MASK ] ] S 2 : [ [ CLS ] , P a r i s , [ MASK ] , a , b e a u t i f u l , c i t y , [ SEP ] , I , l o v e , P a r i s ] ⋮ S 10 : [ [ CLS ] , [ MASK ] , i s , a , b e a u t i f u l , [ MASK ] , [ SEP ] , I , l o v e , P a r i s ] \begin{aligned} & \mathcal S_1:[[\text{CLS}],Paris,is,a,[\text{MASK}],city,[\text{SEP}],I,love,[\text{MASK}]] \\ & \mathcal S_2:[[\text{CLS}],Paris,[\text{MASK}],a,beautiful,city,[\text{SEP}],I,love,Paris] \\ & \quad \vdots \\ & \mathcal S_{10}:[[\text{CLS}],[\text{MASK}],is,a,beautiful,[\text{MASK}],[\text{SEP}],I,love,Paris] \end{aligned} S1:[[CLS],Paris,is,a,[MASK],city,[SEP],I,love,[MASK]]S2:[[CLS],Paris,[MASK],a,beautiful,city,[SEP],I,love,Paris]S10:[[CLS],[MASK],is,a,beautiful,[MASK],[SEP],I,love,Paris]
  • 对模型进行 40 Epoch \text{40 Epoch} 40 Epoch的全数据遍历训练,在每个 Epoch \text{Epoch} Epoch训练中,句子被掩盖标记都不同:
    Epoch 1: S 1 Epoch 2: S 2 ⋮ Epoch 10: S 10 Epoch 11: S 1 Epoch 12: S 2 ⋮ Epoch 40: S 10 \begin{aligned} & \text{Epoch 1:} \quad \mathcal S_1 \\ & \text{Epoch 2:} \quad \mathcal S_2 \\ & \quad \vdots \\ & \text{Epoch 10:} \quad \mathcal S_{10} \\ & \text{Epoch 11:} \quad \mathcal S_{1} \\ & \text{Epoch 12:} \quad \mathcal S_{2} \\ & \quad \vdots \\ & \text{Epoch 40:} \quad \mathcal S_{10} \\ \end{aligned} Epoch 1:S1Epoch 2:S2Epoch 10:S10Epoch 11:S1Epoch 12:S2Epoch 40:S10
    这相当于每一种 MASK \text{MASK} MASK模式被执行了 4 4 4。虽然这种方法起到很好的泛化作用,但其本质上依然是静态掩码

动态掩码并没有在预处理阶段对数据进行 MASK \text{MASK} MASK,而是将数据导入模型过程中进行随机 MASK \text{MASK} MASK。这与上面复制数据的方法相比,它的泛化性更强。因为尤其在训练的 Epoch \text{Epoch} Epoch较大时,静态掩码由于会使同一份掩码结果训练多次,导致在训练过程中机械地记住这个规律

下面是原文中静态掩码与动态掩码在同一任务中的对比情况。在一些任务中,动态掩码的效果略优于静态掩码
静态vs动态

模型输入模式与下一句预测

BERT \text{BERT} BERT中的 NSP \text{NSP} NSP任务旨在句子层面有更优秀的理解,因此 RoBERTa \text{RoBERTa} RoBERTa针对 NSP \text{NSP} NSP任务设计了几种训练格式,来验证 NSP \text{NSP} NSP策略是否有效:

  • Segment-pair +NSP: \text{Segment-pair +NSP:} Segment-pair +NSP: 原始 BERT \text{BERT} BERT使用的模式,其中每个段落 ( Segment ) (\text{Segment}) (Segment)中可能包含多个句子 ( Sentence ) (\text{Sentence}) (Sentence),但 Token \text{Token} Token总长度小于 512 512 512
  • Sentence-pair + NSP: \text{Sentence-pair + NSP:} Sentence-pair + NSP: 将输入段落对改为句子对,正负样本的采样方式分别是从文档中连续采样文档中单独采样。由于输入句子对 Token \text{Token} Token长度明显小于 512 512 512,因而通过增加 Batch size \text{Batch size} Batch size使 Token \text{Token} Token总量与 Segment-pair \text{Segment-pair} Segment-pair相似,并保留了 NSP \text{NSP} NSP策略。
  • Full-sentence: \text{Full-sentence:} Full-sentence: 从一个/多个文档中采样出连续的完整句子 Token \text{Token} Token总长度不超过 512 512 512,并且允许超出文档边界。超出文档边界是指:当采样达到一个文档的末尾时,可以从下一个文档中继续进行采样作为该输入的一部分,但需要在文档之间加入一个额外分隔符,并且该实验删除了 NSP \text{NSP} NSP策略
  • Doc-sentence: \text{Doc-sentence:} Doc-sentence: Full-sentence \text{Full-sentence} Full-sentence采样方式相似,但是不允许超出文档边界。相比于 Full-sentence \text{Full-sentence} Full-sentence,它的 Token \text{Token} Token长度有可能偏少,因此同样通过增加 Batch size \text{Batch size} Batch size使 Token \text{Token} Token总量与 Full-sentence \text{Full-sentence} Full-sentence相似,并同样删除了 NSP \text{NSP} NSP策略

下面是原文对四种训练格式在若干任务中的效果:
4-method

  • 比较使用 NSP \text{NSP} NSP策略 Segment-pair \text{Segment-pair} Segment-pair Sentence-pair \text{Sentence-pair} Sentence-pair格式,发现使用 Segment \text{Segment} Segment效果明显由于 Sentence \text{Sentence} Sentence,原因可能是模型很难从单句中学习到长依赖关系
  • 使用 NSP \text{NSP} NSP策略和未使用 NSP \text{NSP} NSP的角度进行比较,发现:删除 NSP \text{NSP} NSP策略能够略微提高下游任务的性能
  • Doc-sentence \text{Doc-sentence} Doc-sentence略优于 Full-sentence \text{Full-sentence} Full-sentence。但由于 Doc-sentence \text{Doc-sentence} Doc-sentence长度不固定,导致 Batch size \text{Batch size} Batch size存在变化,因而后续实验均使用 Full-sentence \text{Full-sentence} Full-sentence格式进行比较。

使用大批量进行训练

原始 BERT \text{BERT} BERT使用 Batch size=256 \text{Batch size=256} Batch size=256进行训练,训练步骤数量为 1M \text{1M} 1M。在保持总计算量基本不变的情况下,将 Batch size \text{Batch size} Batch size 256 256 256扩展至 2K,8K \text{2K,8K} 2K,8K;对应训练步骤缩减至 125K,31K \text{125K,31K} 125K,31K;并相应地调整学习率 ( lr ) (\text{lr}) (lr)
large batch size
可以发现: Batch size \text{Batch size} Batch size 2K \text{2K} 2K时表现效果最好。但考虑到并行更容易,作者均选择 8K \text{8K} 8K作为后续实验的 Batch size \text{Batch size} Batch size

使用Byte-pair Encoding作为子词词元化算法

RoBERTa \text{RoBERTa} RoBERTa并没有使用 Unicode \text{Unicode} Unicode作为子词次元 ( Subword Unit ) (\text{Subword Unit}) (Subword Unit),而是使用 Bytes \text{Bytes} Bytes进行替代。这种方式可以编码任何输入文本,并且不会引入任何 Unknown \text{Unknown} Unknown标记,这会使 Vocab size \text{Vocab size} Vocab size变得更大,参数更多 ( 30 K ⇒ 50 K ) (30\text{K} \Rightarrow 50\text{K}) (30K50K)

以句子: It was a great day \text{It was a great day} It was a great day为例,对应 RoBERTa \text{RoBERTa} RoBERTa模型的标记结果如下:
[ it , G ˙ was , G ˙ a , G ˙ great , Gday ˙ ] [\text{it},\dot{\text{G}}\text{was},\dot{\text{G}}\text{a},\dot{\text{G}}\text{great},\dot{\text{G}\text{day}}] [it,G˙was,G˙a,G˙great,Gday˙]
其中 G ˙ \dot{\text{G}} G˙表示一个空格 RoBERTa \text{RoBERTa} RoBERTa词元分析其将所有空格替换为 G ˙ \dot{\text{G}} G˙字符。再以一个句子为例: I had a sudden epiphany \text{I had a sudden epiphany} I had a sudden epiphany(我灵光一闪):
[ I , G ˙ had , G ˙ a , G ˙ sudden , G ˙ ep , iphany ] [\text{I},\dot{\text{G}}\text{had},\dot{\text{G}}\text{a},\dot{\text{G}}\text{sudden},\dot{\text{G}}\text{ep},\text{iphany}] [I,G˙had,G˙a,G˙sudden,G˙ep,iphany]
这种标注结果是因为:未从词表中找到单词 epiphany \text{epiphany} epiphany,从而将其拆解未 ep \text{ep} ep iphany \text{iphany} iphany两部分。

更大的数据集和更多的训练步骤

RoBERTa \text{RoBERTa} RoBERTa延用了 BERT-large \text{BERT-large} BERT-large结构 ( L=24,A=16,H=1024 ) (\text{L=24,A=16,H=1024}) (L=24,A=16,H=1024),在 Batch size \text{Batch size} Batch size固定为 8K \text{8K} 8K的情况下,作者进行一系列对比实验:
有点降维打击的意思~数据量大意味着信息更丰富,效果好也在情理之中~
more data more steps
可以发现:

  • 即便没有增加数据, RoBERTa \text{RoBERTa} RoBERTa依旧比 BERT-large \text{BERT-large} BERT-large结果优秀。当然总计算量增加了很多 ( Batch size=8K,steps:31K ⇒ 100 K ) (\text{Batch size=8K,steps:31K} \Rightarrow 100\text{K}) (Batch size=8K,steps:31K100K),但这并没有带来过拟合的问题。
  • 在训练数据基础上加上 additional Data \text{additional Data} additional Data效果进一步提升;
  • 训练过程很稳定:即便 steps=500K \text{steps=500K} steps=500K,依然没有出现过拟合的现象。

RoBERTa_87">RoBERTa配置

综合上面的比对结果,作者给出 RoBERTa \text{RoBERTa} RoBERTa的基本配置:

  • 动态掩码;
  • 策略: Full-sentence without NSP \text{Full-sentence without NSP} Full-sentence without NSP
  • 更大的 Batch size \text{Batch size} Batch size
  • 使用更大 Vocab size \text{Vocab size} Vocab size,字节级别的 Byte-pair Encoding \text{Byte-pair Encoding} Byte-pair Encoding进行训练
  • 训练过程中使用更多的 steps \text{steps} steps additional Data \text{additional Data} additional Data

GLUE,SQuAD,RACE \text{GLUE,SQuAD,RACE} GLUE,SQuAD,RACE等任务中的表现结果如下:

  • GLUE \text{GLUE} GLUE
    GLUE-res
  • SQuAD \text{SQuAD} SQuAD
    squad-res
  • RACE \text{RACE} RACE
    race-res

Reference \text{Reference} Reference
论文链接
《BERT基础教程——Transformer大规模实战》


http://www.ppmy.cn/ops/137534.html

相关文章

后端接受大写参数(亲测能用)

重要点引入包别引用错了 import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data;JsonSerialize Data public class Item {JsonProperty(value "Token")private String token…

第144场双周赛题解:两个字符串得切换距离

两个字符串得切换距离 1、题目描述 给你两个长度相同的字符串 s 和 t ,以及两个整数数组 nextCost 和 previousCost 。 一次操作中,你可以选择 s 中的一个下标 i ,执行以下操作 之一 : 将 s[i] 切换为字母表中的下一个字母&am…

Python Flask快速开发网站

在Web开发领域,Python拥有多种优秀的Web框架,例如Django、Flask、Pyramid等。其中Flask是一个微型框架,核心代码非常精简,只包含了Web应用最基本的功能。这使得Flask非常轻量级,容易上手,适合快速开发小型Web应用。本文将介绍如何使用Flask快速搭建一个简单的网站。 © ivw…

基于python+django+vue.js开发的停车管理系统

功能介绍 平台采用B/S结构,后端采用主流的Python语言进行开发,前端采用主流的Vue.js进行开发。 功能包括:车位管理、会员管理、停车场管理、违规管理、用户管理、日志管理、系统信息模块。 源码地址 https://github.com/geeeeeeeek/pytho…

Vue前端面试进阶(五)

使用Element UI开发的实际项目 在实际项目中,我使用Element UI来快速构建用户界面。Element UI是一套为开发者、设计师和产品经理准备的基于Vue 2.0的桌面端组件库,它提供了丰富的UI组件,极大地提高了开发效率。然而,在使用过程中…

【linux】手搓线程池

【linux】进程池 线程池: 一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着 监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利…

替代Postman ,17.3K star!

现在,许多人都朝着全栈工程师的方向发展,API 接口的编写和调试已成为许多开发人员必备的技能之一。 工欲善其事,必先利其器。拥有一款优秀的 API 工具对于任何工程师来说都是极为重要的,它能够帮助我们高效地完成各种开发任务。 …

什么是JSON,有什么特点

什么是 JSON? JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。它基于 JavaScript 的子集,但独立于语言,被广泛用于服务器与 Web 应…