Qualcomm® AI Engine Direct 使用手册(21)

150 篇文章 13 订阅
50 篇文章 2 订阅


8 量化

8.1 概述

非量化模型文件使用网络参数的 32 位浮点表示。量化模型文件使用网络参数的定点表示,通常为 8 位权重和 8 或 32 位偏差。定点表示与 Tensorflow 量化模型中使用的相同。

在量化模型或非量化​​模型之间进行选择

  • CPU - 选择非量化模型。量化模型目前与 CPU 后端不兼容。

  • DSP - 选择量化模型。在 DSP 后端运行时需要量化模型。

  • GPU - 选择非量化模型。量化模型目前与 GPU 后端不兼容。

  • HTP - 选择量化模型。在 HTP 后端运行时需要量化模型。

  • HTA - 选择一个量化模型。在 HTA 后端运行时需要量化模型。

8.2 量化

本节介绍 QNN 中使用的量化算法背后的概念。当开发人员决定量化图形时,转换器将使用这些概念。

概述

QNN 支持多种量化模式。此处描述了无论模式如何的量化基础知识。

  • 量化使用提供的位宽度将浮点数据转换为 Tensorflow 样式的定点格式。

  • 满足以下要求:

    • 涵盖了全部输入值范围。

    • 强制执行最小范围 0.0001。

    • 浮点零可以精确表示。

  • 量化算法输入:

    • 要量化的浮点值集。
  • 量化算法输出:

    • 8 位定点值集。

    • 编码参数:

      • coding-min - 可表示的最小浮点值(通过定点值 0)

      • coding-max - 可表示的最大浮点值(通过定点值 255)

      • scale - 给定范围的步长(最大 - 最小)/ (2^bw-1)

      • offset - 精确表示 0 的整数值。 round(-min/scale)

  • 算法

  1. 计算输入数据的真实范围(最小值、最大值)。

  2. 计算最小编码和最大编码。

  3. 量化输入浮点值。

  4. 输出:

    • 定点值

    • 最小编码和最大编码参数

    • 比例和偏移参数

细节

  1. 计算输入浮点数据的真实范围。

    • 查找输入数据中的最小值和最大值

    • 表示输入数据的真实范围

  2. 计算最小编码和最大编码。

    • 这些参数用于量化步骤。

    • 这些参数定义了定点格式可表示的范围和浮点值。

      • 编码最小值:指定由定点值 0 表示的最小浮点值

      • 编码最大值:指定将由定点值 255 表示的最大浮点值

      • 每个步长的浮点值,其中步长 = (encoding-max - encoding-min) / (2^bw-1),将是可表示的

      • 精确表示零的偏移量

    • 首先将encoding-min和encoding-max设置为上一步中计算出的真实最小值和真实最大值

    • 要求

      1. 编码范围必须至少为 0.0001

        • 将encoding-max调整为max(true max, true min + 0.0001)
      2. 浮点值 0 必须能够精确表示

        • 可以进一步调整encoding-min或encoding-max
  3. 案件 - 处理 0

  • 输入严格为正

编码最小值设置为 0.0

零浮点值可以用最小定点值 0 精确表示

例如输入范围 = [5.0, 10.0]

编码最小值 = 0.0,编码最大值 = 10.0

  • 输入严格为负数

    • 编码最大值设置为 0.0

    • 零浮点值可以由最大定点值 255 精确表示

    • 例如输入范围 = [-20.0, -6.0]

    • 编码最小值 = -20.0,编码最大值 = 0.0

    • 输入有负值和正值

      • 编码最小和编码最大稍微移动以使浮点零可以精确表示
    • 例如输入范围 = [-5.1, 5.1]

      • 首先将encoding-min和encoding-max分别设置为-5.1和5.1

      • 编码范围为10.2,步长为10.2/255 = 0.04

      • 零值目前无法表示。定点值 127 和 128 可表示的最接近值分别为 -0.02 和 +0.02

      • encoding-min 和encoding-max 偏移-0.02。新的编码最小值为-5.12,新的编码最大值为5.08

      • 浮点零现在可以用定点值 128 精确表示

  1. 量化输入浮点值。
  • 上一步中确定的encoding-min和encoding-max参数用于将所有输入浮点值量化为其定点表示

  • 量化公式为:

    • 量化值 = round(255 * (浮点值 - 编码.min) / (编码.max - 编码.min))
  • 量化值也被限制在 0 和 2^bw-1 之间

  1. 输出
  • 定点值

  • 最小编码、最大编码、比例和偏移参数

