R-Drop:提升有监督任务性能最简单的方法

2022-04-01 17:39:09 浏览数 (1)

作者 | 对白 整理 | 对白的算法屋 编者寄语:

在四种数据增强方法中,R-Drop在美团小样本学习场景的效果最佳。

卷友们好,我是对白。

关注NLP新进展的读者,想必对四月份丹琦女神发布的SimCSE印象颇深,它通过简单的“Dropout两次”来构造正样本进行对比学习,达到了无监督语义相似度任务的全面SOTA。无独有偶,微软在六月底发布的论文《R-Drop: Regularized Dropout for Neural Networks》提出了R-Drop,它将“Dropout两次”的思想用到了有监督任务中,每个实验结果几乎都取得了明显的提升

我在看完论文后,感觉它就是一个训练的思想,可以套用到任何有监督/半监督的训练中,是一种很通用的方法,实践意义很强。相信大伙看完以后,在内卷的道路上又可以领先别人一步了(真是太卷了QAQ)。

一、R-Drop方法介绍

从结果上来看,SimCSE就是希望Dropout对模型结果不会有太大影响,也就是模型输出对Dropout是鲁棒的。所以很明显,“Dropout两次”这种思想是可以推广到一般任务的,这就是R-Drop(Regularized Dropout)。

通常,给定一个样本集合 ,深度学习算法会学习到如下的负对数似然损失:

同时,为了避免模型过拟合,我们通常使用诸如 Dropout 等较为成熟的正则化策略。而作者的这篇文章就抓住了 Dropout 做了一个可推广的简单粗暴的优化方法

首先,引入一个可接受的理念,即同样的输入,同样的模型,分别走过两个 Dropout 得到的将是两个不同的分布,近似将这两个路径网络看作两个不同的模型网络,如下图所示。

基于此,这两个不同的模型产生的不同分布可以表示为 和 、 。而这时的Loss分为两个部分即交叉熵部分:

KL散度部分,而KL散度的作用是希望不同Dropout的模型输出尽可能一致:

最后两个Loss加权:

其中 为超参数根据自己的任务需要调整不同的参数来应对,思想简单明了。

在训练过程中,为了节省训练时间,并不是将同一个输入输入两次,而是将输入句子复制一遍,然后拼接到一起, ,这样就相当于将batch size扩大了一倍,这个可以节省大量的训练时间,当然相比于原始的模型,这个会使得每个step的训练时间增加了,因为模型的训练复杂度提高了,所以需要更多的时间去收敛。训练如下:

这是一种思想,无论是文本分类任务、还是序列标注任务文本生成任务图像任务等,无论你的backbone模型是BERTXLNET,还是CNNRNN,都可以引进这种思想,把交叉熵损失换成任务对应的损失即可,因此,都可以把R-Drop加入到你手头的任务中进行尝试

作者在附录B中,通过数学证明,R-Drop通过引入同一个样本,经过同一个模型的不同Dropout,输出的概率要尽可能相等的优化目标,等价于令模型的所有参数尽可能相等的正则化约束,具体的证明可以看论文里面的推导。

二、下游任务实验

5个任务(机器翻译任务、生成式摘要任务、NLU任务、语言模型任务、图像分类任务),共18个数据集上都取得不俗的表现,从实验的结果来看,引入R-Drop都能给指标带来1%~10%的提升。下面是一些实验的截图。

机器翻译任务

‍‍‍‍‍‍‍‍‍‍‍‍‍

自然语言理解任务

生成式摘要任务

语言模型任务

图像分类任务

三、个人实验

可以看到,R-Drop里面的超参就是Dropout率和 ,实验部分的代码我正在写,准备拿中文GLUE数据集来验证,待实验做好,再补充这一部分。

其实把它引入到你自己的任务中来也很简单,因为R-Drop是一种通用的有监督任务方法,甚至在半监督中都有良好的性能。加入几行代码即可把R-Drop引入到你的任务中。

代码语言:javascript复制
import torch.nn.functional as F

# define your task model, which outputs the classifier logits
model = TaskModel()

def compute_kl_loss(self, p, q pad_mask=None):
    
    p_loss = F.kl_div(F.log_softmax(p, dim=-1), F.softmax(q, dim=-1), reduction='none')
    q_loss = F.kl_div(F.log_softmax(q, dim=-1), F.softmax(p, dim=-1), reduction='none')
    
    # pad_mask is for seq-level tasks
    if pad_mask is not None:
        p_loss.masked_fill_(pad_mask, 0.)
        q_loss.masked_fill_(pad_mask, 0.)

    # You can choose whether to use function "sum" and "mean" depending on your task
    p_loss = p_loss.sum()
    q_loss = q_loss.sum()

    loss = (p_loss   q_loss) / 2
    return loss

# keep dropout and forward twice
logits = model(x)

logits2 = model(x)

# cross entropy loss for classifier
ce_loss = 0.5 * (cross_entropy_loss(logits, label)   cross_entropy_loss(logits2, label))

kl_loss = compute_kl_loss(logits, logits2)

# carefully choose hyper-parameters
loss = ce_loss   α * kl_loss

四、总结

给我感觉,R-Drop在接下来一段时间,会不会成为竞赛拿奖的一种标配?因为从论文里的实验可以看出,基本引入R-Drop都会带来1 ~ 2个点的提升。对于工程上来说嘛,就可以把引入R-Drop当成一种常规操作,超参不多,慢慢调,总会带来一点提升,唯一的牺牲就是增加一点训练时间,但是并不会增加线上应用时的推理时间。

五、美团经验之谈

本质上来说,R-Drop与MixUp、Manifold-MixUp和Adversarial Training(对抗训练)一样,都是一种数据增强方法,在小样本学习场景中用的非常多。小样本学习在美团点评业务上的Benchmark效果对比中,R-Drop的结果也是优于其它三种数据增强方法,小伙伴们赶紧用起来吧。

你好,我是对白,硕士毕业于清华,现大厂算法工程师,拿过八家大厂的SSP级以上offer。

高中荣获全国数学和化学竞赛二等奖。

本科时独立创业五年,成立两家公司,并拿过总计三百多万元融资(已到账),项目入选南京321高层次创业人才引进计划。创业做过无人机、机器人和互联网教育,保研后选择退居为股东。

我每周至少更新三篇原创,分享自己的算法技术、创业心得和人生感悟。

0 人点赞