技术标签: 自然语言处理
论文:Improving BERT Fine-Tuning via Self-Ensemble and Self-Distillation
链接:https://arxiv.org/abs/2002.10345
作者:Yige Xu, Xipeng Qiu, Ligao Zhou, Xuanjing Huang
本文提出了一种自集成和自蒸馏的fine-tuning方法,在不引入外部资源和不显著增加训练时间的前提下,可以进一步增强fine-tuning的效果。
自蒸馏的前世今生——what、why、how?
知识蒸馏(Knowledge Distillation)指的是将预训练好的教师模型(Teacher Model)的知识通过蒸馏的方式迁移到学生模型(Student Model)。自蒸馏(Self-Distillation)则指的是自己蒸馏到自己,Teacher Model就是Student Model的集成版本,称为自集成(Self-Ensemble)。集成模型在是刷榜利器,因此我们希望在训练过程中不同time step的模型也可以集成。为了不增加训练开销,我们选择一种参数平均的方式来进行自集成。
与同期的工作FastBERT的自蒸馏(高层蒸馏到底层)不同,本文的自蒸馏指的是过去time step蒸馏到当前time step。在Fine-tune过程中,目标函数除了有来自标签的监督信号以外,还有来自过去time step的监督信号。本文的自蒸馏是为了进一步提高准确率而不是模型压缩。
I. 在一般的Fine-tune流程当中,我们通常只关注某一个epoch结束之后的模型参数,而不关心在Fine-tune过程中某个time step的参数。那么Fine-tune的中间过程是否有什么值得我们挖掘的信息呢?
II. 在一般的训练过程当中,我们通常将数据集划分成一个个mini-batch,依次通过模型进行训练。如果某一个mini-batch的数据质量不过关,可能会将模型参数带歪,因此是否可以寻找一种方式来减缓“带歪”的趋势呢?
III.好的teacher可以教出更好的学生,而好的学生可以进一步集成为更好的教师,通过迭代可以进行自我增强。
在本文中,我们提出了两种自蒸馏的方式:Self-Distillation-Averaged(SDA)和Self-Distillation-Voted(SDV)。在SDA中,我们首先计算出过去K个time step参数的平均值作为Teacher Model。在SDV中,我们将过去K个time step的参数视为K个Teacher Model。
SDA的目标函数计算方式如下:
£ θ ( x , y ) = C E ( B E R T ( x , θ ) , y ) + λ M S E ( B E R T ( x , θ ) , B E R T ( x , θ ˉ ) ) \pounds _{\theta }(x,y)=CE(BERT(x,\theta ),y)+\lambda MSE(BERT(x,\theta ),BERT(x,\bar{\theta})) £θ(x,y)=CE(BERT(x,θ),y)+λMSE(BERT(x,θ),BERT(x,θˉ))
其中 θ ˉ = 1 K ∑ k = 1 K θ t − k \bar{\theta} = \frac{1}{K}\sum_{k=1}^{K}\theta_{t-k} θˉ=K1∑k=1Kθt−k
SDV的目标函数计算方式如下:
£ θ ( x , y ) = C E ( B E R T ( x , θ ) , y ) + λ M S E ( B E R T ( x , θ ) , 1 K ∑ k = 1 K B E R T ( x , θ t − k ) ) \pounds _{\theta }(x,y)=CE(BERT(x,\theta ),y)+\lambda MSE(BERT(x,\theta ),\frac{1}{K}\sum_{k=1}^{K}BERT(x,\theta_{t-k})) £θ(x,y)=CE(BERT(x,θ),y)+λMSE(BERT(x,θ),K1k=1∑KBERT(x,θt−k))
更稳定的训练过程
我们在SNLI数据集当中随机抽取了1500条训练数据组成一个迷你训练集。不改变模型参数初始化,只改变数据训练顺序。通过在这个迷你训练集上的实验,我们发现SDA和SDV加持下的训练更为稳定,准确率的均值更高、方差更低。
更高的准确率
在SDA和SDV加持下,可以有效提升在下游任务Fine-tune BERT的性能。
表驱动是一种设计方法,使用表驱动替代程序中复杂的if else或者switch case逻辑。使用这种方法可以使程序的逻辑简洁、直白并且易于维护。先举个例子让大家认识表驱动,有这样的需求:写一个程序计算顾客租书的费用,书店有租书业务,把图书分为三类:漫画书,儿童书,普通书。普通书的租书的价格是1元/天,儿童书是1.5元/天,漫画书的价格是1.8元/天。#define ORDIN
Thread类的stop()方法终止线程执行。当线程停止,它就不能通过start()方法重新启动。语法public final void stop()public final void stop(Throwable obj)参数obj:要抛出的Throwable对象。异常SecurityException:如果当前线程无法修改线程,则抛出此异常。示例public class JavaStopExp..._java thread.stop
据百科描述,Ubuntu是基于Debian的Linux系统,而Debian系统的软件是使用APT和dpkg进行管理。dpkg是"Debian Packager"的简写,是一个底层的软件包管理工具。下面小编要为大家带来的是在Ubuntu中使用dpkg命令卸载软件的方法,一起去看看吧!本经验以卸载Ubuntu下的办公软件libreoffice为例子,演示怎样使用dpkg进行卸载软件。查看安装的软件1、..._dpkg remove
Mybatis的批量插入这里有http://ljhzzyx.blog.163.com/blog/static/38380312201353536375/。目前想批量更新,如果update的值是相同的话,很简单,组织update table set column='...' where id in (1,2,3)l这样的sql就可以了。Mybatis中这样写就行UPDATE STUDENT SET ..._mysql batch update
Show variables like ‘character%’; //顯示目前mysql默認 字符集顯示數據連接字符集修改字符集D:\mysql>Net stop mysql //停止MYSQL方法:修改my.ini在安裝文件夾中把my-dafault.ini改成my.ini[mysqld]port=3306Character_set_server = utf8修改完后,重啟mysq..._修改字符集的方法 character_set_client ini mysql
1请求路径不正确,检查请求url是否正确,以ssm框架为例:@Controller@RequestMapping("/login")public class LoginController {@AutowiredUserService userService;@AutowiredSellInfoService sellService;@AutowiredCustomDao custom...
共同点:均可接受一个变量用以限制每次读取的数据量,但通常不使用区别:read() 【即 fileObject().read( [size] ) 】特点:读取整个文件,将文件内容放在一个字符串变量中。劣势:如果文件非常大,尤其大于内存时,无法使用read()方法。with open(r'../learn_file/file_to_read.txt', encoding='utf-8', mode='...
假如你是一个大学之前从未接触过电脑的人的话,大一对于你来是一个快速赶上的时候,如果你在大二有这个念头的话,遗憾的我要告诉你,这些都太晚了. 有人能在大二把高级程序员考过,而他的身边的人也能把机会能挂的科目给挂了,大一当我们同一起跑线时候每人无不对自己的未来充满着憧憬,可这些都要凭自己的实际去证明,大二,是一个多么重要的时段,错过了你会后悔一辈子,好好想想你这个年里做了什么吧 现在已经快6月
读取示例图片,读取示例图片from sklearn.datasets import load_sample_imagefrom sklearn.cluster import KMeansimport matplotlib.pyplot as pltchina = load_sample_image('china.jpg')plt.imshow(china)plt.show()观察图...
数字的鲁棒输入描述获得用户输入的一个数字,可能是浮点数或复数,如果是整数仅接收十进制形式,且只能是数字。对输入数字进行平方运算,输出结果。要求:_获得用户输入的一个数字,可能是浮点数或复数,如果是整数仅接收十进制形式,且只能
[url=http://en.wikipedia.org/wiki/Read-eval-print_loop]REPL[/url],即read-eval-print loop,最早出现在Lisp中,Emacs的[url=http://en.wikipedia.org/wiki/SLIME]Slime[/url]模式编写lisp非常方便。在Slime中流程是这样:[list=1][*] 编写..._conqueterm 使用技巧
动态语言和静态语言最大的不同,就是函数和类的定义,不是编译的时候定义的,而是运行时动态创建的. 直接在类中定义的是类属性,如:class Student(object): name = 'Student'实例属性必须通过实例绑定。如self.age='xx' 根据python的规则,定义时千万不要把类属性和实例属性使用同样的名字。捕获错误目的只是记录一下,便于后续追踪。但是,由于当前函_python学习日记