BERT从零详细解读:如何微调BERT,提升BERT在下游任务中的效果

BERT从零详细解读:如何微调BERT,提升BERT在下游任务中的效果_第1张图片
a)是句子对的分类任务
b)是单个句子的分类任务
c) 是问答任务
d)是序列标注任务

首先我自己最常用的就是:文本分类、序列标注和文本匹配。
这四个都是比较简单的,我们来看d)序列标注,其实就是把所有的token输出,做了一个softmax,去看它属于实体中的哪一个。对于单个样本,它的一个文本分类就是使用CLS这边,第一个CLS的输出,去做一个微调,做一个二分类,或者是多分类。
a)这个其实本质是一个文本匹配的一个任务,文本匹配就是把两个句子拼接起来,去判断它是否相似。左上角也是用CLS输出判断,0不相似,1相似。基本上其实就是这样,其实在下游任务中它使用还是比较简单的。

如何提升BERT在下游任务中的效果或者是表现。因为我们在实际应用中,很少会让你自己去从头训练一个bert。一般都是用训练好的,就是大公司放出来的bert,然后我们自己在自己的任务中做一些微调。

很多朋友的做法都是,先获取谷歌中文或者是其它公司的bert,然后基于自己的任务数据去做微调。但是我们想要更好的性能的话,现在有很多tirck需要去做。

首先,我想提的第一点就是去做 Post training。

四步骤

比如做微博文本情感分析:

  1. 在大量通用预料上训练一个LM(pretrain);- 中文谷歌BERT
  2. 在相同领域上继续训练LM(Domain transfer); - 在大量微博文本上继续训练这个BERT
  3. 在任务相关的小数据上继续训练LM(Task transfer);- 在微博情感文本上(有的文本不属于情感分析的范畴)
  4. 在任务相关数据上做具体任务(Fine-tune)。

一般经验是,先做Domain transfer,再进行 Task transfer,最后Fine-tune 性能是最好的。

如何再相同领域数据中进行further pre-training

  1. 动态mask:就是每次epoch去训练的时候mask,而不是一直使用同一个。

    bert在训练的时候使用的是固定的mask,就是把文本mask之后存在本地,然后每次训练的时候都是使用同一个文件,也就是说每次训练的时候我们使用的都是同样的mask标志。比如之前的例子【我爱吃饭】,每次训练的时候都是mask掉了这个”吃“,这样其实不太好。然后动态mask呢,就是每个epoch训练之前,去对数据进行mask。
    刚才说bert一直使用同一套mask,也不太准确,它是有做一些改进,他有复制一些文本,大家具体去看一下论文。

  2. n-gram mask:其实比如ERINE 和 SpanBert都是类似于做了实体词的mask。

    我们可以退一步,就是如果你自己训练的时候,你没有特别准确的实体词,你可以不做实体词的mask,你可以做n-gram mask.

我们在做的时候参数一定要设置得特别的好,Batch size其实16,32,64,128影响不太大;Learning rate(Adam)5e-5,3e-5,2e-5,尽可能小一点避免灾难性遗忘;在微调的时候number of epochs,一般是3、4个,一般不会太大;weighted decay修改后的adam,使用warmup,搭配线性衰减,这个是比较重要的;

还有就是比如在预训练的时候做数据增强(一些简单的EDA)、自蒸馏、外部知识的融入(比如融入知识图谱的知识,或者加一些实体词的信息),这些都可以,不过比较吃机器。

你可能感兴趣的:(NLP,自然语言处理)