骁龙神经处理引擎SDK参考指南(3)

281 篇文章 30 订阅
SNPE支持的网络层包括GPU和DSP运行时,提供浮点和量化模型。量化涉及将32位浮点参数转换为8位定点,影响包括初始化时间、内存使用和精度。量化算法确保范围覆盖和零点精确表示,而增强量化模式和调整权重重量化旨在提高准确性。混合精度支持不同操作的位宽和数据类型,允许在浮点和定点间转换。量化和非量化模型的选择取决于GPU和DSP的性能需求与精度平衡。
摘要由CSDN通过智能技术生成


4 网络模型

4.1 支持的网络层

支持的网络层

SNPE 支持下表中列出的网络层类型。

有关受支持的运行时和各个层类型的限制和约束的详细信息,请参阅限制。

GPU 运行时中所有支持的层对两种 GPU 模式均有效:GPU_FLOAT32_16_HYBRID 和 GPU_FLOAT16。
GPU_FLOAT32_16_HYBRID - 数据存储以半浮点方式完成,计算以全浮点方式完成。
GPU_FLOAT16 - 数据存储和计算均以半浮点数完成。

可以在ONNX 运营商支持找到受支持的 ONNX 操作列表。

注意:此表已过时,不反映支持的层/后端的当前状态。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.2 支持的 ONNX 操作

运营商支持
snpe-onnx-to-dlc 目前支持以下运算符和参数:

在这里插入图片描述

4.3 量化与非量化

4.3.1 概述

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

Caffe and Caffe2

snpe-caffe-to-dlc和 tools_snpe-caffe2-to-dlc的默认输出是非量化模型。这意味着所有网络参数都保留在原始 Caffe 模型中存在的 32 位浮点表示中。要将模型量化为 8 位定点,请参阅snpe-dlc-quantize。请注意,打算使用snpe-dlc-quantize进行量化的模型必须将其批量维度设置为 1。通过在初始化期间调整网络大小,可以在推理期间使用不同的批量维度。

ONNX

snpe-onnx-to-dlc的默认输出是非量化模型。这意味着所有网络参数都保留在原始 ONNX 模型中的 32 位浮点表示中。要将模型量化为 8 位定点,请参阅snpe-dlc-quantize。请注意,打算使用snpe-dlc-quantize进行量化的模型必须将其批量维度设置为 1。通过在初始化期间调整网络大小,可以在推理期间使用不同的批量维度。

TensorFlow

snpe-tensorflow-to-dlc的默认输出是非量化模型。这意味着所有网络参数都保留在原始 TensorFlow 模型中的 32 位浮点表示中。要将模型量化为 8 位定点,请参阅snpe-dlc-quantize。请注意,打算使用snpe-dlc-quantize进行量化的模型必须将其批量维度设置为 1。通过在初始化期间调整网络大小,可以在推理期间使用不同的批量维度。

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

概括
在这里插入图片描述
细节

  • 显卡和中央处理器
    • GPU 和 CPU 始终使用浮点(非量化)网络参数。
    • 支持使用具有 GPU 和 CPU 运行时的量化 DLC 文件。网络初始化时间将显着增加,因为 SNPE 将自动对网络参数进行反量化,以便在 GPU 和 CPU 上运行。
    • 如果担心网络初始化时间,建议对 GPU 和 CPU 使用非量化 DLC 文件(默认)。
    • DLC 文件的量化确实会引入噪声,因为量化是有损的。
    • 执行期间的网络性能不受量化与非量化 DLC 文件选择的影响。
  • 数字信号处理器
    • DSP 总是使用量化的网络参数。
    • 支持在 DSP 上使用非量化 DLC 文件。网络初始化时间将显着增加,因为 SNPE 将自动量化网络参数以便在 DSP 上运行。
    • 一般推荐使用量化后的DLC文件在DSP上运行。除了缩短网络初始化时间外,使用量化模型还可以减少初始化期间的内存使用峰值,并减小 DLC 文件的大小。
  • AIP
    • AIP 运行时始终使用量化的网络参数。
    • 必须通过 snpe-dlc-quantize 才能为 HTA 子网生成二进制文件。
    • 不支持将非量化 DLC 文件与 AIP 运行时一起使用。
    • HTA 子网使用 DLC 中的量化参数。
    • HNN (Hexagon NN) 子网使用量化参数的方式与 DSP 运行时相同。
  • 平衡 DLC 文件大小、网络初始化时间和准确性
    • 如果网络主要在 GPU 和 CPU 上运行,建议在开发过程中同时尝试量化和非量化模型。如果量化模型提供了足够的准确性, 那么它可能会以增加网络初始化时间为代价来使用。好处是 DLC 文件小得多。准确性、网络初始化时间和 DLC 文件大小之间的权衡是特定于应用程序的。
    • 如果网络主要在 DSP 上运行,则使用非量化模型没有任何好处。如前所述,它会显着增加网络初始化时间和 DLC 文件大小,但不会提高准确性。

