训练后量化

训练后量化是一种可减小模型大小的转换技术 同时缩短 CPU 和硬件加速器的延迟时间, 模型准确率降低。你可以量化已经过训练的浮点数 使用 LiteRT 转换器

优化方法

有多个训练后量化选项可供选择。这里有一个 各种选择及其优势的摘要表:

分析法 优势 硬件
动态范围 量化 更小 4 倍,速度提升 2-3 倍 CPU 用量
完整整数 量化 小 4 倍,速度提升 3 倍以上 CPU、Edge TPU、 微控制器
Float16 量化 2 倍小,GPU 加速 CPU、GPU

下面的决策树可以帮助确定哪种训练后量化 方法最适合您的用例:

训练后优化选项

不量化

建议你先在没有量化的情况下转换为 TFLite 模型 。这将生成一个浮动 TFLite 模型。

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
tflite_quant_model = converter.convert()

我们建议您首先执行此操作, TF 模型的运算符与 TFLite 兼容,也可以用作 用于调试后续训练后引入的量化误差的基准 量化方法。例如,如果量化 TFLite 模型 虽然浮动 TFLite 模型非常准确,但是我们可以缩小 量化版本的 TFLite 运算符所导致的错误问题。

动态范围量化

动态范围量化可减少内存使用量并加快计算速度 而无需提供代表性数据集来进行校准。这个 量化类型,仅静态量化浮点的权重 转换为整数,其可提供 8 位的精度:

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
tflite_quant_model = converter.convert()

为了进一步缩短推理过程中的延迟时间,“动态范围”运算符 根据激活数到 8 位的范围动态量化激活函数,并执行 计算。这项优化功能 接近完全定点推理的延迟时间。不过,输出仍然 使用浮点数存储,因此动态范围运算的加速速度 比完全定点数计算更复杂。

全整数量化

您可以进一步缩短延迟时间、减少峰值内存用量,以及 兼容纯整数硬件设备或加速器 所有模型数学内容都是整数量化。

对于全整数量化,您需要校准或估算范围, 即(min, max)。不同于常量 张量(例如权重和偏差),以及变量张量(例如模型输入), 激活(中间层的输出)和模型输出, 除非我们运行几次推理周期,否则将得到校准。因此,转换器 需要一个代表性数据集来进行校准。此数据集可能规模较小, 训练数据或验证数据的子集(大约 100-500 个样本)。请参阅 representative_dataset() 函数。

从 TensorFlow 2.7 版本开始,您可以通过 签名,如下例所示:

def representative_dataset():
  for data in dataset:
    yield {
      "image": data.image,
      "bias": data.bias,
    }

如果给定 TensorFlow 模型中有多个签名,您可以 通过指定签名密钥来指定多个数据集:

def representative_dataset():
  # Feed data set for the "encode" signature.
  for data in encode_signature_dataset:
    yield (
      "encode", {
        "image": data.image,
        "bias": data.bias,
      }
    )

  # Feed data set for the "decode" signature.
  for data in decode_signature_dataset:
    yield (
      "decode", {
        "image": data.image,
        "hint": data.hint,
      },
    )

您可以通过提供输入张量列表来生成代表性数据集:

def representative_dataset():
  for data in tf.data.Dataset.from_tensor_slices((images)).batch(1).take(100):
    yield [tf.dtypes.cast(data, tf.float32)]

从 TensorFlow 2.7 版本开始,我们建议使用基于签名的方法 因为输入张量排序可以 以便轻松翻转

出于测试目的,您可以使用虚拟数据集,如下所示:

def representative_dataset():
    for _ in range(100):
      data = np.random.rand(1, 244, 244, 3)
      yield [data.astype(np.float32)]
 

具有浮点回退的整数(使用默认的浮点输入/输出)

为了对模型进行完全整数量化,但在使用浮点数运算符时, 未采用整数实现方式(以确保转化顺利进行),请使用 执行下列步骤:

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.representative_dataset = representative_dataset
tflite_quant_model = converter.convert()

