训练后量化是一种可减小模型大小的转换技术 同时缩短 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 的委托接口实现量化方案 。