量化示例

  1. 输入:
  • 输入值 = [-1.8, -1.0, 0, 0.5]

  • 编码最小值设置为 -1.8,编码最大值设置为 0.5

  • 编码范围为2.3,大于要求的0.0001

  • 编码最小值调整为−1.803922,编码最大值调整为0.496078,以使零可以精确表示

  • 步长为 0.009020

  • 偏移量为 200

  1. 输出:
  • 量化值为 [0, 89, 200, 255]

反量化示例

  1. 输入:
  • 量化值 = [0, 89, 200, 255]

  • 编码最小值 = −1.803922,编码最大值 = 0.496078

  • 步长为 0.009020

  • 偏移量为 200

  1. 输出:
  • 反量化值 = [−1.8039, −1.0011, 0.0000, 0.4961]

位宽选择

QNN 目前支持权重和偏差的默认量化位宽为 8。然而,权重、偏差和激活位宽度可以通过传递 –weight_bw、 –bias_bw 和/或 –act_bw 之一并后跟位宽来覆盖。有关命令行选项的更多详细信息,请参阅此处的转换器文档。

8.3 量化模式

QNN 支持四种量化模式:tf、对称、增强和调整。主要区别在于它们如何选择要使用的量化范围。

TF
上面已经描述了默认模式,它使用正在量化的数据的真实最小值/最大值,然后调整范围以确保最小范围并确保 0.0 是精确可量化的。

对称
对称量化遵循与 TF 量化相同的基本原理,但将范围调整为对称。它通过从原始范围中选择新的最小值和最大值来实现此目的,使得 new_max=max(abs(min), abs(max)) 并将范围调整为 (-new_max, max) 以使范围围绕 0 对称.这通常仅用于权重,因为它有助于减少运行时的计算开销。通过将 –param_quantizer 对称传递给其中一个转换器来启用此模式。

增强型
增强量化模式(通过将“enhanced”传递给其中一个转换器–param_quantizer中的或选项来调用)使用一种算法来尝试确定一组更好的量化参数以提高精度。该算法可能会选择与默认量化器不同的最小/最大值,并且在某些情况下,它可能会设置范围,使得一些原始权重和/或激活不能落入该范围。然而,这个范围确实比简单地使用真实的最小值/最大值产生更好的精度。通过在选项后附加“权重”或“激活”,可以独立启用增强量化器的权重和激活。–act_quantizer

这对于权重和/或激活可能具有“长尾”的某些模型很有用。(想象一个范围,其中大多数值在 -100 到 1000 之间,但少数值远大于 1000 或远小于 -100。)在某些情况下,可以忽略这些长尾,并且可以更有效地使用范围 -100, 1000比全系列。

增强型量化器仍然强制执行最小范围并确保 0.0 是精确可量化的。

TF 调整
此模式仅用于将权重量化为 8 位定点(通过将“调整”传递给转换器之一中的–param_quantizer或选项来调用),它使用正在量化的数据的调整后的最小值或最大值,而不是真正的最小值/最大值或排除长尾的最小/最大。经验证,这能够为降噪模型提供准确度优势。使用此量化器,如有必要,最大值将被扩大,最小值将被减小。–act_quantizer

调整后的权重量化器仍然强制执行最小范围并确保 0.0 是完全可量化的。

8.4 增强的量化技术

由于训练技术、模型架构和层类型多种多样,量化可能是一个很难解决的问题。为了缓解量化问题,量化器中添加了模型预处理技术,可以提高量化精度急剧下降的模型的量化性能。

