模型压缩

Model Compression

Posted by Roger on November 17, 2020

模型压缩简介

总结自李宏毅老师的视频教程:Network Compression

  为了将神经网络模型部署到手机、智能手表等计算资源有限的设备上,动辄几个GB大小参数的网络自然是不现实的,需要压缩模型到合适的规模。模型压缩方法主要有如下几类:

  • 网络剪枝(Network Pruning)
  • 知识蒸馏(Knowledge Distillation)
  • 参数量化(Parameter Quantization)
  • 网络结构设计(Architecture Design)
  • 动态计算(Dynamic Computation)
  • 硬件设计

1. 网络剪枝

  神经网络通常有很多参数是冗余的(即某些参数很小,或某些neuron在大多数时间里输出都为0或很小)。因此,可以对这些参数进行剪枝以达到减小网络参数的目的。
Q:为什么不直接训练一个小的网络呢?
A:这是因为大的网络往往更容易训练(网络参数越多,遇到local minimum的概率越小,大多数情况是saddle point,且local minimum处的loss很接近于global minimum),可以得到更好的结果。而直接训练一个小的网络结果不如训练大网络的效果好。
  网络剪枝的流程是:先评估哪些参数不重要可以移除→移除后用训练数据进行Fine-tuning以恢复损失的精度→重复上述过程直至满意的结果。weight pruning会造成不同的neuron的输入/输出不一致,这样的话无法利用GPU加速。为了规范数据以利用GPU加速,可以使用neuron pruning,即直接删除对应的neuron(等效于缩小hidden layer的规模)。

2. 知识蒸馏

  该方法是先训练一个大的神经网络来学习任务,在此基础上再训练一个小的网络来“模仿”该大网络的行为。即给定相同的输入,小网络要模仿大网络的输出。这与直接使用数据标签进行训练的区别是:以多分类任务为例,数据标签只能提供单一的信息(是否是该类),无法提供更详细的类与类之间的关系。而大网络不是只输出单个结果,而是输出一个分布,有助于小网络从中学到更丰富的信息。
  一个有用的trick:Temperature:
Temperature

3. 参数量化

  • 使用更少的bit来表示一个值,如float32变为float16
  • 权值聚类
    比如将参数聚为4类,那么可用2 bit来表示四种不同的权值,保留每种权值与对应数值的组合(即保存一个映射表,其中对应的数值可以为该类参数的均值)
  • 在权值聚类基础上更进一步,使用更少的bit来表示聚类簇的频率,如哈夫曼编码
  • Binary weights,网络参数值只可能是1/-1,先随机初始化实值网络参数,以及多组不同的由±1权值组成的网络参数组合。计算梯度时,不使用实值参数来计算,而是用和当前实值参数最接近的Binary network的参数来进行计算梯度,用得到的梯度来更新实值网络。

4. 网络结构设计

  对于全连接层网络,假设原网络是由两层Dense层连接组成,两层neuron数分别为$m$、$n$,此时在两层中间再插入一层neuron数为$k$($k \lt min(m, n)$)的Dense层。那么之前两层之间的参数大小为$m\cdot n$,插入后参数大小变为$m\cdot k+n\cdot k=k\cdot (m+n)$。k选择较小可以使整体参数变小,但同时网络的表达能力也变弱。
  对于卷积网络,用Depthwise Seperable(Depthwise Convolution + Pointwise Convolution)来代替普通的卷积网络。
VanillaConv
DepthwiseConv

5. 动态计算

  在网络电量低或者计算资源不足时,不使用整个网络得出预测结果,而是使用部分网络给出预测结果。比如对于多个Dense层堆叠的网络,在每个(或每几个)层上都加上结果的输出,这样在有需要时,可以只用网络的低层输出的结果作为预测结果,从而减少计算量。
  这样做有一个缺点:由于低层网络之前只需要学习局部/底层特征,加上结果输出后该部分网络“被迫”学习更加全局的特征,从而破坏了整体的网络布局。研究解决该问题的论文有:Multi-Scale Dense Networks。