google-ai-edge/ai-edge-quantizer

GitHub: google-ai-edge/ai-edge-quantizer

一款灵活的训练后量化工具,旨在帮助开发者在边缘设备上优化和部署 LiteRT 模型。

Stars: 182 | Forks: 33

# AI Edge Quantizer 一款面向高级开发者的量化工具,用于量化已转换的 LiteRT 模型。它 旨在帮助高级用户在资源 密集型模型(例如 GenAI 模型)上追求最佳性能。 ## 构建状态 构建类型 | 状态 | ----------- | --------------| 单元测试 | [![Unit Tests Status Badge](https://github.com/google-ai-edge/ai-edge-quantizer/actions/workflows/nightly_unittests.yml/badge.svg?branch=main)](https://github.com/google-ai-edge/ai-edge-quantizer/actions/workflows/nightly_unittests.yml) | 每日发布版 | [![Nightly Release Status Badge](https://github.com/google-ai-edge/ai-edge-quantizer/actions/workflows/nightly_release.yml/badge.svg?branch=main)](https://github.com/google-ai-edge/ai-edge-quantizer/actions/workflows/nightly_release.yml) | 每日 Colab | [![Nightly Colab Status Badge](https://github.com/google-ai-edge/ai-edge-quantizer/actions/workflows/nightly_colabs.yml/badge.svg?branch=main)](https://github.com/google-ai-edge/ai-edge-quantizer/actions/workflows/nightly_colabs.yml) | ## 安装 ### 环境要求与依赖 * Python 版本:3.10, 3.11, 3.12, 3.13 * 操作系统:Linux, MacOS * TensorFlow: [![tf-nightly](https://img.shields.io/badge/tf--nightly-latest-blue)](https://pypi.org/project/tf-nightly/) ### 安装 Nightly PyPi 包: ``` pip install ai-edge-quantizer-nightly ``` ## API 用法 量化器需要两个输入: 1. 未量化的源 LiteRT 模型(FlatBuffer 格式,FP32 数据类型,扩展名为 `.tflite`) 2. 量化配置(详见下文) 并输出一个准备好部署在边缘设备上的量化 LiteRT 模型。 ### 基本用法 简而言之,量化器按以下步骤运行: 1. 实例化 `Quantizer` 类。这是用户访问量化器 功能的入口点。 2. 加载所需的量化配置(详见小节)。 3. 量化(并保存)模型。量化器的 大部分内部逻辑都在此阶段运行。 ``` from ai_edge_quantizer import quantizer, recipe qt = quantizer.Quantizer("path/to/input/tflite") # 加载一个开箱即用的 recipe(例如 dynamic int8 quantization)。 qt.load_quantization_recipe(recipe.dynamic_wi8_afp32()) qt.quantize().export_model("/path/to/output/tflite") ``` 请参阅[入门 Colab](colabs/getting_started.ipynb) 获取这 3 个步骤最简单的快速入门指南,以及[选择性量化 Colab](colabs/selective_quantization_isnet.ipynb) 了解有关高级功能的更多细节。 #### LiteRT 模型 请参阅 [LiteRT 文档](https://ai.google.dev/edge/litert) 了解如何从 Jax、PyTorch 和 TensorFlow 生成 LiteRT 模型。输入的源模型应为 FlatBuffer 格式、扩展名为 `.tflite` 的 FP32(未量化)模型。 #### 量化配置 用户需要使用 AI Edge Quantizer 的 API 指定一个量化配置,以 应用到源模型上。量化配置编码了关于 如何量化模型的所有信息,例如位数、数据类型、对称性、 scope 名称等。 从本质上讲,量化配置定义为以下类型的命令集合: _“在 **Scope Z** 下,使用 **ConfigN** 对 **Operator Y** 应用 **量化算法 X**。”_ 例如: _\"使用 **INT8 对称与动态量化**,对 scope **'dense1/'** 下的 **FullyConnected op** 进行**均匀量化**。”_ 所有未指定的 op 将保持为 FP32(未量化)。在 TFLite 中,operator 的 scope 被定义为该 op 的输出 tensor 名称,这保留了来自源模型(例如 TF 中的 scope)的分层模型信息。获取 scope 名称的最佳方法是使用 [Model Explorer](https://ai.google.dev/edge/model-explorer) 可视化模型。 目前,量化一个 operator 有三种方法: * **动态量化(推荐)**:对权重进行量化,而 activation 保持浮点格式,且不经过 AI Edge Quantizer (AEQ) 处理。Runtime kernel 负责处理这些 activation 的即时量化,这由 `compute_precision=integer` 和 `explicit_dequantize=False` 来标识。 * 优点:减少了模型大小和内存使用。由于 整数计算而提升了延迟。不需要样本数据(校准)。 * 缺点:activation tensor 的即时量化可能会影响模型 质量。并非所有硬件都支持(例如,某些 GPU 和 NPU)。 * **仅权重量化**:仅量化模型权重,而不量化 activation。实际的操作 (op) 计算仍保持浮点格式。 量化后的权重在被输入到 op 之前,会通过 在量化权重和消耗它的 op 之间插入一个 dequantize op 来进行显式反量化。 要启用此功能,需将 `compute_precision` 设置为 `float`,并将 `explicit_dequantize` 设置为 `True`。 * 优点:减少了模型大小和内存使用。不需要样本数据 (校准)。通常具有最佳的模型质量。 * 缺点:由于进行带有 显式反量化的浮点计算,因此没有延迟收益(甚至可能更差)。 * **静态量化**:权重和 activation 均被量化。这 需要一个校准阶段来估算 runtime tensor (activation) 的量化参数。 * 优点:减少了模型大小、内存使用和延迟。 * 缺点:需要样本数据进行校准。将静态量化 参数(源自校准)施加于 runtime tensor 可能会损害 质量。 通常,我们建议在 CPU/GPU 部署时使用动态量化,在 NPU 部署时使用静态 量化。 我们在 [recipe.py](ai_edge_quantizer/recipe.py) 中包含了常用的配置。这在 [入门 Colab](colabs/getting_started.ipynb) 示例中进行了演示。高级用户可以通过量化器 API 构建自己的配置。 #### 模型验证与准确性基准测试 量化模型不可避免地会引入数值噪声。在调用 `qt.quantize()` 之后,您可以使用内置的 `validate()` 方法验证浮点 基线与量化模型之间的数学失真,该 方法会返回一个单一的 `ComparisonResult` 对象,将节点映射到其误差指标 值。您可以将它们打印出来,或者自动保存为 Model Explorer JSON 文件: ``` # 1. 默认 validation(默认评估 MSE metric) comparison_results = qt.validate(test_data=sample_data) print( "Per-layer metrics:", comparison_results.get_all_tensor_results(), ) # 2. 多 metric validation(直接保存所有 metrics 和 validation json 数据) comparison_results = qt.validate( test_data=sample_data, error_metrics=[ quantizer.ValidationErrorMetric.MSE, quantizer.ValidationErrorMetric.SNR, ], save_folder='/tmp/' ) all_results = comparison_results.get_all_tensor_results() for tensor_name, metrics in all_results.items(): print( f"Tensor: {tensor_name} " f"- MSE: {metrics.get(quantizer.ValidationErrorMetric.MSE.value, 0.0):.6f} " f"- SNR: {metrics.get(quantizer.ValidationErrorMetric.SNR.value, 0.0):.6f}" ) ``` 更详细的示例可以在 [quantize_toy_model.py](ai_edge_quantizer/examples/mnist/quantize_toy_model.py) 中找到。 #### 使用 Model Explorer 可视化模型 获取确切的 operator scope 名称,并在视觉上比较基线浮点和量化图之间的 tensor 形状和量化缩放比例的最佳方法是使用 [Model Explorer](https://ai.google.dev/edge/model-explorer)。 要在终端中并排可视化两个导出的 `.tflite` 模型,请运行: ``` model_explorer --models \ "/path/to/baseline_float.tflite,/path/to/quantized_model.tflite" ``` #### 部署 请参阅 [LiteRT 部署文档](https://ai.google.dev/edge/litert/inference) 了解部署量化 LiteRT 模型的方法。 ### 高级配置 除了使用 [recipe.py](ai_edge_quantizer/recipe.py) 中的模板外,用户还可以通过多种方式配置和自定义量化配置。例如,用户可以配置配方以实现以下功能: * 选择性量化(将选定的 op 排除在量化之外) * 灵活的混合方案量化(混合不同的 precision、计算 precision、scope、op、config 等) * 4-bit 权重量化 [选择性量化 Colab](colabs/selective_quantization_isnet.ipynb) 展示了其中一些更高级的功能。 有关配置 schema 的详细信息,请参阅 [recipe_manager.py] 中的 `OpQuantizationRecipe`。 对于涉及混合量化的高级用法,以下 API 可能会 有用: * 使用 [quantizer.py](ai_edge_quantizer/quantizer.py) 中的 `Quantizer:load_quantization_recipe()` 来加载自定义配置。 * 使用 [quantizer.py](ai_edge_quantizer/quantizer.py) 中的 `Quantizer:update_quantization_recipe()` 来扩展或覆盖 配置的特定部分。 ### Operator 覆盖范围 下表概述了可用配置允许的设置。 | | | | | | | | | | | | --- | --- | --- | --- | --- | --- |--- |--- |--- |--- | | **配置** | | DYNAMIC_WI8_AFP32 | DYNAMIC_WI4_AFP32 | STATIC_WI8_AI16 | STATIC_WI4_AI16 | STATIC_WI8_AI8 | STATIC_WI4_AI8 | WEIGHTONLY_WI8_AFP32 | WEIGHTONLY_WI4_AFP32 | |activation| num\_bits | None | None | 16 | 16 | 8 | 8 | None | None | | | symmetric |None | None | TRUE | TRUE | [TRUE, FALSE] | [TRUE, FALSE] | None | None | | | granularity |None | None | TENSORWISE | TENSORWISE | TENSORWISE | TENSORWISE | None | None | | | dtype| None | None |INT | INT | INT | INT | None | None | | weight | num\_bits | 8 | 4 | 8 | 4 | 8 | 4 | 8 | 4 | | | symmetric | TRUE | TRUE | TRUE | TRUE | TRUE | TRUE | [TRUE, FALSE] | [TRUE, FALSE] | | | granularity | \[CHANNELWISE, TENSORWISE\] | \[CHANNELWISE, TENSORWISE\] | \[CHANNELWISE, TENSORWISE\] | \[CHANNELWISE, TENSORWISE\] | \[CHANNELWISE, TENSORWISE\] | \[CHANNELWISE, TENSORWISE\] | \[CHANNELWISE, TENSORWISE\] | \[CHANNELWISE, TENSORWISE\] | | | dtype | INT | INT | INT | INT | INT | INT | INT | INT | | explicit\_dequantize | | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | TRUE | | compute\_precision || INTEGER | INTEGER | INTEGER | INTEGER | INTEGER | INTEGER | FLOAT | FLOAT | **支持量化的 Operator** | | | | | | | | | | | --- | --- | --- | --- | --- | --- |--- |--- |--- | | **配置** | DYNAMIC_WI8_AFP32 | DYNAMIC_WI4_AFP32 | STATIC_WI8_AI16 | STATIC_WI4_AI16 | STATIC_WI8_AI8 | STATIC_WI4_AI8 | WEIGHTONLY_WI8_AFP32 | WEIGHTONLY_WI4_AFP32 | |FULLY_CONNECTED |
|
|
|
|
|
|
|
| |CONV_2D |
| |
|
|
|
|
| | |BATCH_MATMUL |
| |
| |
| |
| | |EMBEDDING_LOOKUP |
|
|
| |
|
|
| | |DEPTHWISE_CONV_2D|
| |
| |
| |
| | |AVERAGE_POOL_2D | | |
| |
| | | | |RESHAPE | | |
| |
| | | | |SOFTMAX | | |
| |
| | | | |TANH | | |
| |
| | | | |TRANSPOSE | | |
| |
| | | | |GELU | | |
| |
| | | | |ADD | | |
| |
| | | | |CONV_2D_TRANSPOSE|
| |
| |
| | | | |SUB | | |
| |
| | | | |MUL | | |
| |
| | | | |MEAN | | |
| |
| | | | |RSQRT | | |
| |
| | | | |CONCATENATION | | |
| |
| | | | |STRIDED_SLICE | | |
| |
| | | | |SPLIT | | |
| |
| | | | |LOGISTIC | | |
| |
| | | | |SLICE | | |
| |
| | | | |SELECT | | |
| |
| | | | |SELECT_V2 | | |
| |
| | | | |SUM | | |
| |
| | | | |PAD | | |
| |
| | | | |PADV2 | | |
| |
| | | | |MIRROR_PAD | | |
| |
| | | | |SQUARED_DIFFERENCE | | | | |
| | | | |MAX_POOL_2D | | |
| |
| | | | |RESIZE_BILINEAR | | |
| |
| | | | |RESIZE_NEAREST_NEIGHBOR| | |
| |
| | | | |GATHER_ND | | |
| |
| | | | |PACK | | |
| |
| | | | |UNPACK | | |
| |
| | | | |DIV | | |
| |
| | | | |SQRT | | |
| |
| | | | |GATHER | | |
| |
| | | | |HARD_SWISH | | | | |
| | | | |MAXIMUM | | |
| |
| | | | |REDUCE_MIN | | |
| |
| | | | |EQUAL | | |
| |
| | | | |NOT_EQUAL | | |
| |
| | | | |SPACE_TO_DEPTH | | | | |
| | | | |RELU | | |
| |
| | | |
标签:LiteRT, TensorFlow, 人工智能, 模型优化, 模型量化, 用户模式Hook绕过, 端侧部署, 边缘计算, 逆向工具