训练后量化是一种转换技术,它可以缩减模型大小,同时降低 CPU 和硬件加速器的延迟时间,但不会降低模型准确度。使用 LiteRT 转换器将已训练的浮点型 TensorFlow 模型转换为 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 位,并使用 8 位权重和激活值执行计算。此优化可提供接近完全定点推理的延迟时间。不过,输出仍以浮点格式存储,因此动态范围操作的提速不如完整的定点计算。
完全整数量化
通过确保所有模型数学运算都经过整数量化,您可以进一步缩短延迟时间、减少峰值内存用量,并与纯整数硬件设备或加速器兼容。
对于全整数量化,您需要校准或估计范围,即模型中所有浮点张量的(最小值、最大值)。与权重和偏差等常量张量不同,模型输入、激活(中间层的输出)和模型输出等变量张量无法进行校准,除非我们运行几个推理周期。因此,转换器需要一个具有代表性的数据集来校准它们。此数据集可以是训练或验证数据的一小部分子集(大约 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()
仅限整数
创建仅包含整数的模型是 LiteRT for Microcontrollers 和 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(IEEE 16 位浮点数标准)来减小浮点模型的规模。如需启用 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 量化的优势如下:
- 它可以将模型大小缩减一半(因为所有权重都变为原来的一半)。
- 这会导致准确率略有下降。
- 它支持一些可直接对 float16 数据进行操作的委托(例如 GPU 委托),从而实现比 float32 计算更快的执行速度。
float16 量化的缺点如下:
- 与量化为定点数学相比,它减少的延迟时间并不多。
- 默认情况下,float16 量化模型在 CPU 上运行时会将权重值“反量化”为 float32。(请注意,GPU 委托不会执行此反量化,因为它可处理 float16 数据。)
仅限整数:16 位激活函数,8 位权重(实验性)
这是一种实验性量化方案。它与“仅限整数”方案类似,但激活函数根据其范围量化为 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。
这种量化的缺点是:
- 目前,由于缺少优化的内核实现,推理速度明显慢于 8 位全整数。
- 目前,它与现有的硬件加速 TFLite 委托不兼容。
如需查看此量化模式的教程,请点击此处。
模型准确率
由于权重是在训练后量化的,因此可能会出现准确率损失,尤其是对于较小的网络。Kaggle Models 上提供了针对特定网络的预训练全量化模型。请务必检查量化模型的准确性,以验证准确性的任何下降是否在可接受的范围内。您可以使用相关工具来评估 LiteRT 模型的准确性。
或者,如果准确率下降幅度过大,请考虑使用量化感知训练。不过,这样做需要在模型训练期间进行修改以添加伪量化节点,而本页上的训练后量化技术则使用现有的预训练模型。
量化张量的表示形式
8 位量化使用以下公式来近似浮点值。
\[real\_value = (int8\_value - zero\_point) \times scale\]
该表示法包含两个主要部分:
每个轴(也称为每个通道)或每个张量的权重,以 int8 二进制补码值表示,范围为 [-127, 127],零点等于 0。
每个张量的激活/输入由范围为 [-128, 127] 的 int8 二进制补码值表示,零点范围为 [-128, 127]。
如需详细了解我们的量化方案,请参阅我们的量化规范。我们建议希望接入 TensorFlow Lite 委托接口的硬件供应商实现其中描述的量化方案。