8.1 模型压缩的方法
Posted 炫云云
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了8.1 模型压缩的方法相关的知识,希望对你有一定的参考价值。
相关论文下载:模型压缩方法与bert压缩的论文
模型压缩
模型在设计之初都是过参数化的,这是因为模型的参数量与复杂度代表着模型的容量与学习能力,但当我们实际使用时,我们需要更好的部署他(低资源),更快的响应(快速推理),常常需要进行模型压缩。
模型压缩就是简化大的模型,得到推理快资源占用低的小模型
,而想"即要马而跑又不用吃草"通常是很难的,所以压缩后的模型常常也会有不同程度的牺牲,如模型性能下降。此外,模型压缩是作用在推理阶段,带来的常常是训练时间的增加。
模型压缩又分为几种方式:一种是剪枝(Pruning)
与量化(Quantization)
,一种是知识蒸馏(Knowledge Distillation)
, 还有一种是权重共享(Sharing)与因数分解(Factorization)
。该部分内容推荐一篇博客:All The Ways You Can Compress BERT1
剪枝
剪枝技术是通过将大模型中一些"不重要"的部分剪断,得到一个"稀疏"结构的模型。剪枝又分为"结构性剪枝"与"非结构性剪枝".剪枝可以作用在权重粒度, 也可以作用在attention heads / layer粒度上。一些方法在训练过程中也会施加正则化以增加修剪能力(层dropout)。
量化
量化不改变模型的网络结构,而是改变模型的参数的数据格式,通常模型在建立与训练时使用的是 float32 格式的,量化就是将格式转换为 low-bit
, 如 float16 甚至二值化,如此即提速又省显存。
知识蒸馏
知识蒸馏是训练一个小模型(student)来学习大模型(teacher),由于大模型是之前已经fine-tuning的,所以此时学习的目标已经转换为对应的logit而不再是one-hot编码了,所以student有可能比teacher的性能更好。这样即小又准的模型实在太好了。
不过为了达到这样的效果,通常设计小模型时不光要学习大模型的输出,还要学习各个中间层结果,权重矩阵和隐藏的激活等,这就需要仔细设计模型的结构与loss及loss融合方案了。一种简单的方法是只学习大模型的logit,这与对label做embedding有点类似。
权重共享
模型中的一些权重与模型中的其他参数具有相同的值。 如ALBERT中的每一层共享self-attention中的参数。
权重分解
将权重矩阵进行因数分解, 通过将参数矩阵分解成两个较小矩阵的乘法来近似参数矩阵。这对矩阵施加了一个低秩约束。权重因数分解既可以应用于token 嵌入(在磁盘上节省了大量内存)也可以应用于前馈/自注意层中的参数(用于一些速度改进)。
训练前vs下游
有些方法只压缩某些下游任务。另一些人用一种任务无关的方式来压缩伯特。
模型压缩的必要性
看了上面模型压缩的方法,每一个都有种"脱裤子放屁"的感觉,与其训练一个大模型,再费力把它变小,为何不直接开始就弄个小的呢?
- 首先,模型在设计之初是都是会或多或少的过参数化,因为模型的参数量与复杂度代表着模型的容量与学习能力;
- 其次,开始就用一个小模型,那这个小模型也是需要设计的,不能随便拿来一个,而设计一个性能高参数规模小的小模型难度是非常大的,往往是模型小了性能也低了;
- 第三点,大模型压缩后与小模型虽然参数规模相当,但是对应的模型空间并不相同
- 此外,为了更好的部署,如手机或FPGA等,得到精度更高模型更小(distillation)或者利用硬件加速(low-bit),模型压缩都是值得试一试的手段。
更详细的讨论,可以参考为什么要压缩模型,而不直接训练一个小的CNN2
参考
一个小的CNN: https://www.zhihu.com/question/303922732
以上是关于8.1 模型压缩的方法的主要内容,如果未能解决你的问题,请参考以下文章
Cg入门20:Fragment shader - 片段级模型动态变色(实现汽车动态换漆)
如何将 View 类中的代码片段移动到 OnAppearing() 方法?
基于多种模型剪枝方法(L1-normSlimmingAutoSlim)的模型轻量化和模型压缩实现