1. 量化
将高精度模型用低精度来表示,使得模型更小
2. 剪纸
讲模型中作用较小的部分舍弃,让模型更小。
##3. 模型蒸馏
3.1. DistilBERT(2019.10.2)
知识蒸馏的基础原理:
定义两个网络,teacher网络和student网络,teacher网络是预训练得到的大模型,student模型是想要学习和迁移得到的小模型。根据Hinton的文章,一般的蒸馏模式是:把teacher网络的输出作为soft-label,student网络学习的目标是hard-label,交叉构造三种loss来联合训练,目的是时student网络具备与teacher网络同样的推理目标。
模型简述:
student的网络解决与teacher的网络结构相同,都是Bert。主要改动有:
- 对student网络的构造,就是从teacher网络每两层去掉一层。因为,作者调研发现,隐层维度的变化比层数的变化对性能的影响较小,所以只改变网络层数。
- 因为student网络的层数减少两倍,所以去掉token type embedding和pooler。
- 使用teacher网络每两层的一层的参数来初始化student网络。
- 使用更大的batch,使用dynamic masking,去掉NSP任务。这几点是从RoBERTa中取的经。
三个loss:
- , teacher模型得到的目标概率分布是,student模型得到的目标概率分布是,然后计算两个分布的KL散度:。KL散度是衡量两个分布的相关度,使用这个loss,在训练的时候,就可以把teacher网络中丰富的先验知识带进训练过程。 这里使用softmax-temperature,使用来控制输出概率的平滑度,在inference时,设置为1。
- ,就是bert中的masked语言模型的loss。
- ,计算student网络的hidden state和teacher网络的hidden state的余弦相似度。
然后将三个loss加权想和:
实验:
inference时间对比,大概提升了60%:
Ablation test结果,可以看出Lce、Lcos、参数初始化为结果影响较大:
3.2 TinyBert (2019.11.23)
主要贡献
- 提出的蒸馏方法,增加了对Transformer中attention层考量。
- 提出two-stage的蒸馏模式,在pre-training和fine-tuning阶段进行相同的蒸馏,验证效果更好。
- 实验证明结果很好。
模型简述:
问题定义:
teacher模型(m层)和student模型(n层)每层通过一个函数映射。student学teacher的过程就是通过最小化下面的目标函数:
各种loss的定义:
- Transformer-layer Distillation
又分为基于注意力的蒸馏和基于隐层的蒸馏。作者使用注意力蒸馏,是因为最近的研究发现,通过BERT学习的注意力矩阵包含丰富的语言学知识,这些语言学知识包含了语法和共指信息,对自然语言理解非常重要。
基于注意力的蒸馏:
计算student和teacher之间注意力矩阵的MSE,其中表示head的个数。 基于隐层的蒸馏:
计算Transformer输出层,也就是hidden states,之间MSE,公式中是把映射到相同维度的,是一个需要学习的参数矩阵。
- Embedding-layer Distillation
是对输入层输入做比较。
- Prediction-Layer Distillation
根据上面的定义,就可以最终得到student网络的完整的loss:
其中和分别是student网络和teacher网络的预测目标的logits。这就是标准蒸馏范式中的KL-loss。
两段式蒸馏:
文章提出在两个阶段都进行蒸馏,即:在pre-training结点进行蒸馏,得到General Distillation Model。在fine-tuning阶段,先做data augmentation,然后执行相同的蒸馏,得到Task-specific Distillation Model。
实验:
TinyBERT在经验上是有效的,其性能能够超过基线BERT的96%,容量小7.5倍,推理速度快9.4倍。同时,TinyBERT要比基线DistillBERT也明显更优,只有其28%的参数,31%的推理时间:
在 GLUE 基准上实现了与 BERT 相当(下降 3 个百分点)的效果:
##4. 模型结构上的优化
4.1《Deformer:Decomposing Pre-trained Transformers for Faster Question Answering》(ACL 2020)
BERT模型做QA问题,比如问答或者阅读理解,需要将query和document拼接作为模型输入,然后使用self-attention对输入文本进行多层的交互编码,之后使用线性分类器在document中寻找可能的答案序列。而通常document都非常的长,所以就会有大量的计算。
这篇文章提出,将BERT模型做成两段式的结构,提前进行一些运算。
有研究表明,在多层Transformer模型中,低层(low layers)的编码主要关注一些局部的预言表层特征(比如词性,语法等),到了高层(upper layer)才逐渐关注与下游任务相关的全局语义信息。所以,在low layers, **”文档编码能够不依赖于问题“**的假设是正确的。所以,这篇文章的思路具体来说:在底层先对问题和文档各自编码,在高层拼接问题和文档的隐层表征再进行交叉编码。如下图:
另外,作者实验发现这种结构在SQuAD上精度损失比较大,所以作者添加了两个蒸馏损失项。目的是最小化Defomer的高层表征和分类层logits与原始BERT模型的差异。
实验:
在三个QA任务上,BERT和XLNet采用DeFormer分解后,取得了2.7-3.5倍的加速,节省内存65.8-72.0%,效果损失只有0.6-1.8%。但还是很慢,达不到实时的效果。
4.2《AlBert》
主要三个改变,
- 使embedding层的维度()设置为远小于隐层的维度(),然后通过矩阵分解,将的矩阵分解为,,其中, 为字典大小,就是先将embedding的矩阵,映射到小维度的矩阵,然后再映射到大维度的隐层矩阵。这样就可以使embedding层参数大大减小。
- 共享emcoder中的所有参数。
- 将NSP任务改为SOP任务。
3. 《FastBERT》
1.主要贡献
这篇文章主要是想优化predict阶段的性能,采用提前结束的策略。即在predict阶段,在每一层transformer之后,接一个分类器(作者提出的方法在分类问题上使用),如果分类器的结果置信度很高,就不往更深层进行,提前结束。
这样,容易预测的样本(特征明显)通过一两层就可以得到结果,较难的样本则需要经过所有层。因为,分类器的计算复杂度要远远低于transformer的计算,所以,平均下来,predict的性能可以得到提高。
2.模型简述
上图是模型架构,下面是模型训练和推理顺序:
- Pre-training:BERT(或者其他预训练模型)作为**主干(backbone)**不变,预训练阶段没有改变。
- Fine-tuning for Backbone:在分类任务上微调模型主干。
- Self-distillation for branch:分支自蒸馏,将主干模型知识蒸馏到分支分类器上,使用无标签数据就可以。即对于主干模型预测结果的概率分布与各层分支分类器预测的概率分布,计算两者的KL散度,然后所有层(共个student)的loss之和为最终的loss。
- Adaptive inference:自适应推理,即使用student分类器对样本进行层层分类。结果明确的直接给出结果结束预测,结果不明确的继续到下一层。其中,作者定了的预测结果**不确定性(Uncertainty)**的定义:
其中,表示分类器的输出概率分布,表示分类标签个数,这个定义的意义其实就是概率分布的熵,概率分布越散乱,熵越大,信息量越多,不确定性越低,分类结果也就越明确。 通过speed阈值来确定每层结束的条件(每一层分类器之后得到的Uncertainty,当小于speed时,提前结束)。所以,当speed增大,就会有更少sample被送到更高层,推理速度就越慢。
3.实验结果
以在中文数据集的结果为例,可以得出几个结论:
- 综合来说,比DistilBERT效果要好很多。
- 当提高speed阈值,提升速度与准确率降低的综合判断更优秀。