在深度学习领域量化主要是存储量化(减少存储所需内存)以及计算量化(减少计算时间)。而博主主要使用pytorch,在pytorch里支持的量化主要有动态量化(推理过程中进行量化)、静态量化(训练后进行量化)、感知量化(边训练边量化,用的时间更长,但精度几乎无损)。
Tensor量化
要实现量化首先要进行Tensor量化,Tensor量化与scale、zero-point参数有关,公式为:
round(x/scale+zero-point)
Tensor一般量化有2种模式,per tensor与per channel,前者所有数值都按照相同方式进行scale与zero-point计算,后者有多种不同的scale与zero-pointc参数,而且精度损失更少。
静态量化
静态量化一般有2种形式,仅weight量化以及weight与activation同时量化。前者主要目的是使得模型参数所占内存减小,且相对简单。后者则相对较为复杂。
在pytorch内静态量化分为5个步骤。(以下步骤主要进行的是模型量化,本质上就是用量化OP替换非量化OP)
(1)fuse_model,就是将可进行融合的op进行融合,比如Conv与BN层进行融合等。融合后第一个op会替换融合后的op,其余op则替换为nn.identity。
fuse_modules(model, modules_to_fuse, inplace=False, fuser_func=fuse_known_modules, fuse_custom_config_dict=None)
(2)qconfig,该步骤目的是设置模型量化的方式,通过插入两个observer来监测activation与weight。同时由于推理平台的不同,pytorch的量化配置也不相同。
(3)prepare,将每个可支持量化的模块插入Observer,收集数据并进行量化分析。
(4)feed data,将一个合适的校验数据送入前述模型中,获得更好的activation的量化参数信息。
(5)convert,运用代码转化模型。
torch.quantization.convert(model, inplace=True)
模型量化后就是量化模型的推理,与浮点模型的区别主要是要进行量化节点的插入以及op替换。
量化节点插入:需要在网络的forward里面插入QuantStub与DeQuantSub两个节点。
op替换:需要将模型中的Add、Concat等操作替换为支持量化的FloatFunctional。