4.3.3 量化算法

本节介绍 SNPE 中使用的量化算法背后的概念。这些概念被snpe-dlc-quantize使用,也被 SNPE 在使用 DSP 运行时时用于输入量化。

概述

注: SNPE 支持多种量化模式。此处描述了量化的基础知识,无论模式如何。有关详细信息,请参阅量化模式。

  • 量化将浮点数据转换为 Tensorflow 风格的 8 位定点格式
  • 满足以下要求:
    • 涵盖了整个输入值范围。
    • 强制执行最小范围 0.01。
    • 浮点零是可以精确表示的。
  • 量化算法输入:
    • 要量化的浮点值集。
  • 量化算法输出:
    • 一组 8 位定点值。
    • 编码参数:
      • encoding-min - 可表示的最小浮点值(由固定点值 0)
      • encoding-max - 可表示的最大浮点值(由固定点值 255)
  • 算法
    • 计算输入数据的真实范围(最小值、最大值)。
    • 计算编码最小值和编码最大值。
    • 量化输入的浮点值。
    • 输出:
      • 定点值
      • encoding-min 和 encoding-max 参数

细节

  1. 计算输入浮点数据的真实范围。
    • 找到输入数据中的最小值和最大值
    • 表示输入数据的真实范围
  2. 计算编码最小值和编码最大值。
    • 这些参数用于量化步骤。
    • 这些参数定义了将由定点格式表示的范围和浮点值。
      • encoding-min:指定将由定点值 0 表示的最小浮点值
      • encoding-max:指定将由定点值 255 表示的最大浮点值
      • 每个步长的浮点值,其中步长 = (encoding-max - encoding-min) / 255,将是可表示的
      • encoding-min 和 encoding-max 首先设置为上一步计算的真实最小值和真实最大值
    • 第一个要求:编码范围必须至少为 0.01
      • encoding-max 调整为 max(true max, true min + 0.01)
    • 第二个要求:0 的浮点值必须可以精确表示
      • encoding-min 或 encoding-max 可以进一步调整
  3. 处理 0。
    • 案例 1:输入严格为正
      encoding-min 设置为 0.0
      零浮点值可以用最小定点值 0 精确表示
      例如输入范围 = [5.0, 10.0]
      编码最小值 = 0.0,编码最大值 = 10.0
    • 情况 2:输入严格为负
      • encoding-max 设置为 0.0
      • 零浮点值恰好可以用最大定点值 255 表示
      • 例如输入范围 = [-20.0, -6.0]
        • 编码最小值 = -20.0,编码最大值 = 0.0
    • 案例 3:输入同时为负和正
      • encoding-min 和 encoding-max 稍微移动以使浮点零可以精确表示
      • 例如输入范围 = [-5.1, 5.1]
        • encoding-min 和 encoding-max 首先分别设置为 -5.1 和 5.1
        • 编码范围为 10.2,步长为 10.2/255 = 0.04
          -零值目前不可表示。最接近的可表示值分别为 -0.02 和 +0.02,固定点值分别为 127 和 128
          -encoding-min 和 encoding-max 偏移 -0.02。新的编码最小值为 -5.12,新的编码最大值为 5.08
          -浮点零现在可以用定点值 128 精确表示
  4. 量化输入的浮点值。
    • 上一步中确定的 encoding-min 和 encoding-max 参数用于将所有输入浮点值量化为其定点表示
    • 量化公式为:
      • 量化值 = round(255 * (浮点值 - encoding.min) / (encoding.max - encoding.min))
    • 量化值也被限制在 0 到 255 之间
  5. 产出
    • 定点值
    • encoding-min 和 encoding-max 参数

量化示例

  • 输入:
    • 量化值 = [0, 89, 200, 255]
    • 编码最小值 = −1.803922,编码最大值 = 0.496078
  • 步长为 0.009020
  • 输出:
    • 反量化值 = [−1.8039, −1.0011, 0.0000, 0.4961]
      偏置位宽

SNPE 当前支持权重和偏差的默认量化位宽为 8。但是,可以通过从snpe-dlc-quantize指定命令行选项“–bias_bitwidth 32”来覆盖偏置位宽以使用 32 位量化。对于某些模型,使用 32 位偏差可能会略微提高准确性。不幸的是,很难预测哪些模型可以从中受益,因为模型架构、权重分布等都会对量化性能产生影响。

激活位宽

SNPE 还支持,量化位宽为 16 的激活。(见注释)

