论文:DistilBERT, a distilled version of BERT: smaller, faster, cheaper and lighter
作者:Victor Sanh, Lysandre Debut, Julien Chaumond, Thomas Wolf
时间:2020
一、完整代码
这里我们使用python代码进行实现
# 完整代码在这里 # 代码在https://github.com/huggingface/transformers # 有时间再来处理
二、论文解读
2.1 介绍
这个是HuggingFace
出的论文,相信跑模型的同学应该没有人不知道HuggingFace
的,这里要介绍的是DistilBERT
,这是在大规模预训练模型在NLP任务流行的时候,提出的一种减少参数量但却保持相当能力的BERT
模型;这篇论文引入了一种结合语言建模,蒸馏,余弦距离损失的三重损失,利用该损失在预训练阶段使用知识蒸馏,可以减少BERT
模型40%
的大小,保持97%
的能力,同时加快60%
的速度;
虽然说BERT
和GPT
类的模型在处理NLP
任务时带来了极大的改进;但是NLP领域出现了一种现象,就是在模型越大的时候,模型的效果就越好,我估计这也是大厂疯狂卷算力的原因吧;作者在这里提出了两点担忧,第一点是:模型越大,计算越困难,算力要求就越大,这可能导致电力的疯狂消耗,会导致环境问题;第二点是:如此大的模型需要很大的算力和内存消耗,这是一般的家庭无法承担得起的,这会阻碍大模型的广泛应用,所以目前大多采用的是api方式;
而通过知识蒸馏预先训练的相对较小的语言模型,可以在许多的下游任务中达到相似的性能,而且能够使模型在推理的更轻更快,在训练时需要较小的预算;论文中还显示知识蒸馏后的模型可以在移动设备上运行;
2.2 知识蒸馏
知识蒸馏是一种模型压缩技术,它是通过一个小的,紧凑的模型来重复大的模型或者模型集合的行为,进而达到减少参数却保持相似的性能的作用,这个小的,紧凑的模型一般称为学生模型,大的或者模型集合一般称为教师模型,这个理论中学生模型能否超越教师模型,我觉得主要是看教师模型的参数是否高效吧;总的来说,知识蒸馏的目的是:学生模型要尽可能的学习到教师模型中类与类之间的相似性和差异;
知识蒸馏损失函数:
这里 t i t_i ti表示的是教师模型的概率估计, si表示的是学生模型的概率估计,同时这里利用了softmax-temperature
,其采取的方式如下:
其中T
控制输出分布的平滑性,而 zi是第 i类的模型分数;在训练时对学生模型和老师模型施加相同的T
,而在推理时,将T
设置为1以恢复标准的softmax;
2.3 三重损失
论文中模型采取的损失函数是三重损失的线性组合,分别是知识蒸馏损失函数,掩码语言模型损失函数,余弦嵌入损失函数,得到最后的损失函数为:
2.4 DistilBERT
学生模型架构:和BERT
架构一致,在transformer
的层数上有些减少,是原来的 1 2 \frac{1}{2} 21,同时发现减少embedding
的维度即d_model
维度的减少相较于其他参数的影响比如说层数对计算效率的影响较小,所以在知识蒸馏时专注于考虑层数的减少;
学生模型初始化:模型采用的是二选一的方式,即从每个两层中选出一层,保留参数构成的模型来进行初始化;如果采用随机初始化的方式,效果很差;
蒸馏:DistilBERT
是在非常大的批次上提炼的,每一个批次数据量大约是4000
个,训练中只使用了动态掩蔽,而没有使用NSP任务;
数据和计算能力:与原始BERT模型在相同的语料库上训练DistilBERT
:DistilBERT
在8个 16GB的V100gpu上进行了大约90小时的训练,RoBERTa
需要对1024个32GB的V100进行1天的训练;训练后的DistilBERT
可以部署在iphone 7p
上
现在考虑三个损失对模型的影响:
右侧的分数是以三重损失 + 教师权重初始化
来对比的,可以发现 L m l m L_{mlm} Lmlm的影响最小;
知识蒸馏技术在NLP之前的任务是通过特定任务来初始化,这样教师模型的权重可能会存在大幅度更新,导致教师权重失效,而使用教师模型的数据来进行初始化学生模型,可以充分利用教师模型的参数,进而获得更好的效果;
论文中还提到了其他模型的压缩技术:剪枝的方式:在测试时可以去除自我注意中的一些头部,而不会显著降低模型的表现,即把多头注意力机制的头的数量减少,进而来优化效率;量化:优化计算方式;
三、整体总结
DistilBERT
是知识蒸馏在NLP
任务上的一个应用;