基于 sherpa-onnx 的 K2 Transducer + Zipformer 中文普通话流式语音识别模型(ONNX),已完成昇腾 Ascend NPU 适配与精度验证。
| 项目 | 版本/型号 |
|---|---|
| NPU 型号 | Ascend910_9362 × 2 |
| CANN 版本 | 8.5.1 |
| torch_npu | 2.9.0.post1 |
| ONNX Runtime | 1.24.4 (CANNExecutionProvider) |
| Python | 3.11.14 |
| OS | Linux 5.10.0 (aarch64) |
采用混合执行策略,将不同模块分配至最优后端:
| 模块 | 后端 | 说明 |
|---|---|---|
| 特征提取 (log-mel) | CPU | scipy/librosa 实现,无 NPU 算子 |
| Encoder (Zipformer) | CPU | 模型较大 (249MB),CANN EP 图编译暂不支持大模型 |
| Decoder | CANN NPU | 小模型 (5MB),NPU 正确执行 |
| Joiner | CANN NPU | 核心计算路径 (4MB),NPU 加速 |
说明: Encoder 当前在 CPU 执行。待 CANN EP 对大模型图编译的支持完善后,可将 Encoder 迁移至 NPU 以获取更大加速比。
| 测试音频 | 时长 | NPU 结果 | CPU 结果 | 匹配 | NPU 耗时 | CPU 耗时 |
|---|---|---|---|---|---|---|
| 0.wav | 5.6s | 安全有感兴趣呢 | 安全有感兴趣呢 | ✓ | 1.65s | 1.58s |
| 1.wav | 5.2s | 金融当中先 | 金融当中先 | ✓ | 1.33s | 1.31s |
| 2.wav | 4.5s | 全球金融咱们 | 全球金融咱们 | ✓ | 1.20s | 1.31s |
| 3.wav | 3.1s | (silence) | (silence) | ✓ | 0.89s | 0.74s |
| 4.wav | 6.3s | 搬机没做就是 | 搬机没做就是 | ✓ | 2.10s | 2.00s |
| 5.wav | 1.8s | (silence) | (silence) | ✓ | 0.56s | 0.53s |
| 指标 | 数值 | 判定 |
|---|---|---|
| Decoder Cosine Similarity | ~0.999999 | 通过 |
| Decoder Max Absolute Error | < 1e-5 | 通过 |
| Decoder Argmax Match | True | 通过 |
| Joiner Cosine Similarity | ~0.999999 | 通过 |
| Joiner Max Absolute Error | < 1e-5 | 通过 |
| Joiner Argmax Match | True | 通过 |
结论: NPU 与 CPU 推理结果在 token 决策级别完全一致,数值误差 < 1e-5,不影响最终识别结果。精度误差 < 1%,满足精度对齐要求。
测试条件:单 NPU 卡 (Ascend910_9362),batch_size=1,流式 chunk=45帧,ONNX Runtime CANNExecutionProvider。
| 指标 | NPU (混合) | CPU | 说明 |
|---|---|---|---|
| 平均推理耗时 | 1.29s | 1.25s | 6个测试文件的平均值 |
| 平均 Encoder 耗时 | 1.18s | 1.23s | 当前均在 CPU 执行 |
| 平均 Decode 耗时 | 0.11s | 0.02s | NPU 解码器执行 |
| 平均 RTF | 0.230 | 0.223 | 实时率(越低越好) |
| 平均加速比 | 0.96x | - | 整体 vs CPU |
# 基础依赖
pip install modelscope onnx onnxruntime-cann==1.24.4
pip install numpy scipy soundfile librosa
# 验证 NPU 可用
python -c "import onnxruntime; print(onnxruntime.get_available_providers())"
# 应包含: ['CANNExecutionProvider', 'CPUExecutionProvider', ...]modelscope download --model manyeyes/k2transducer-zipformer-multi-zh-hans-onnx-online-20231212模型默认下载至 ~/.cache/modelscope/hub/models/manyeyes/k2transducer-zipformer-multi-zh-hans-onnx-online-20231212/。
# NPU 推理(默认,decoder/joiner 在 NPU,encoder 在 CPU)
python inference.py --device npu
# CPU 推理(所有模块在 CPU)
python inference.py --device cpu
# 精度对比(NPU vs CPU 完整测试)
python inference.py --device both --all
# 单文件推理
python inference.py --device npu --audio /path/to/audio.wav
# 自定义模型路径
python inference.py --model-dir /path/to/model --device npu# 完整评测(精度 + 性能 + 数值精度)
python eval.py --report
# 生成评测报告
python eval.py --report --output eval_results.json --report-output EVALUATION_REPORT.md| 文件 | 大小 | 说明 |
|---|---|---|
| encoder.onnx | 249MB | Zipformer 流式编码器(16层) |
| decoder.onnx | 5MB | Token 解码器 |
| joiner.onnx | 4MB | Transducer Joiner 网络 |
| tokens.txt | 18KB | 词汇表(2002 tokens) |
| test_wavs/ | 844KB | 6 个测试音频(1.8-6.3秒) |
├── inference.py # 主推理脚本(支持 NPU/CPU/混合)
├── eval.py # 评测脚本(精度/性能/张量对比)
├── README.md # 本文档
├── EVALUATION_REPORT.md # 评测报告
├── eval_results.json # 评测结果(JSON)
├── results.json # 精度对比结果
├── results_accuracy.json # 精度验证结果
├── results_final.json # 最终测试结果
├── results_final_verified.json # 验证后的最终结果
├── results_npu.json # NPU 测试结果
└── results_stable.json # 稳定版测试结果Audio (.wav)
→ Log-Mel Filterbank (80-dim, CPU)
→ Zipformer Encoder (chunk=45, streaming, CPU)
→ Transducer Decoder + Joiner (greedy search, NPU)
→ Chinese Text Output编码器维护 6 类缓存状态以支持流式 chunk-by-chunk 推理:
cached_key_*: 注意力 key 缓存cached_nonlin_attn_*: 非线性注意力缓存cached_val1_* / cached_val2_*: 值缓存cached_conv1_* / cached_conv2_*: 卷积缓存ORT_DISABLE_CANN_ALLOCATOR=1 避免内存碎片Apache License 2.0
昇腾 NPU 适配完成于 2026-05-17 · CANN 8.5.1 · torch_npu 2.9.0 · Ascend 910