预训练模型 fine tune 方法小结

  • 2021 年 4 月 12 日
  • AI

还有一些其它杂七杂八的文献以及百度和google上的网友分享的经验之谈。


1、数据层面:

分词算法和pretrained model保持一致没什么问题,

(1)截断问题:使用三种方法,简单取头512个tokens,尾512个tokens,头128+尾382个tokens三种策略(关于超长文本的bert 应用其实有非常多的方法,这里仅仅使用了比较简单的截断)

(2)用下游任务对标的语料继续pretrain一下然后再finetune,因为下游语料的分布可能和训练语料的分布存在差异;还有用不同领域的语料来继续pretrain的。。迷茫。

(3)数据增强,推荐nlp_augment和text attack 这两个library,实现了大部分常见的nlp数据增强的方法,除此之外,还有人通过graph来增强的。

2、layers 层面:

(1) 因为bert的不同layer对于不同下游任务具有不同的适应性,比如k层对A任务效果更好,L层对B任务效果更好,所以做法就是尝试用不同层的输出直接完成下游任务,不一定到最后一个transformer block;

(2) 冻结不同层,仅fine tune部分层

(3)不同层的输出做concat,各种交叉组合balabala

3、输出层面:

sentence bert 中提到比较多策略,mean max pooling或者cls,mean pooling效果据说最好,除此之外,因为bert的layer输出是一个sequece,这和早期文本分类的各种网络结构输入sentence的每个词的embedding的形式一样,所以接各类cnn ,lstm甚至新的self attention结构也没什么问题,可以统一把 cnn,rnn,mean,max,self attention等都看作是pooling(GNN里就把LSTM看作一种pooling了)

4、超参数设置:

(1)learning rate:2e-5,weight decay 不对layer norm和bias做仅对其它weights做(hugging face的trainer的默认策略)克服迁移过程中的灾难性遗忘问题;

(2)分层学习率,类似于CNN,浅层transformer block学习泛化represent,高层学习特定represent,所以越浅则学习率越低,第一个transformer block用2e-5,按照1/0.95的速率增长,越深层学习率越大;

(3)batch size,可承受范围内尽量大,主要为了快,至于效果,说不准。

(4)warm up steps,lr schedule,epochs数量,dropout rate等,太trick,不同paper用的都有一些不太一样,没啥好总结的,建议一开始按照hugging face上官方默认的超参数设置就好,然后根据需要自己微调。

5、多任务学习:

这块看MTDNN比较好,多任务获得很好的效果,简单来说就是多个任务头,多个loss直接简单相加(目前基本上没看到什么好的结果是关于在多任务上做多目标优化得到的),多个任务的选择比较关键,然后一个技巧就是多任务学完再到最终的目标任务上再fine tune一下。

另外还有一大堆针对特定nlp任务做的其它的一些技巧,这部分算了吧,推荐还是看比赛的solution代码以及huggingface上的各种tutorial,最实际效果最好。

最后是个人使用的经验:

1、尽量大batch节约时间,learning rate尽量小,觉得慢就大点学习率+lr schedule慢慢调,大小建议按照官方给的就好了别瞎改;

2、输出pooling效果普遍比仅用cls好;

3、pretrain效果还是可以,下游对标的语料继续pretrain可以找到更好的起点,这个方法还是比较立竿见影的;

4、尽量把torch的性能优化做好,不知道会给你节约多少时间,fp16,deepspeed,DDP,多gpu这类的(这部分放到torch的性能优化总结,都很简单,都封装好了,几行代码就完事儿了)

5、数据永远是第一位,无他,数据增强还是不错的;

6、语料还是需要做一定预处理的,但是做过头了反而损失性能,这很尴尬,至于怎么做预处理,删什么东西,补什么东西,我也总结不了,不同的应用可能做起来效果差很多;

7、过拟合上正则,weight de’cay,dropout,对抗训练之类的,这个和常规的网络优化差不多;

8、尽量多focus在数据上少focus在调参上,bert跑一次普通的机器要跑死,没什么空间给你调太多参数的。