要启用 16 位定点推理,请将激活的量化位宽指定为 16,同时将权重的量化位宽保持为 8。将命令行选项:“–act_bitwidth 16 –weights_bitwidth 8”传递给 snpe-dlc-quantize,将生成量化模型文件具有 16 位激活和 8 位权重。

建议使用 UserBuffer TF16 作为输入/输出数据格式,以提高效率。在这种情况下,如果使用浮点数据,SNPE 的用户需要自己对输入/输出数据进行量化/反量化。使用snpe-net-run测试时,可以使用命令行选项“–userbuffer_tfN 16”来选择UserBuffer TF16模式。

ITensor 和 UserBuffer 浮点格式仍然可以与 16 位整数推理一起使用,但内部应用的量化效率较低。

量化模式

SNPE支持多种量化模式,区别在于如何选择量化参数。

默认量化模式

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

增强量化模式

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

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

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

调整权重量化模式

此模式仅用于将权重量化为 8 位定点(通过使用“use_adjusted_weights_quantizer”参数调用snpe-dlc-quantize),它使用被量化数据的调整后的最小值或最大值,而不是真正的最小值/最大值或最小值/max 排除长尾。这已被验证能够专门为降噪模型提供准确性优势。使用此量化器,如果需要,将扩展最大值或减小最小值。

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

增强的量化技术

由于无数的训练技术、模型架构和层类型,量化可能是一个难以解决的问题。为了减轻量化问题,已将两种新的模型预处理技术添加到snpe-dlc-quantize中,这可能会提高量化精度急剧下降的模型的量化性能。

引入的两种新技术是 CLE(跨层均衡)和 BC(偏置校正)。

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

BC 纠正了量化过程中在激活中引入的偏置误差。它通过累积来自浮点模型和量化模型的卷积/MatMul 激活数据来实现这一点,然后校正层输出的统计偏差。此校正被添加到所讨论层的偏差中。

增强的量化技术:局限性

在许多情况下,CLE+BC 可以使量化模型恢复到接近其原始浮点精度。当前算法有一些注意事项/限制:

  • CLE 对所有存在于单个分支中的特定操作模式进行操作(输出不能被多个操作使用)。匹配的操作模式(r=required, o=optional)是:
    • Conv®->Batchnorm®->activation(o)->Conv®->Batchnorm®->activation(o)
    • Conv®->Batchnorm®->activation(o)->DepthwiseConv®->Batchnorm®->activation(o)->Conv®->Batchnorm®->activation( o)
  • CLE 算法目前只支持 Relu 激活。任何 Relu6 激活都会自动更改为 Relu,除此之外的任何激活都会导致算法忽略前面的卷积。通常,从 Relu6->Relu 的切换是无害的,不会导致任何精度下降,但是某些模型可能会出现轻微的精度下降。在这种情况下,CLE+BC 只能将精度恢复到该降级级别,而不能恢复到原始浮点精度。
  • CLE 要求在转换为 DLC 之前原始模型中存在 batchnorm(特别是可检测的 batchnorm beta/gamma 数据),以便运行完整的算法并重新获得最大精度。对于 Tensorflow,有时即使使用折叠的 batchnorms 仍然可以找到 beta 和 gamma,只要折叠没有将参数折叠到卷积的静态权重和偏差中。如果它没有检测到所需的信息,您可能会看到一条类似以下内容的消息:“HBA 量化算法的模型无效。” 这表明该算法将仅部分运行并且可能存在准确性问题。

通常,CLE 和 BC 最好一起使用,因为它们相互补充。CLE 非常快(几秒),但是 BC 可能非常慢(几分钟到几小时),因为量化数据必须在进行校正时反复通过网络运行。当时间紧迫时,最好先尝试 CLE 并检查生成模型的准确性。如果精度很好(在浮点模型的几个 % 以内),那么 CLE+BC 应该在原始模型上运行并且可能会给出更好的结果。在精度仍然很差的情况下,BC 不太可能提供更多额外的精度增益。

要运行典型用例 CLE+BC,请将“–optimizations cle --optimizations bc”传递给snpe-dlc-quantize。

要仅运行 CLE,请将“–optimizations cle”传递给snpe-dlc-quantize。

应始终将原始转换后的浮点模型用作 snpe-dlc-quantize 的输入。不支持将量化模型传回量化器,这将导致未定义的行为。此外,BC 不应在没有 CLE 的情况下单独运行,因为它不会解决权重/激活量化的主要问题。

有关算法的更多信息,请访问: https 😕/arxiv.org/abs/1906.04721

量化影响

量化模型和/或在量化的运行时(如 DSP)中运行它会影响准确性。某些模型在量化时可能无法正常工作,并可能产生不正确的结果。衡量量化对分类模型影响的指标通常是“平均精度”、“前 1 错误”和“前 5 错误”。这些指标发布在各种模型的 SNPE 发行说明中。

