[项目复盘报告 V5.0] 嵌入式平台 (RV1126B) 流式 ASR 模型 (Zipformer) INT8 端到端量化与部署
| 项目属性 | 内容 |
|---|---|
| 项目名称 | 第五部分:RV1126BP平台 Sherpa ASR RKNN量化 |
| 项目周期 | 2025-08-21 ~ 2025-09-23 |
| 项目用时 | 40(约5人天) |
| 复盘日期 | 2025-09-27 |
| 核心人员 | Potter White |
1. 项目目标 (Project Objective)
为基于 Rockchip RV1126B SoC 的嵌入式设备,将一个 FP32 精度的流式 Zipformer ASR (Automatic Speech Recognition) ONNX 模型,转换为 INT8 精度的 RKNN 模型,并在 sherpa-onnx C++ 推理框架中完成部署与验证,以满足低延迟和低功耗的运行要求。
2. 执行方法与流程 (Methodology & Workflow)
本项目采用了一套系统性的方法,覆盖从模型分析、运行时环境改造、量化数据生成到最终模型验证的全过程。
graph TD
classDef main fill:#2c3e50,color:white,stroke:#8e9eab;
classDef task fill:#4b3e58,color:white,stroke:#b8a3d3;
classDef check fill:#27ae60,color:white,stroke:#88d1a1;
classDef fail fill:#c0392b,color:white,stroke:#e69a93;
classDef success fill:#16a085,color:white,stroke:#72d6c1;
classDef note fill:#f39c12,color:white,stroke:#f8c471;
S[<b>开始: FP32 ONNX 模型</b>]:::main
A["<div style='text-align:left; padding:10px;'><b>1. 初始模型分析与转换</b><br>- 使用预量化的 INT8 ONNX 模型进行直接转换</div>"]:::task
%% --- THIS IS THE MISSING LINE THAT FIXES THE CONNECTION ---
S --> A
A --> R1{"<div style='text-align:center'>转换是否成功?</div>"}:::check
R1 -- "否: 存在 `DynamicQuantizeLinear` 算子" --> B
B["<div style='text-align:left; padding:10px;'><b>2. C++ 运行时适配</b><br>- 分析 `sherpa-onnx` RKNN 后端代码<br>- 增加对 `RKNN_TENSOR_INT8` 类型的处理分支<br>- 实现 INT8 输出到 FP32 的手动反量化逻辑</div>"]:::task
B --> C
C["<div style='text-align:left; padding:10px;'><b>3. 校准数据集迭代</b><br><b>3.1 (快照法):</b> 提取特征帧, 状态张量补零<br><b>3.2 (流式模拟):</b> 使用 `onnxruntime` 模拟流式推理, 捕获真实的非零状态张量</div>"]:::task
C --> R2{"<div style='text-align:center'>INT8 模型推理结果?</div>"}:::check
R2 -- "3.1 -> Garbled Output" --> C
R2 -- "3.2 (`interval=1`) -> <b>First Success</b>" --> D
D["<div style='text-align:left; padding:10px;'><b>4. 量化策略调优</b><br>- <b>算法:</b> 测试 `normal` (默认) 与 `kl_divergence` 算法<br>- <b>混合精度:</b> 尝试手动及自动混合量化</div>"]:::task
D --> E
E["<div style='text-align:left; padding:10px;'><b>5. 最终方案验证</b><br>- 对比不同策略下的模型精度与性能 (RTF)</div>"]:::task
E --> F[<b>完成: 产出可部署的 INT8 RKNN 模型</b>]:::success
subgraph "关键技术点"
K1[静态图 vs. 动态图]:::note
K2[有状态模型的校准]:::note
K3[量化算法内存分析]:::note
K4[混合精度量化]:::note
end
A --> K1
C --> K2
D --> K3 & K43. 工程实施细节与关键问题记录 (Implementation & Key Findings)
3.1 初始模型转换
- 执行动作: 尝试使用
rknn-toolkit2直接转换模型提供方发布的int8.onnx模型。 - 观察结果: 转换失败。工具链报错,指出模型中包含
DynamicQuantizeLinear算子,该算子与 RKNN NPU 的静态图 (Static Graph) 计算模式不兼容。 - 采取措施: 确定了必须使用
FP32ONNX 模型作为输入源,并利用rknn-toolkit2自身的静态量化 (Static Quantization) 功能进行转换。
3.2 C++ 推理框架 (sherpa-onnx) 适配
- 执行动作: 在使用
FP32模型成功转换为INT8RKNN 模型后,在sherpa-onnx中进行推理。 - 观察结果: 运行时报错,提示
Unsupported tensor type: 2, INT8。 - 采取措施:
- 修改了
sherpa-onnx的 RKNN 后端 C++ 源码,在模型输入、输出及状态 (states) 处理逻辑中,增加了对RKNN_TENSOR_INT8数据类型的分支处理。 - 在获取模型输出后,根据
rknn_tensor_attr中的scale和zp(zero_point) 参数,实现了手动的反量化 (Dequantization) 步骤,将INT8输出转换为后续解码逻辑所需的FP32数据。
- 修改了
3.3 量化校准数据集的迭代与优化
此阶段是项目核心,通过多次迭代确定了有效的校准数据生成方案。
迭代 1: 快照式数据集 (Snapshot Dataset)
- 方法: 从音频中提取多个特征帧 (
x) 作为校准样本,所有状态输入 (cached_*tensors) 均使用全零张量填充。 - 结果: 生成的
INT8模型在推理时输出乱码或静默。
- 方法: 从音频中提取多个特征帧 (
迭代 2: 精确特征提取 + 快照式数据集
- 方法: 深入分析
sherpa-onnx的 C++ 源码 (features.h),在 Python 数据生成脚本中精确复现了其音频预处理流程,包括去直流偏置 (Remove DC Offset) 和预加重 (Pre-emphasis)。状态输入仍使用全零张量。 - 结果: 推理结果没有改善,证明状态张量的真实性是更关键的因素。
- 方法: 深入分析
迭代 3: 模拟流式数据集 (Simulated Streaming Dataset)
- 方法: 编写 Python 脚本,使用
onnxruntime完整模拟sherpa-onnx的流式推理过程。在每个时间步 (time step),将真实的特征帧 (x) 和由上一步onnxruntime计算出的真实非零状态 (cached_*) 作为一组完整的校准样本保存下来。 - 结果:
- 使用此方法生成的完整数据集 (
sampling_interval=1) 进行量化后,模型首次成功输出完整、可读的识别结果,RTF (Real-Time Factor, 实时率) 约为 0.29。 - 数据集体积巨大 (超过 100GB),导致转换时间长达数小时。
- 使用此方法生成的完整数据集 (
- 方法: 编写 Python 脚本,使用
3.4 量化策略的进一步探索
基于第 3.3 节成功的 interval=1 数据集,进行了以下策略调优:
量化算法:
normal(默认): 成功生成模型,结果如 3.3 所述。kl_divergence: 在转换过程中,因内存消耗过大导致系统内存溢出 (Out of Memory, OOM) 而失败。分析表明,该算法需要一次性加载大量样本进行统计计算,与大规模数据集不兼容。
数据采样方法:
- 系统采样 (
sampling_interval > 1) / 随机采样: 尝试通过采样减少数据集体积,以配合kl_divergence算法。 - 结果: 虽然转换可以成功,但生成的模型推理结果重新变为乱码。这表明 Zipformer 模型对校准数据中状态的时间连续性 (Temporal Continuity) 高度敏感。
- 系统采样 (
混合精度量化 (Mixed-Precision Quantization):
- 方法: 尝试使用
rknn-toolkit2的手动及自动混合量化功能,将Softmax等对精度敏感的算子保留为FP16。 - 结果: 手动混合未能显著改善精度,并引入了新的识别错误。自动混合生成的模型在运行时报错或输出乱码。
- 方法: 尝试使用
4. 项目成果与结论 (Results & Conclusion)
最终交付成果:
- 一个可在 RV1126B 平台上稳定运行的
INT8RKNN ASR 模型,RTF 达到 0.29,实现了从FP32到INT8的成功部署。 - 一套经过验证的、针对流式有状态 (stateful) 模型的校准数据集生成脚本 (
09_generate_calibration_dataset.py),该脚本通过模拟流式推理来保证状态张量的真实性和连续性。
- 一个可在 RV1126B 平台上稳定运行的
工程结论:
- 对于此 Zipformer 模型,校准数据的状态真实性与时间连续性是量化成功的决定性因素,其重要性高于特征提取的微小差异。
rknn-toolkit2的kl_divergence等统计型量化算法,在处理大规模、高维度的连续数据集时存在内存限制。- 在当前工具链和模型架构下,使用完整的流式模拟数据集配合
normal量化算法,是在各项约束(精度、性能、转换可行性)之间取得的最佳工程方案。