zoukankan      html  css  js  c++  java
  • tensorrt int8量化原理几点问题记录

    1.重新编码后是如何运算得到最终结果的?

    (1)如何用int8表示float32的计算?

      其实就是多了一个放大倍数的问题,举个例子:比如原来float32的计算为:0.1 * 0.2 + 0.3 * 0.4 = 0.14,那么使用int8计算:1*2 + 3*4 = 14,相当于原来的数值都取10倍放大倍数(int8标定也就是标定这个放大倍数),那么由于乘法的原因,最后的结果相当于放大了100倍.这样就能使用Int8来取代float32的计算.

    (2)怎么解决偏置问题及溢出问题?

      假设我们的网络是卷积后面紧跟着偏置,例如:原来float32的计算为:0.1*0.2 + 0.1 = 0.12,这时候如果采取和上面一样的策略,那么就会得到:1*2+1 = 3,再缩小100倍得到结果:0.03,问题出在偏置放大了10倍,前面是个乘法运算,相当于放大了100倍,也就是说带偏置的层要特殊处理一下?

      另一个问题:用Int8计算卷积是很容易溢出了,比如:56*45这个值明显大于INT8_MAX == 127,这时候怎么处理?

    nvdia官方的tensorrt-int8文档(http://on-demand.gputechconf.com/gtc/2017/presentation/s7310-8-bit-inference-with-tensorrt.pdf)给了一个计算卷积层的例子,可以很好的解释这两个疑惑,如图所示:

     可以看出:

    ①在计算卷积的时候,使用了int32作为中间值,这样就解决了溢出问题(对于目前的卷积核大小,用Int8乘积之后再做和是不可能超出int32的范围的).

    ②带偏置的层不是直接用int8计算,而是先转换为fp32计算出结果,再变换为int8,变换过程就是一个线性映射,不会太耗费资源.

    另外还可以解释一些其他疑惑:比如权重的scale是如何确定的?看上图中的weights_scale[K]是个数组,代表的应该是不同输出channel的放大倍数值,因此可以猜测,weights的不同输出通道可能有不同的放大倍数,但是因为weights的分布是固定的,因此通常weights采用不饱和量化就可以(参考https://zhuanlan.zhihu.com/p/58208691https://arleyzhang.github.io/articles/923e2c40/),个人感觉采用饱和的量化方式,精度可能有提高,比如确定了每个通道的最大值和最小值,将最大值映射为127,最小值映射为-128,总比将float32_max映射为127能取得更好的精度(仅为个人猜测).

    2.KL散度的基本概念?

    https://www.zhihu.com/question/41252833

    tensorrt如何利用KL散度求取放大倍数(或者称为映射阈值)?

    求取过程大致如下:

    ①选择一个测试集的子集,获取原来分布的直方图(直方图的区间个数为2048个(bins),每个区间的范围就是:(最大激活值-最小激活值)/ 2048)

    ②依次取第i个bins的值为阈值(为什么i从128开始取,因为如果i取小于127时,KL散度肯定要比i取127时大,因此i小于128的情况根本不用考虑),然后求取以此值为阈值的Int8分布。再求取原分布与新分布的KL散度值,最终取使KL最小的索引值,设为m,然后阈值设为(m+0.5)*一个bin的长度.

    文章:https://arleyzhang.github.io/articles/923e2c40/中提出一个疑问:标定的T值怎么会小于128,原因是作者误将索引和激活值混为一谈,m的值是不会小于128的,但是m只是个索引,T = (m+0.5)*一个bin的长度,T是激活值,激活值是有可能出现任意值的.

    3.激活值的分布不考虑负值么?

    上面的例子发现bin的的索引从128开始取,是没有考虑激活值为负数的情况,原因是nvidia官方给的tensorrt-int8量化的例子激活函数都是relu,意味着激活值没有负值,因此可以不考虑负值,但是如果激活函数采用的不是relu,比如会产生负的激活值的tanh函数,那么在量化的时候(即确定放大倍数的时候)就要考虑负的激活值.具体如何考虑,个人猜测为:找到直方图中的0点,从bin[start] = 0,这个start±128位置向两端遍历,求取KL散度的最小值的索引值.

    4.求KL散度时长度不同问题怎么解决?

    在上面计算KL散度之前有一步为:expand candidate_distribution_Q to 'i' bins,计算两个分布的KL散度时,要求分布长度是相同的,原分布映射为int8分布后,长度变为128,而原分布的长度为i(将大于i的直方图分布结果加和值bin[i],保证分布完整性),因此必须先将分布长度调整一致,参考官方文档:

    另外计算KL散度前,要先进行归一化处理.

  • 相关阅读:
    10.9 第七次作业游戏
    10.23 第六次作业 刘惠惠 this关键字
    第五次作业 刘惠惠 自动生成的方法存根
    谷歌历史影像下载
    ArcGIS 基础13-整饰输出
    ArcGIS 基础12-保存文件并打包
    ArcGIS 基础11-专题制图
    ArcGIS 基础10-拓扑校验
    ArcGIS 基础9-属性查询和空间查询
    ArcGIS 基础8-坐标系转换
  • 原文地址:https://www.cnblogs.com/deepllz/p/11672912.html
Copyright © 2011-2022 走看看