引入的主要技术是 CLE(跨层均衡)。

CLE 的工作原理是利用激活函数的尺度等方差性质来缩放网络中的卷积权重范围。此外,该过程吸收了可能由于从一个卷积层到后续卷积层的权重缩放而导致的高偏差。

增强量化技术:局限性
在许多情况下,CLE 可以使量化模型恢复到接近其原始浮点精度。当前算法有一些警告/限制:

CLE 对特定的操作模式进行操作,这些操作全部存在于单个分支中(输出不能被多个操作消耗)。匹配的操作模式(r=必需,o=可选)是:

Conv®->Batchnorm®->激活(o)->Conv®->Batchnorm®->激活(o) Conv®->Batchnorm®->激活(o) ->DepthwiseConv®->Batchnorm®->激活(o)->Conv®->Batchnorm®->激活(o)

CLE 算法目前仅支持 Relu 激活。任何 Relu6 激活都会自动更改为 Relu,除此之外的任何激活都会导致算法忽略前面的卷积。通常,从 Relu6 到 Relu 的切换是无害的,不会导致精度下降,但某些模型可能会出现轻微的精度下降。在这种情况下,CLE 只能将精度恢复到降低的水平,而不能恢复到原始浮动精度。CLE 要求在转换为 DLC 之前原始模型中存在批规范(特别是可检测的批规范 beta/gamma 数据),以便运行完整的算法并重新获得最大精度。对于 Tensorflow,即使使用折叠批量规范,有时仍然可以找到 beta 和 gamma,只要折叠没有将参数折叠到卷积的静态权重和偏差中。如果它没有检测到所需的信息,您可能会看到类似以下的消息:“HBA 量化算法模型无效。” 这表明该算法将仅部分运行,并且可能存在准确性问题。

要运行 CLE,只需将选项 –algorithms cle 添加到转换器命令行即可。

