TensorRT-INT8校准原理

摘抄自此git blogIN8校准原理,做了点注释,侵删

  • No saturation(不饱和映射):简单的将一个tensor 中的 -|max| 和 |max| FP32 value 映射为 -127 和 127 ,中间值按照线性关系进行映射。但是试验结果显示这样做会导致比较大的精度损失。
    在这里插入图片描述

  • Saturate(饱和映射)

    • 这种做法不是将 ±|max| 映射为 ±127,而是存在一个 阈值 |T| ,将 ±|T| 映射为±127,显然这里 |T|<|max|。
    • 只要 阈值 选取得当,就能将分布散乱的较大的激活值舍弃掉,也就有可能使精度损失不至于降低太多。在这里插入图片描述
  • 网络的前向计算涉及到两部分数值:权值和激活值(weights 和activation,二者要做乘法运算),Szymon Migacz 也提到他们曾经做过实验,说对weights 做saturation 没有什么变化,因此 对于weights的int8量化就使用的是不饱和的方式;而对activation做saturation就有比较显著的性能提升,因此对activation使用的是饱和的量化方式。

  • 使用KL距离确定|T|:映射后的分布(如INT8分布)要和FP32的分布最接近

    • 首先在 校准集上 进行 FP32 inference 推理;
    • 对于网络的每一层(遍历):
      • 收集这一层的激活值,并做 直方图(histograms ),分成几个组别(bins)(官方给的一个说明使用的是2048组),分组是为了下面遍历 |T| 时,减少遍历次数(注:总不能每个连续值都去计算一下分布相似度);
      • 对于不同的 阈值 |T| 进行遍历,因为这里 |T|的取值肯定在 第128-2047 组之间,所以就选取每组的中间值进行遍历;选取使得 KL_divergence(ref_distr, quant_distr) 取得最小值的 |T|。
    • 返回一系列 |T|值,每一层都有一个 |T|。创建 CalibrationTable 。
    • 上面解释一下:假设 最后 使得 KL散度最小的|T|值是第200组的中间值,那么就把原来 第 0-200组的 数值线性映射到 0-128之间,超出范围的直接映射到128。直方图统计举例
      在这里插入图片描述
  • 伪代码

//首先分成 2048个组,每组包含多个数值(基本都是小数)
Input: FP32 histogram H with 2048 bins: bin[ 0 ],, bin[ 2047 ] 
  
For i in range( 128 , 2048 ): // |T|的取值肯定在 第128-2047 组之间,取每组的中点
	reference_distribution_P = [ bin[ 0 ] , ..., bin[ i-1 ] ] // 选取前 i 组构成P,i>=128
	outliers_count = sum( bin[ i ] , bin[ i+1 ] ,, bin[ 2047 ] ) //边界外的组
	reference_distribution_P[ i-1 ] += outliers_count //边界外的组加到边界P[i-1]上,没有直接丢掉
	P /= sum(P) // 归一化
      
    // 将前面的P(包含i个组,i>=128),映射到 0-128 上,映射后的称为Q,Q包含128个组,
    // 一个整数是一组
	candidate_distribution_Q = quantize [ bin[ 0 ],, bin[ i-1 ] ] into 128 levels
	
	//这时的P(包含i个组,i>=128)和Q向量(包含128个组)的大小是不一样的,无法直接计算二者的KL散度
	//因此需要将Q扩展为 i 个组,以保证跟P大小一样
	expand candidate_distribution_Q to ‘ i ’ bins 
	
	Q /= sum(Q) // 归一化
	//计算P和Q的KL散度
	divergence[ i ] = KL_divergence( reference_distribution_P, candidate_distribution_Q)
End For
//找出 divergence[ i ] 最小的数值,假设 divergence[m] 最小,
//那么|T|=( m + 0.5 ) * ( width of a bin )
Find index ‘m’ for which divergence[ m ] is minimal
threshold = ( m + 0.5 ) * ( width of a bin )
  • 代码部分解释:在这里插入图片描述

  • 部分校准结果:我们来看看 ResNet-152中 res4b30层校准前后的结果对比在这里插入图片描述

总结:本文主要记录INT8的校准方式,核心内容来自于文章开头的blog,说的比较清楚。除此之外,量化还有其他内容,比如如何量化、反量化,CPU、GPU如何实现INT8的计算等,待补充
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值