int8量化

梯度量化

参考:

http://on-demand.gputechconf.com/gtc/2017/presentation/s7310-8-bit-inference-with-tensorrt.pdf

目标:将FP32的数据转换为INT8,并且精度不会降低很多

为什么:INT8有更高的吞吐量,更低的内存占用

挑战:INT8精确度低的问题

解决办法:在量化训练好的模型参数和计算的时候最小化信息损失

结果:TensorRT已经搞定了这些

量化 原理

一句话原理

将fp32的卷积(相乘)转换为int8的卷积(相乘)

A = scale_A * QA + bias_A

B = scale_B * QB + bias_B

AB = scale_A scale_B QA\QB +

​ scale_A *QA+ bias_B +

​ scale_B *QB + bias_A +

​ bias_A * bias_B

英伟达通过实验说不要偏置也没有影响

A = scale_A * QA

B = scale_B * QB

AB = scale_A QA*scale_B * QB

线性量化

将FP32的值线性映射到一个-127~127之间的数 ,具体的做法是将参数从小到大排列,然后平均分成255份,最小的那一份的数对应-127,次小的那一份数对应-126…

1559040708301

饱和量化

将fp32过大过小的值去掉,再执行线性映射

1559040732799

如何找到合适的阈值

1559039847512

  1. 收集不同样本计算下参数的直方图 ,比如某一层resnet_52_conv
  2. 产生很多阈值,将FP32的值映射到int8
  3. 让不同阈值的FP32激活值分布和INT8激活值做KL_divergence,选出该最小对应的阈值

如何做KL散度

1559039779276

1559039935491

$$KL = min(H(P)-H(Q))$$,P为参考样本,Q为int8计算之后的样本

LK_divergence具体是怎么做的?

小目标检测中,转tensorrt精度会有很大的损失,原因是系统把红绿灯那一小块卷积后的结果当成噪点处理了,被截断,这是猜想

  1. 不断阶段参考样本,从128开始
  2. 将截断外的数值求和
  3. 将2中得到的值添加到阶段样本P之后
  4. 求样本P的概率分布
  5. 创建样本Q,它是从P的INT8量化
  6. 将样本Q拉伸到和P一样长
  7. 计算Q的概率分布
  8. 求P,Q的KL散度,得到T