有关算法的更多信息可以在这里找到:[ https://arxiv.org/abs/1906.04721 ]

量化影响
量化模型和/或在量化运行时(如 HTP)中运行模型可能会影响准确性。某些模型在量化时可能无法正常工作,并且可能会产生不正确的结果。用于衡量量化对分类模型影响的指标通常是“平均精度”、“Top-1 误差”和“Top-5 误差”。

量化覆盖
如果提供了选项 –quantization_overrides,用户可以提供一个带有用于量化的参数的 json 文件。这些将覆盖转换过程中携带的任何量化数据(例如 TF 伪量化)或在正常量化过程中计算的量化数据。根据 AIMET 规范定义的格式。

json 中有两个部分,一个用于覆盖运算符输出编码的部分(称为“activation_encodings”)和一个用于覆盖参数(权重和偏差)编码的部分(称为“param_encodings”)。两者都必须存在于文件中,但如果不需要覆盖,则可以为空。包含当前支持的所有选项的示例:

{
   "activation_encodings": {
       "Conv1:0": [
           {
               "bitwidth": 8,
               "max": 12.82344407824954,
               "min": 0.0,
               "offset": 0,
               "scale": 0.050288015993135454
           }
       ],
       "input:0": [
           {
               "bitwidth": 8,
               "max": 0.9960872825108046,
               "min": -1.0039304197656937,
               "offset": 127,
               "scale": 0.007843206675594112
           }
       ]
   },
   "param_encodings": {
       "Conv2d/weights": [
           {
               "bitwidth": 8,
               "max": 1.700559472933134,
               "min": -2.1006477158567995,
               "offset": 140,
               "scale": 0.01490669485799974
           }
       ]
   }
}

请注意,不需要提供比例和偏移量。如果提供了它们,则将使用它们,否则将根据提供的 bw、min 和 max 参数计算它们。

每通道量化覆盖
每通道量化应用于作为 Conv 使用者(Conv2d、Conv3d、TransposeConv2d、DepthwiseConv2d)权重输入的张量。本节提供了手动覆盖这些基于 Conv 的运算权重张量的每通道编码的示例。当我们为给定张量提供多个编码(等于通道数)时,将使用每通道量化。我们看到以下情况的卷积权重示例。

情况 1:没有每通道量化的非对称编码

{
    "features.9.conv.3.weight": [
        {
            "bitwidth": 8,
            "is_symmetric": "False",
            "max": 3.0387749017453665,
            "min": -2.059169834735364,
            "offset": -103,
            "scale": 0.019991940143061618
        }
    ]
}

情况 2:具有 3 个输出通道的每通道量化编码

{
    "features.8.conv.3.weight": [
        {
            "bitwidth": 8,
            "is_symmetric": "True",
            "max": 0.7011175155639648,
            "min": -0.7066381259227362,
            "offset": -128.0,
            "scale": 0.005520610358771377
        },
        {
            "bitwidth": 8,
            "is_symmetric": "True",
            "max": 0.5228064656257629,
            "min": -0.5269230519692729,
            "offset": -128.0,
            "scale": 0.004116586343509945
        },
        {
            "bitwidth": 8,
            "is_symmetric": "True",
            "max": 0.7368279099464417,
            "min": -0.7426297045129491,
            "offset": -128.0,
            "scale": 0.005801794566507415
        }
    ]
}

注意:每通道量化必须使用偏移 == -2^(bitwidth-1) 的对称表示。每个通道始终具有 is_symmetry = True。

8.5 量化模型

要启用量化,只需将选项 –input_list 以及包含原始数据输入的文本文件传递到网络即可。请注意,此文件中指定的输入应与转换生成的 .cpp 文件中的输入完全匹配。在大多数情况下,这些输入可以直接从源框架模型中获得。然而,在极少数情况下,例如当输入被转换器修剪时,这些输入可能会有所不同。文件的格式对每组网络输入使用一行:

<inputFile0>
<inputFile1>
<inputFile2>

如果网络包含多个输入,则它们全部列在一行上,以空格分隔,并以输入名称和“:=”开头

<inputNameA>:=<inputFile0a> <inputNameB>:=<inputFile0b>
<inputNameA>:=<inputFile1a> <inputNameB>:=<inputFile1b>
<inputNameA>:=<inputFile2a> <inputNameB>:=<inputFile2b>

例子
对于包含单个输入的图形,输入文本文件将包含类似以下内容的内容:

/path/to/file/chair.raw
/path/to/file/mongoose.raw
/path/to/file/honeybadger.raw

对于包含多个图输入的网络:

input_left_eye:=left0.rawtensor input_right_eye:=right0.rawtensor
input_left_eye:=left1.rawtensor input_right_eye:=right1.rawtensor
input_left_eye:=left2.rawtensor input_right_eye:=right2.rawtensor

8.6 混合精度和 FP16 支持

混合精度允许为同一图中的不同操作指定不同的位宽度(例如 INT8 或 INT16)或数据类型(整数或浮点)。当连续操作之间的激活精度或数据类型不同时,会自动插入数据类型转换操作。图形可以混合使用浮点和定点数据类型。每个操作可以具有不同的权重和激活精度。然而,对于特定的操作,要么所有输入、输出和参数(权重/偏差)都是浮点型,要么全部都是整数类型。请参阅后端补充,了解特定操作支持的权重/激活位宽度。

  • 中央处理器

  • 图形处理器

  • 高温TP

  • HTP FP16

FP16(半精度)还可以将整个模型转换为 FP16,或者在浮点和整数运算混合的混合精度图的情况下,在浮点运算的 FP16 和 FP32 数据类型之间进行选择。下面描述了使用混合精度的不同模式。

非量化模式
在此模式下,不会向转换器提供校准图像(未提供 –input_list 标志)。转换后的 QNN 模型仅具有用于激活和权重的浮点张量。

  • 非量化 FP16:如果在命令行中添加“–float_bw 16”,则所有激活和权重/偏差张量都将转换为 FP16。

  • 非量化 FP32:如果命令行中缺少“–float_bw”或给出“–float_bw 32”,则所有激活和权重/偏差张量都使用 FP32 格式。

量化模式
在这种模式下,校准图像被提供给转换器(–input_list 被提供)。转换后的 QNN 模型具有用于激活和权重的定点张量。

  • 无覆盖:如果编码文件没有给出 –quantization_overrides 标志,则所有激活均按照 –act_bw(默认 8)进行量化,并且参数分别按照 –weight_bw/–bias_bw(默认 8/8)进行量化。

  • 完全覆盖:如果给出 –quantization_overrides 标志以及指定模型中所有操作的编码的编码文件。在这种情况下,对于根据编码文件定义为整数/浮点的所有操作,位宽将根据 JSON 设置(编码 json 中的 dtype=‘int’ 或 dtype=‘float’)。

  • 部分覆盖:如果 –quantization_overrides 标志与指定部分编码的编码文件一起给出(即某些操作缺少编码),则会发生以下情况。

    • json 文件中不可用编码的层以与无覆盖情况相同的方式进行编码,即定义为整数,其位宽按照 –act_bw/–weight_bw/–bias_bw 定义(或其默认值 8/8/8)。对于某些操作(Conv2d、Conv3d、TransposeConv2d、DepthwiseConv2d、FullyConnected、MatMul),即使任何输出/权重/偏差在编码文件中指定为浮点,所有三个操作都将被覆盖为浮点。使用的浮点位宽将与编码文件中覆盖张量的浮点位宽相同。在这种情况下,我们还可以使用 –float_bias_bw (16/32) 标志手动控制偏差张量的位宽(如果编码 json 中不存在它的编码并且存在于输出/权重中)。

    • json 中可用编码的层的编码方式与完全覆盖情况相同。

我们展示了具有 3 个 Conv2d 操作的网络的示例 json。第一个和第三个 Conv2d 操作是 INT8,而第二个 Conv2d 操作标记为 FP32。FP32 操作(即 conv2_1)夹在“activation_encodings”中的两个 INT8 操作之间,因此转换操作将插入到 FP32 操作之前和之后。conv2_1 相应的权重和偏差也在“param_encodings”中的 JSON 中标记为浮点型。

{
   "activation_encodings": {
       "data_0": [
           {
               "bitwidth": 8,
               "dtype": "int"
           }
       ],
       "conv1_1": [
           {
               "bitwidth": 8,
               "dtype": "int"
           }
       ],
       "conv2_1": [
           {
               "bitwidth": 32,
               "dtype": "float"
           }
       ],
       "conv3_1": [
           {
               "bitwidth": 8,
               "dtype": "int"
           }
       ]
   },
   "param_encodings": {
       "conv1_w_0": [
           {
               "bitwidth": 8,
               "dtype": "int"
           }
       ],
       "conv1_b_0": [
           {
               "bitwidth": 8,
               "dtype": "int"
           }
       ],
       "conv2_w_0": [
           {
               "bitwidth": 32,
               "dtype": "float"
           }
       ],
       "conv2_b_0": [
           {
               "bitwidth": 32,
               "dtype": "float"
           }
       ],
       "conv3_w_0": [
           {
               "bitwidth": 8,
               "dtype": "int"
           }
       ],
       "conv3_b_0": [
           {
               "bitwidth": 8,
               "dtype": "int"
           }
       ]
   }
}

json 中不存在的操作将被假定为定点,并且将分别根据 –act_bw/–weight_bw/–bias_bw 选择位宽度。

{
   "activation_encodings": {
       "conv2_1": [
           {
               "bitwidth": 32,
               "dtype": "float"
           }
       ]
   },
   "param_encodings": {
       "conv2_w_0": [
           {
               "bitwidth": 32,
               "dtype": "float"
           }
       ],
       "conv2_b_0": [
           {
               "bitwidth": 32,
               "dtype": "float"
           }
       ]
   },
   "version": "0.5.0"
}

下面的量化混合精度图将根据上面显示的 JSON 生成。请注意,适当添加转换操作以在 float 和 int 类型之间进行转换,反之亦然。

请添加图片描述

  • 17
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值