知识蒸馏
知识蒸馏的作用是使用小网络使得小网络的性能和大网络差不多,从而实现大网络的模型压缩。将大网络压缩成小网络有以下步骤:
(1) 训练大网络
(2) 将训练好的大网络的输出logit,使用一个温度值$T$放缩,得到$\frac{1}{T}$logit,将放缩后的logit经过softmax层,得到soft label
(3) 对小网络,使用两项目标函数:第一个目标函数要求小网络的输出logic使用同一个温度$T$放缩,放缩后经过softmax层,要求softmax层的输出结果和soft label的交叉熵最小;第二个目标函数要求小网络没有经过放缩的softmax层输出结果与正确标签的one-hot向量的交叉熵最小。
知识蒸馏之所以能起作用,我的理解有两点:
(1) 通过温度$T$,使得输出logit更平缓,类间的差距缩小,但是类间的相对关系不变,平缓的输出更容易拟合(类似于标签平滑的效果)。
(2) 大模型参数多,能输出更极端的logit,而小模型参数小输出的logit无法兼顾那么多极端情况,使小模型的输出没那么极端且保持类间输出的相对关系,可以通过对大模型和小模型的logit同时放缩,在放缩中进行拟合,这么做会更容易。
在线蒸馏
知识蒸馏除了可以压缩模型,还可以提升模型的学习效率。在使用分布式的学习场景时,通常需要用到分布式的梯度下降算法优化模型参数,而分布式的梯度下降算法需要有一个中心机器来同步不同机器的梯度更新情况,这种做法效率不高,且最终效果往往没有单机情况好。知识蒸馏可以应用于分布式的参数学习环境:
(1) 各个机器单独从同一份数据集中抽样数据学习,单独更新模型参数
(2) 特定时刻,统计所有机器对数据样本的输出logit期望,组成teacher model
(3) 各个机器单独学习,在原来的基础上加上teacher model的输出指导,单独更新模型参数
通过这样的方式,就可以利用知识蒸馏合并模型,实现模型的分布式学习,有实验结果表明,这种学习方式比分布式SGD更好。
模型压缩
模型压缩旨在减小模型占用的空间,可分为减小模型占用存储空间和减小模型占用运行空间。减小模型占用存储空间一般有剪枝和量化的方法,而减小模型占用运行空间则有量化、低秩分解和知识蒸馏的方法。
剪枝
类似于L1正则化,将权重较小的值直接标记为0,此时权重矩阵是一个稀疏矩阵,可以使用稀疏矩阵的存储方法存储,减小存储空间。剪枝可以减小存储空间,但在运行时依然要将矩阵对应位置的值置零,所以没有减小运行空间。
量化
量化是减小数字的位数,比如将64位的double压缩到使用8位表示。量化会导致一些数值误差,是一种有损的方法。量化可以有效降低模型的存储与运行空间。
低秩分解
低秩分解在于将一个很大的$N\times M$的权重矩阵分解成两个较小的$N\times K$和$K\times M$的矩阵的乘积。当这种分解不存在时,也可以使用两个小矩阵去近似,没有必要完全相等,比如可以使用$K\times 1$和$1\times K$的乘积近似一个$K\times K$的卷积核,即将一个卷积核分解成两个一维向量的乘积。低秩分解因为是利用小矩阵的乘积去近似大矩阵,所以也是有损的压缩方式,但有时候这种有损的压缩方式又会带来一些惊喜,我们可以将这种近似看作一种正则化。
知识蒸馏
前面已经提过,这里就不赘述了。