TensorRT量化第三课:动态范围的常用计算方法

目录

  • 模型量化原理
    • 前言
    • 1.前情回顾
    • 2.动态范围的常用计算方法
    • 3.Histogram
      • 3.1 定义
      • 3.2 histogram实现
      • 3.3 思考
      • 3.4 拓展
    • 总结

模型量化原理

前言

手写AI推出的全新TensorRT模型量化课程,链接。记录下个人学习笔记,仅供自己参考。

本次课程为第三课,主要讲解动态范围的常用计算方法。

课程大纲可看下面的思维导图

TensorRT量化第三课:动态范围的常用计算方法_第1张图片

1.前情回顾

在之前的课程中我们学习了对称量化和非对称量化的知识,在tensorRT中的INT8量化使用的方法就是对称量化。上节课提出在对称量化中存在一个问题,就是当数据中存在极端值时,会对量化精度造成不利影响,这节课我们就一起来学习相关解决方案。

2.动态范围的常用计算方法

首先来看下本次课程的题目,动态范围的常用计算方法,之前似乎没有提过呀,有点抽象()。

动态范围(Dynamic Range)指的是输入数据中数值的范围,计算动态范围是为了确定量化时使用的比特位数(还是抽象)。个人理解计算动态范围就是为了获得更好的Scale,毕竟Scale会影响到整个量化的精度,而Scale的计算和输入数据的值域范围息息相关(即值域的动态范围),在上节课中非对称量化过程中Scale计算为 S c a l e = ( R m a x − R m i n ) ( Q m a x − Q m i n ) Scale = \frac{(Rmax-Rmin)}{(Qmax-Qmin)} Scale=(QmaxQmin)(RmaxRmin),而对称量化过程中的Scale计算为 S c a l e = ∣ R m a x ∣ Q m a x Scale = \frac{|Rmax|}{Qmax} Scale=QmaxRmax,都与输入数据的数值范围相关。

现在来看看动态范围的计算方法,动态范围的计算方法与量化的方式相关,对称量化和非对称量化使用的计算方法略有不同。在对称量化中,通常采用的是输入数据的绝对值的最大值作为动态范围的计算方法;而在非对称量化中,通常采用最小值和最大值的差作为动态范围的计算方法

经过上面分析就不难理解题目动态范围的常用计算方法,在之前对称量化中的动态范围的计算方法就是Max方法即采取输入数据的绝对值的最大值,但是这种计算方法存在问题,就是容易受到离散点即噪声的干扰,我们的考虑改进,或者说采取其它的动态范围计算方法,也就是本节课程的Histogram以及Entropy方法。

常用的动态范围计算方法包括:(from chatGPT)

  • Max方法:在对称量化中直接取输入数据中的绝对值的最大值作为量化的最大值。这种方法简单易用,但容易受到噪声等异常数据的影响,导致动态范围不准确。
  • Histogram方法:统计输入数据的直方图,根据先验知识获取某个范围内的数据,从而获得对称量化的最大值。这种方法可以减少噪声对动态范围的影响,但需要对直方图进行统计,计算复杂度较高。
  • Entropy方法:将输入数据的概率密度函数近似为一个高斯分布,以最小化熵作为选择动态范围的准则。这种方法也可以在一定程度上减少噪声对动态范围的影响,但需要对概率密度函数进行拟合和计算熵,计算复杂度较高。

对称量化和非对称量化的选择与动态范围的计算方法有一定的关系。对称量化要求量化的最大值和最小值的绝对值相等,可以采用Max方法或Histogram方法进行计算。非对称量化则可以采用Entropy方法进行计算,以最小化量化后的误差。

3.Histogram

3.1 定义

直方图(histogram)是统计学中常用的一种图形,它将数据按照数值分组并统计每组数据的出现频率,然后将频率用柱状图的方式表示出来。直方图通常用于描述一组数据的分布情况,可以帮助人们了解数据的特征,例如数据的中心位置、离散程度、对称性、峰态等(from chatGPT)

下面是一张直方图的示例:

TensorRT量化第三课:动态范围的常用计算方法_第2张图片

下面是该直方图生成的示例代码:

import numpy as np
import matplotlib.pyplot as plt

data = np.random.randn(1000)

plt.hist(data, bins=50)

plt.title("histgram")
plt.xlabel("value")
plt.ylabel("freq")
# plt.savefig("histgram.png", bbox_inches="tight")
plt.show()

