当前位置:   article > 正文

PyTorch模型量化方法_pytorch bite 量化

pytorch bite 量化

官方文档
https://pytorch.org/docs/stable/quantization.html#common-errors
 

PyTorch的量化:

量化指的是使用更少的bit来存储原本以浮点数存储的tensor,以及使用更少的bit来完成原本以浮点数完成的计算。

这么做的好处主要有如下几点:
更少的模型体积,接近4倍的减少;
可以更快的计算,由于更少的内存访问和更快的int8计算,可以快2~4倍。

量化还需要底层硬件支持,x86 CPU(支持AVX2)、ARM CPU、Google TPU、Nvidia Volta/Turing/Ampere、Qualcomm DSP 这些主流硬件都对量化提供了支持。

PyTorch对量化的支持目前有如下三种方式:
Post Training Dynamic Quantization,模型训练完毕后的动态量化;
Post Training Static Quantization,模型训练完毕后的静态量化;
QAT(Quantization Aware Training),模型训练中开启量化。


Tensor的量化:

PyTorch为了实现量化,首先就得需要具备能够表示量化数据的Tensor,这就是从PyTorch 1.1之后引入的Quantized Tensor。 
Quantized Tensor可以存储 int8/uint8/int32类型的数据

xq = torch.quantize_per_tensor(x, scale = 0.5, zero_point = 8, dtype=torch.quint8)
量化tensor,也就是xq,和fp32 tensor的x的关系大概就是:
xq = round(x / scale + zero_point)

把xq在反量化回来
xdq = xq.dequantize()
dequantize函数就是quantize_per_tensor的反义词,把一个量化tensor转换为float tensor。
xdq = (xq - zero_point) * scale

xdq和x的值已经出现了偏差的事实告诉了我们两个道理:
量化会有精度损失;
我们这里随便选取的scale和zp太烂,选择合适的scale和zp可以有效降低精度损失。

而在PyTorch中,选择合适的scale和zp的工作就由各种observer来完成。

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量化。


Post Training Dynamic Quantization:

torch.quantization.quantize_dynamic(model, qconfig_spec=None, dtype=torch.qint8, mapping=None, inplace=False)

只有权重被量化的model,dtype参数可以取值 float16 或者 qint8。
当对整个模型进行转换时,默认只对以下的op进行转换:
Linear
LSTM
LSTMCell
RNNCell
GRUCell

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


Post Training Static Quantization:

需要把训练集或者和训练集分布类似的数据喂给模型(注意没有反向传播),然后通过每个op输入的分布特点来计算activation的量化参数(scale和zp)——称之为Calibrate(定标)。

静态量化包含有activation了,也就是post process,也就是op forward之后的后处理。
为什么静态量化需要activation呢?因为静态量化的前向推理过程自(始+1)至(终-1)都是INT计算,activation需要确保一个op的输入符合下一个op的输入。


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

(1)
比如给fuse_modules传递下面的参数就会合并网络中的conv1、bn1、relu1:
torch.quantization.fuse_modules(gemfield_model, [['conv1', 'bn1', 'relu1']], inplace=True)

(2)
#如果要部署在x86 server上
gemfield_model.qconfig = torch.quantization.get_default_qconfig('fbgemm')

(3)
prepare用来给每个子module插入Observer,用来收集和定标数据。
gemfield_model_prepared = torch.quantization.prepare(gemfield_model)

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

(5)
转换模型
gemfield_model_prepared_int8 = torch.quantization.convert(gemfield_model_prepared)


动态量化中可是只量化了op的权重哦,输入的量化所需的scale的值是在推理过程中动态计算出来的。
而静态量化中,统统都是提前就计算好的。
网络 forward 的开始和结束还必须安插 QuantStub 和 DeQuantStub

网络forward的开始和结束还必须安插QuantStub和DeQuantStub。

动态量化和静态量化的最大区别:
静态量化的float输入必经QuantStub变为int,此后到输出之前都是int;
动态量化的float输入是经动态计算的scale和zp量化为int,op输出时转换回float。


QAT(Quantization Aware Training):

在训练过程中就开启了量化功能。
https://zhuanlan.zhihu.com/p/299108528
https://blog.csdn.net/c9Yv2cf9I06K2A9E/article/details/113488003

这两种方式都是支持直接量化操作的,但是GPU不支持,怎么支持GPU,Pytorch官方最新版文档说了,必须采用量化感知的训练方式训练模型,模型才支持GPU量化。
https://cloud.tencent.com/developer/article/1920514

PyTorch支持在具有AVX2支持或者更高版本的x86 CPU或者ARM CPU上运行量化运算符。

如果想要在GPU上操作,可以先使用torch.nn.export函数将模型转换成onnx格式,然后就可以放到TensorRT框架上inference了。(TensorRT目前不能直接解析Pytorch的网络模型,需要转换成onnx)
https://www.zhihu.com/question/431572414/answer/1601740370

Pytorch暂时的量化操作还不是很完善,可能存在只能在CPU上运行,且速度变慢的情况。如果有量化需求,推荐使用tensorrt和GPU一起使用。
https://www.modb.pro/db/495074

Dynamic Quantization

目前仅支持几种算子, Linear, LSTM, LSTMCell, GRUCell, and RNNCell。居然连nn.Conv2d都不支持(https://pytorch.org/tutorials/recipes/quantization.html),结果就是如果你自己试图量化官方的mobilenet,会发现模型的体积没有下降多少

inference的时候有个int8和float转化的过程,所以推理性能可能不会大幅增加。
https://aitechtogether.com/article/34248.html

Pytorch模型量化
https://www.cnblogs.com/LXP-Never/p/16822727.html
 

例子
https://zhuanlan.zhihu.com/p/590234415

Pytorch量化之图像超分量化
https://zhuanlan.zhihu.com/p/349329744

给大家介绍模型训练后静态量化的过程

Pytorch的量化大致分为三种:
模型训练完毕后动态量化、模型训练完毕后静态量化、模型训练中开启量化。

在做静态量化时需要对数据集进行推理获取数据的分布特点、定标。
https://blog.csdn.net/lai_cheng/article/details/118961420
代码
https://github.com/Laicheng0830/Pytorch_Model_Quantization
 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/377513
推荐阅读
相关标签
  

闽ICP备14008679号