pytorch模型压缩方法总结

2021-10-28  本文已影响0人  加油11dd23

剪枝

structed vs unstructed

一个是在channel粒度上做剪枝,另一个是在神经元Unit维度上做剪枝

random vs l1 vs ln vs global

量化

动态量化 vs 静态量化

区别

1.torch.quantize_per_tensor()函数的scale和zero_point需要自己设定。
所谓动态是指这个函数torch.quantization.quantize_dynamic能自动选择最合适的scale和zero_point。

  1. 网络在前向推理的时候动态的量化float32类型的输入。
  2. 权重部分的量化是“静态”的,是提前就转换完毕的,而之所以叫做“动态”量化,就在于前向推理的时候动态的把input的float tensor转换为量化tensor。
  3. 动态量化的本质就藏身于此:基于运行时对数据范围的观察,来动态确定对输入进行量化时的scale值。这就确保 input tensor的scale因子能够基于输入数据进行优化,从而获得颗粒度更细的信息。模型的参数则是提前就转换为了INT8的格式(在使用quantize_dynamic API的时候)。这样,当输入也被量化后,网络中的运算就使用向量化的INT8指令来完成。 而在当前layer输出的时候,我们还需要把结果再重新转换为float32——re-quantization的scale值是依据input、 weight和output scale来确定的
  4. 动态量化中可是只量化了op的权重哦,输入的量化所需的scale的值是在推理过程中动态计算出来的。而静态量化中,统统都是提前就计算好的。

QuantStub使用的是HistogramObserver,根据输入从[-3,3]的分布,HistogramObserver计算得到min_val、max_val分别是-3、2.9971,而qmin和qmax又分别是0、127,其schema为per_tensor_affine,因此套用上面的per_tensor_affine逻辑可得:

动态量化

Post Training Dynamic Quantization,简称为Dynamic Quantization,也就是动态量化,或者叫作Weight-only的量化,是提前把模型中某些op的参数量化为INT8,然后在运行的时候动态的把输入量化为INT8,然后在当前op输出的时候再把结果requantization回到float32类型。动态量化默认只适用于Linear以及RNN的变种。

当对整个模型进行转换时,默认只对以下的op进行转换:
Linear
LSTM
LSTMCell
RNNCell
GRUCell
为啥呢?因为dynamic quantization只是把权重参数进行量化,而这些layer一般参数数量很大,在整个模型中参数量占比极高,因此边际效益高。对其它layer进行dynamic quantization几乎没有实际的意义。

静态量化

与其介绍post training static quantization是什么,我们不如先来说明下它和dynamic quantization的相同点和区别是什么。相同点就是,都是把网络的权重参数转从float32转换为int8;不同点是,需要把训练集或者和训练集分布类似的数据喂给模型(注意没有反向传播),然后通过每个op输入的分布特点来计算activation的量化参数(scale和zp)——称之为Calibrate(定标)。是的,静态量化包含有activation了,也就是post process,也就是op forward之后的后处理。为什么静态量化需要activation呢?因为静态量化的前向推理过程自(始+1)至(终-1)都是INT计算,activation需要确保一个op的输入符合下一个op的输入。

PyTorch会使用五部曲来完成模型的静态量化:

这一步不是训练。是为了获取数据的分布特点,来更好的计算activation的scale和zp。至少要喂上几百个迭代的数据,

per-channel vs per-tensor

per tensor 和 per channel。Per tensor 是说一个tensor里的所有value按照同一种方式去scale和offset; per channel是对于tensor的某一个维度(通常是channel的维度)上的值按照一种方式去scale和offset,也就是一个tensor里有多种不同的scale和offset的方式(组成一个vector),如此以来,在量化的时候相比per tensor的方式会引入更少的错误。PyTorch目前支持conv2d()、conv3d()、linear()的per channel量化。

上一篇下一篇

猜你喜欢

热点阅读