在上述代码中首先使用numpy生成了一组包含1000个随机数的数据,然后调用matplotlib库中的plt.hist()函数生成该数据的直方图。其中data参数表示要绘制的数据,bins表示直方图的柱子数量,这里设置为50个。

3.2 histogram实现

histogram方法为什么能克服Max方法中离散点即噪声干扰问题呢?主要在于直方图统计了数据出现的频率,它可以将数据按照一定的区间进行离散化处理,并计算每个区间中数据点的数量。这种方法相对于Max方法来说,能够更好地反映数据的分布情况,从而更准确地评估数据的动态范围。我们假设数据服从正态分布,即离散点在两边,我们可以通过从两边向中间靠拢的方法,去除离散点,类似于双指针的方法,算法具体流程如下:

  • 首先,统计输入数据的直方图和范围
  • 然后定义左指针和右指针分别指向直方图的左边界和右边界
  • 计算当前双指针之间的直方图覆盖率,如果小于等于设定的覆盖率阈值,则返回此刻的左指针指向的直方图值,如果不满足,则需要调整双指针的值,向中间靠拢
  • 如果当前左指针所指向的直方图值大于右指针所指向的直方图值,则右指针左移,否则左指针右移
  • 循环,直到双指针覆盖的区域满足要求

下面是该算法流程的一个简单示例:

TensorRT量化第三课:动态范围的常用计算方法_第3张图片

其中0~5代表算法执行的步骤,首先双指针位于直方图的左右区间,然后计算其覆盖率发现不满足设定的阈值要求,计算此时的左指针的直方图值小于右指针的直方图值,左指针右移即步骤1,继续上述步骤发现覆盖率还是不满足,且此时右指针值小故右指针左移即步骤2,以此类推到步骤3、步骤4,到步骤4计算发现覆盖率满足阈值要求,故将此时的双指针的直方图值的绝对值返回即可。

通过上面的分析,示例代码如下:

def scale_cal(x):
    max_val = np.max(np.abs(x))
    return max_val / 127

def histogram_range(x):
    hist, range = np.histogram(x, 100)
    total = len(x)
    left  = 0
    right = len(hist) - 1
    limit = 0.99
    while True:
        cover_percent = hist[left:right].sum() / total
        if cover_percent <= limit:
            break

        if hist[left] > hist[right]:
            right -= 1
        else:
            left += 1
    
    left_val = range[left]
    right_val = range[right]
    dynamic_range = max(abs(left_val), abs(right_val))
    return dynamic_range / 127

if __name__ == "__main__":
    np.random.seed(1)
    data_float32 = np.random.randn(1000).astype('float32')
    # print(f"input = {data_float32}")

    scale = scale_cal(data_float32)
    scale2 = histogram_range(data_float32)
    print(f"scale = {scale}  scale2 = {scale2}")

上述代码中histogram_range函数是基于数据直方图计算缩放因子的,该函数先将数据进行直方图统计,然后使用双指针算法去除数据直方图中的离散点,最后通过剩余数据的动态范围计算出缩放因子。

3.3 思考

Histogram方法虽然能够解决Max方法中的离散点噪声问题,但是使用数据直方图进行动态范围的计算,要求数据能够比较均匀地覆盖到整个动态范围内。如果数据服从类似正态分布,则直方图的结果具有参考价值,因为此时的数据覆盖动态范围的概率较高。但如果数据分布极不均匀或出现大量离散群,则直方图计算的结果可能并不准确。此时可考虑其它的动态范围计算方法。

3.4 拓展

np.histogram是用于生成直方图的函数,其参数和返回值如下:

参数

  • a:待处理的数据,可以是一维或者多维数组,多维数组将会被展开成一维数组
  • bins:表示数据分成的区间数
  • range:表示数据的取值范围,可以是一个元组或数组
  • density:是否将直方图归一化。如果为True,直方图将归一化为概率密度函数。默认False
  • weights:每个数据点的权重,可以是一维数组或与a数组相同的形状的数组。默认为None,表示所有的数据点权重相同。

返回值

  • hist:一个长度为bins的一维数组,表示每个区间中数据点的数量或者归一化后的概率密度值。
  • bin_edges:长度为bins + 1的一维数组,表示每个区间的边界。

总结

本次课程学习了动态范围计算中的直方图计算,该方法可解决Max方法中离散点问题,但同时要求数据的分布要均匀,不能出现过多的离散群。期待下次的动态范围计算方法Entropy

你可能感兴趣的:(量化,深度学习,模型量化,TensorRT)