混合精度和 FP16 支持

混合精度允许为同一图形中的不同操作指定不同的位宽(例如 8 位或 16 位)或数据类型(整数或浮点数)。当连续操作之间的激活精度或数据类型不同时,将自动插入数据类型转换操作。图形可以混合使用浮点和定点数据类型。每个操作可以有不同的权重和激活精度。但是,对于特定操作,所有输入、输出和参数(权重/偏差)都将是浮点数或全部都是定点格式。

量化覆盖

如果在模型转换期间提供了选项 –quantization_overrides,用户可以提供一个带有用于量化的参数的 json 文件。这些将与模型一起缓存,并可用于覆盖从转换中携带的任何量化数据(例如 TF 伪量化)或在 snpe-dlc-quantize 中的正常量化过程中计算。要在 snpe-dlc-quantize 期间覆盖参数,必须传递选项 –override_params,并且将使用缓存的值。json 格式是根据 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 “:[ 
          { 
              “位宽”:8,
              “最大”:0.9960872825108046,
              “最小”:-1.0039304197656937,
              “偏移量”:127,
              “比例”:0.007843206675594112 
          } 
      ] 
  },
  “param_encodings”:{ 
      “Conv2d/weights”:[
          { 
              “位宽”:8,
              “最大”:1.700559472933134,
              “最小”:-2.1006477158567995,
              “偏移量”:140,
              “比例”:0.01490669485799974 
          } 
      ] 
  } 
}

在“activation_encodings”下,名称(例如“Conv1:0”)表示应该覆盖量化的输出张量名称。在“param_encodings”下,名称代表将指定编码的权重或偏差。常用参数简述:

  • bitwidth (int, required) - 用于量化的位宽。请注意,这与模型将在其上运行的运行时的现有位宽支持非常匹配。
  • max (float, required) - 分布或期望范围内的最大数字。
  • min (float, required) - 分布或期望范围内的最小数字。
  • offset (int) - 指示零点的整数偏移量(即精确表示 0 的点)
  • scale (float) - 表示整数大小除以所需分布范围的值

请注意,不需要提供比例(也称为增量)和偏移量(零点)。如果提供了它们,将使用它们,否则将根据提供的位宽、最小值和最大值参数计算它们。

注意:- 用于激活的量化位宽 16,在某些运行时从 Snapdragon 865/765 开始支持,目前并非对所有操作都启用。

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

  • 无覆盖:如果编码文件没有给出 –quantization_overrides 标志,则所有激活都按照 –act_bitwidth(默认 8)量化,参数分别按照 –weight_bitwidth/–bias_bitwidth(默认 8/8)量化。

  • 完全覆盖:如果给出了–quantization_overrides 标志以及指定模型中所有操作的编码的编码文件。在这种情况下,对于根据编码文件定义为整数的所有操作(编码 json 中的 dtype=‘int’),位宽将根据 JSON 设置。如果在命令行上给出 –float_bitwidth 16,则在编码文件 (dtype=‘float’) 中定义为 float 的操作将被标记为激活和权重的 FP16。否则它们将被标记为 FP32。即对于在 encodings json 中标记为 float 的操作,encodings json 中的位宽将被忽略,并根据 –float_bitwidth 标志设置为 16 位或 32 位。

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

    • json 文件中编码不可用的层的编码方式与无覆盖情况相同,即定义为整数,位宽定义为每 –act_bitwidth/–weight_bitwidth/– bias_bitwidth(或其默认值 8/8/8)。

    • 在 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”:[ 
               { 
                   “位宽”: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": "浮动" 
               } 
           ],
           “conv2_b_0”:[ 
               { 
                   “bitwidth”:32,
                   “dtype”:“float} 
           ],
           “conv3_w_0”:[ 
               { 
                   “bitwidth”:8,
                   “dtype”:“int} 
           ],
           “conv3_b_0”:[ 
               { 
                   “位宽”:8,
                   “dtype”:“int} 
           ] 
    } 
       }

json 中不存在的操作将被假定为定点,位宽将分别根据 –act_bitwidth/–weight_bitwidth/–bias_bitwidth 选择。注意:目前,编码 json 中指定的浮点位宽被忽略,量化器使用使用 –float_bitwidth 转换器选项指定的位宽。

 { 
       "activation_encodings": { 
           "conv2_1": [ 
               { 
                   "bitwidth": 32, 
                   "dtype": "float" 
               } 
           ] 
       }, 
       "param_encodings": { 
           "conv2_w_0": [ 
               { 
                   "bitwidth": 32, 
                   "dtype": “浮动” 
               } 
           ],
           “conv2_b_0”:[ 
               { 
                   “位宽”:32,
                   “dtype”:“浮动”
               } 
           ] 
       } 
    }

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

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值