模型压缩分为前端压缩和后端压缩
前端压缩,是指在不改变原网络结构的压缩技术,主要包括知识蒸馏、轻量级网络(紧凑的模型结构设计)以非结构化剪枝;
后端压缩,是指包括低秩近似、结构化剪枝、参数量化以及二值网络等,目标在于尽可能减少模型大小,会对原始网络结构造成极大程度的改造。
低秩分解
给定权重矩阵W∈Rm×nW∈R^{m×n}W∈Rm×n,将其表示为若干个低秩矩阵的组合,W=∑αiMiW=\sum\alpha_i M_iW=∑αiMi,MiM_iMi为低秩矩阵,每一个低秩矩阵都可分解为小规模矩阵的乘积,Mi=GiHiTM_{i}=G_{i}H_{i}^{T}Mi=GiHiT
近两年已不再流行。原因在于:除了矩阵分解操作成本高、逐层分解不利于全局参数压缩,需要大量的重新训练才能达到收敛等问题之外,近两年提出的新网络越来越多地采用 1*1 卷积,这种小卷积核不利于低秩分解方法的使用,很难实现网络压缩与加速
剪枝
非结构化剪枝和结构化剪枝
结构化剪枝中通道剪枝用的最多
最常用的剪枝标准:L1/L2剪枝/每个特征图插入一个可学习的乘法参数、梯度幅度剪枝(英伟达一阶泰勒展开剪枝)
剪枝方法:训练-剪枝-微调、逐步剪枝、稀疏训练
量化
所谓“量化”,是指从权重中归纳出若干“代表”,由这些“代表”来表示某一类权重的具体数值。
量化中最有效的方法为定点量化,即将浮点数映射为定点数进行运算,再将运算结果反映射回浮点数的过程。
映射方式:线性量化
仿射量化
即将原始数据分布通过仿射变换到(0,255),也称为非对称量化。公式:xint=round(xΔ)+zx_{int}=round(\frac{x}{\Delta})+zxint=round(Δx)+z,xQ=clamp(0,Nlevels−1,xint)x_Q=clamp(0,N_{levels-1},x_{int})xQ=clamp(0,Nlevels−1,xint)。通过线性变化将原始数据映射至(0,255),如下图左。
Δ为量化步长,z为零点,z用来确保零值量化正确。
对称量化
由于对零值量化会增加额外的计算量,若数据分布较为对称,则可将零点量化去除,将原始数据分布通过变换到(-127,128),如上图右,公式:xint=round(xΔ)x_{int}=round(\frac{x}{\Delta})xint=round(Δx),xQ=clamp(−Nlevels/2+1,Nlevels−1/2,xint)x_Q=clamp(-N_{levels}/2+1,N_{levels-1}/2,x_{int})xQ=clamp(−Nlevels/2+1,Nlevels−1/2,xint)。
量化方式
训练后量化
先通过正常训练获得模型参数,再直接对模型权值进行量化
1、只量化权重:只能减少传输和模型大小,不能降低运算成本,由于权重在模型训练时已经获得,因此可以直接获取权重张量的最大最小值,计算伪量化的参数,在对其进行量化
2、量化权重和激活层:量化激活层与量化权重不同,需要经过几轮推理,获取激活层的最大最小值,再对其量化
逐通道量化性能比逐层量化好;非对称量化性能更接近浮点数精度。对称和非对称的效果取决于数据分布。
激活层量化几乎不损失精度,是因为BN层限制了激活层的动态范围。
参数更多的网络比如ResNet,量化效果比参数更少的网络好。
量化感知训练
通过在模型训练时加入量化节点,以模拟实际模型量化时的精度损失,再以梯度回传的方式更新参数。
在训练时需获得浮点权值的梯度,但量化过程不可导,其使用直通估计器计算梯度:δr=δq∗1x∈S,S:xmin<x<xmax\delta_r = \delta_q*1_{x∈S},S:x_{min}<x<x_{max}δr=δq∗1x∈S,S:xmin<x<xmax
训练后量化
很直接的方法就是根据数值范围的大小来确定 max和min,得到scale和zero来进行量化
但这种方法容易受到噪声的影响,比如,有些 weight 或者 feature 中可能存在某些离群点,它的数值较大,但对结果影响又很小,如果把这些数值也统计到 minmax 里面,就容易造成浪费。
一般采用截断/校准的方法来确保量化前和量化后的分布保持一致,如直方图校准、KL散度校准
知识蒸馏
将庞大而复杂的大模型学习到的知识,通过一定技术手段迁移到精简的小模型上,从而使小模型能够获得与大模型相近的性能。也可说让小模型去拟合大模型,从而让小模型学到与大模型相似的函数映射。
student 模型最终的损失函数由两部分组成:
第一项是由小模型的预测结果与大模型的“软标签”所构成的交叉熵(cross entroy);
第二项为预测结果与普通类别标签的交叉熵。
个人认为知识蒸馏不太靠谱,现在复杂的网络的连接都特别复杂,而适合部署的网络应该是像VGG那种,中间特征根本无法约束,只约束输出缺乏解释性。