最近要开始使用Transformer去做一些事情了,特地把与此相关的知识点记录下来,构建相关的、完整的知识结构体系,
以下是要写的文章,本文是这个系列的第十篇:
Bert模型虽然很火,但是模型太大,在device上基本不可用,要想更好的使用的话需要让模型变小。MobileBert综合运用多种技术,将Bert模型在手机上的运行降低到了40ms,让我看到了Bert在手机上运用的希望。
MobileBert中采用的技术如下:
可以看到,优化方法仍然没有出我们在前面文章里讲的四条:量化,矩阵分解,结构改动,知识蒸馏。下面我们一项一项的进行讲解。
我们知道,Bert的体态其实很宽,Bert-base的宽度是768,Bert-large的宽度是1024。而Bert的宽度有几个特点:
这点如果不熟悉的欢迎去翻以前的文章,上面都有链接。
由于之前的研究表明,减少层次,让模型变浅,得到的小模型相对于大模型损失太大,所以MobileBert尝试把模型变窄。而直接全体变窄经过试验又会导致较大的损失,所以,MobileBert使用Inverted Bottleneck的形式来保证Bert模型中Transformer块之间的宽度不变。如下图所示:
a图是一个正常的Bert,有L个Transformer块。b图和c图则是带有Inverted-bottleneck的模型,可以看到,所谓的Inverted-Bottleneck,就是在每个Transformer块的前后各添加一个全连接层来保证Transformer块的输入和输出是同一个宽度。我们称这两个全连接层为Linear入和Linear出这样宽度就变成两个:块内宽度和块间宽度。
以此,b图可以把Transformer块变胖,就是一个更大的模型,c图是把中间的块变窄,就组成了MobileBert。
在b图和c图中,可以注意到,Multi-Head Attention的输入是Embedding,所以Multi-Head Attention和Linear入负责把输入embedding从块间宽度变成块内宽度。而输出的变化则由Linear出全权负责。
那么就有个问题,为什么输入上的做法要和输出不同?答案是为了保证模型的容量。MobileBertTiny就是全依靠Linear来变换输入输出。
在MobileBertTiny中,采用的Inverted-bottleneck就是只用
Linear入来把embedding从块间宽度变成块内宽度,然后Linear入的输出再输入给Multi-Head Attention。这样会带来参数量的大幅度降低,同时模型容量降低也可能伤害最后的效果。
由于c图从头训练达到较好效果比较难,所以MobileBert的做法是先训练b图的大模型,然后再去做模型蒸馏使得最后的MobileBert达到较好的效果。
我们知道,Transformer块分为Multi-Head Attention和Feed Forward两个部分,这两个部分有各自的功能:
而当用了Inverted-bottleneck后,Attention部分的输入是块间宽度的Embedding,而全连接层的输入则是块内宽度。因此就导致了一个问题,这两部分的参数矩阵此消彼长,Attention部分变多,而全连接层变少。导致它们的比例出了问题。而后面的实验会表明,这种比例的变化会导致模型的效果变差。
而解决方案则是把全连接层复制几份来恢复这个比例。还是看上面那张图,图中的c图的全连接层部分框起来乘以了一个F。这就是Stacked FFN。
对于中间的一些计算操作,MobileBert也做了优化。去掉了Layer Norm而用一个更简单的操作来替代:
其中,圆圈代表的是阿达玛矩阵乘积,即element-wise的矩阵乘法。
另个优化是Gelu激活函数被替换成Relu。
embedding层占了很大一部分参数,为了解决这个问题,MobileBert使用了维度为128的embedding,然后用一维卷积来把embedding转化为512大小。
MobileBert共采用了如下几种损失函数:
提出了三种策略:
三种策略如下图所示:
实验使用的一些模型结构参数如下表,可以看到,MobileBert和Bert-Large的深度相同,但是块内宽度只有128,块间宽度则是512。
下表列举了一些探索的参数组合上的结果,可以看到:
在跟Bert类似,接近1:2的参数比的时候会更好。
Glue任务上的结果如下:
可以看到,MobileBert without OPT效果出众,MobileBert-Tiny在Pixel 4上速度仅为40ms。
SQuAD上的结果如下:
采用的post-training量化,会带来微弱的损失。
Latency上的实验结果,去掉LayerNorm带来60ms提升,再去掉gelu又带来30ms提升。
不同策略对比,最后的PKT最好
损失函数上的消融实验,FMT起的效果最大。
勤思考,多总结是工程师的必备品德。
论文提出了Inverted-Bottleneck来从结构上对Bert进行优化,但小尺寸的IB难以训练,所以需要一个大尺寸的IB来做模型蒸馏。在这里可以看出模型蒸馏对于压缩的独特意义。
另一个独特的研究在于Multi-Head Attention和FFN的参数比的研究和实验,这里认为模型的容量体现在参数量上,那么如何看待模型结构对于模型容量的影响?比如把FFN换成卷积也需要同样的参数量吗?
LayerNorm和Gelu的替换对于latency影响巨大。那么一个简单的问题,LayerNorm和Gelu分别做了什么耗时的计算?