仅限整数

创建纯整数模型是 微控制器Coral Edge TPU

此外,为了确保与纯整数设备(例如 8 位)兼容, 微控制器)和加速器(例如 Coral Edge TPU)的应用,则可以强制执行 对所有操作(包括输入和输出)进行全整数量化,方法是使用 执行下列步骤:

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.representative_dataset = representative_dataset
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.int8  # or tf.uint8
converter.inference_output_type = tf.int8  # or tf.uint8
tflite_quant_model = converter.convert()

Float16 量化

您可以通过将权重量化到 float16,16 位浮点数的 IEEE 标准。启用 float16 权重量化,请按以下步骤操作:

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_types = [tf.float16]
tflite_quant_model = converter.convert()

float16 量化的优点如下:

  • 它可以将模型大小减少至原来的一半(因为所有权重都变成了 原始大小)。
  • 它可以最大限度降低准确率损失。
  • 它支持一些可以运行的代理(例如 GPU 委托), 直接基于 float16 数据,因此执行速度比 float32 快 计算。

float16 量化的缺点如下:

  • 延迟时间的减少幅度不及量化到定点数数学。
  • 默认情况下,float16 量化模型会“去量化”权重值 在 CPU 上运行时将其转换为 float32(请注意,GPU 代理不会执行 因为它可以处理 float16 数据。)

仅限整数:具有 8 位权重的 16 位激活(实验性)

这是一个实验性的量化方案。类似于“仅整数” 方案,但激活函数根据其范围到 16 位、权重进行量化 将量化为 8 位整数,而偏差会量化为 64 位整数。这个 称为 16x8 量化。

这种量化的主要优势在于,它可以提高准确性 但只会稍微增加模型大小。

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.representative_dataset = representative_dataset
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8]
tflite_quant_model = converter.convert()

如果模型中的某些运算符不支持 16x8 量化,则 模型仍然可以量化,但不受支持的运算符将保持浮点数。通过 为此,您应将以下选项添加到 target_spec。

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.representative_dataset = representative_dataset
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8,
tf.lite.OpsSet.TFLITE_BUILTINS]
tflite_quant_model = converter.convert()

通过此功能提高准确性的用例示例 量化方案包括:

  • 超分辨率,
  • 音频信号处理,例如降噪和波束成形;
  • 图像去噪、
  • 根据单张图片进行 HDR 重构。

这种量化的缺点是:

  • 由于 缺少经过优化的内核实现。
  • 目前,它与现有硬件加速 TFLite 不兼容 党代表票

您可以在以下位置找到关于此量化模式的教程: 此处

模型准确率

由于权重在训练后量化,因此准确性可能会降低, 尤其是对于小型广告联盟预训练的完全量化模型 Kaggle 上的特定广告网络提供 模型 ,了解所有最新动态。请务必检查量化模型的准确度, 准确度的任何降低情况在可接受的限制范围内。其中的工具 评估 LiteRT 模型 准确率

或者,如果准确度下降太高,不妨考虑使用量化 知道 训练 ,了解所有最新动态。但是,这样做需要在模型训练期间进行修改,以添加虚假情况 量化节点的训练后量化技术, 使用现有的预训练模型。

量化张量的表示法

8 位量化使用以下函数近似计算浮点值 公式。

\[real\_value = (int8\_value - zero\_point) \times scale\]

该表示法包含两个主要部分:

  • 每个轴(也称为每个通道)或每个张量权重,以 int8 two 值 补全 [-127, 127] 范围内的值,零点等于 0。

  • 每个张量激活/输入以 int8 2 的补码值表示, 范围为 [-128, 127],零点的范围为 [-128, 127]。

有关量化方案的详细内容,请参阅我们的量化方案 规范。希望接入 TensorFlow 的硬件供应商 建议使用 Lite 的委托接口实现量化方案 。