[算法工具链][图像算法][RDK X5][VideoViT PTQ calibrate后精度从90%跌至26%]

### 1. 基础信息

| 项 | 内容 |

|----|------|

| 板卡型号 | **RDK X5** |

| 问题领域 | **算法工具链(OpenExplore)**、图像算法 |

| 复现概率 | **必现**(同一 cal 集、同一 mapper,多次 makertbin 均如此) |

**转化环境(x86 OE Docker,问题发生在此阶段):**

| 项 | 内容 |

|----|------|

| march | `bayes-e` |

| hb_mapper | 1.24.3 |

| hbdk | 3.49.15 |

| hbdk_runtime | 3.15.55.0 |

| horizon_nn | 1.1.0 |

| Python | `python3 --version` → **(发帖前在容器内填写,如 3.10.x)** |

| horizon 相关包 | `pip list \| grep horizon` → **(发帖前粘贴输出)** |

**板端系统(若已烧录/推理,请补充;模板要求):**

```bash

sudo cat /etc/version

sudo rdkos_info

```

> 请将 `sudo rdkos_info` 输出保存为 `rdkos_info_xxxx.txt` 并以****附件****上传(见 [社区提问模板]( 社区提问模板 ))。

> 本次问题主要在 **OE 容器内 PTQ**,若尚未上板,可注明「仅 OE 转化阶段,板端 rdkos_info 待补」。

—

### 2. 问题描述

**开发内容:** 自研 VideoViT 四分类(猫行为:`active` / `eating` / `others` / `water`),PyTorch 导出 ONNX,使用 `hb_mapper makertbin` 转 X5 BPU。

**输入输出:**

- 输入:`video`,`1×16×3×224×224`(16 帧 clip)

- 输出:`logits`(4 类)

- 结构含时序模块:`temporal` / `temporal_gate` / `temporal_mha` 等

**预期结果:** PTQ 后分类精度接近 FP32(校准集约 90%,完整 val 约 94%)。

**实际表现(同一 cal120,decord 预处理,featuremap + `no_preprocess`):**

| 阶段 | 运行时 | 准确率 | others / water recall |

|------|--------|--------|------------------------|

| 原始 FP32 | ONNXRuntime | **90%** | 77% / 90% |

| optimized | HB_ONNXRuntime | **90%** | 77% / 90% |

| **calibrated** | HB_ONNXRuntime | **26%** | **0% / 0%** |

| **quantized** | HB_ONNXRuntime | **25%** | **0% / 0%** |

**与预期不符之处:**

- `optimize` 阶段正常,**`calibrate` 之后** logit 失真、分类塌缩;

- `quantized` 与 `calibrated` 几乎一样差,说明主因在 **校准(估 scale)**,而非单独 INT8 一层;

- 单条真值为 `active` 的样本:calibrated 预测为 `eating`,四类 logit 被拉平;

- `quant_info` 中 `temporal_gate`、`blocks.8/attn` 等层 **cosine similarity 为负**(最低约 -0.53)。

**校准日志片段:**

```

Calibration using batch 8

Reset batch_size=1 and execute forward again…

```

—

### 3. 复现步骤

```bash

# 1. 生成校准 bin(decord,与训练 val 一致)

python3 preprocess_cal_data_for_x5.py --cal_csv …/cal.csv --cal_root …/ave --output_dir …/cal_data_f32

# 2. PTQ + 编译

hb_mapper makertbin --model-type onnx --config /workspace/cat_mall_9448_mapper_ave.yaml

# 3. 分阶段评估(HB vs ORT)

python3 eval_all_hb_stages.py --val_csv …/cal.csv --output_dir …/stage_compare

```

**转换命令:**

```bash

hb_mapper makertbin --model-type onnx --config /workspace/cat_mall_9448_mapper_ave.yaml

```

—

4. 已排查措施与结果

| 排查项 | 结果 |

|--------|------|

| 标签 / eval argmax | 已核对 meta,无 off-by-one |

| 预处理不一致 | 已统一 decord,与训练一致 |

| 校准集过少/不平衡 | 每类 30 条(共 120)仍塌缩 |

| `calibration_type: max` | 早期曾「几乎全 eating」,未恢复 |

| `kl + per_channel`(当前) | optimized 90%,calibrated 仍 ~26% |

| 论坛类似帖 | 见 [双目量化后纯色]( RDK X5双目估计算法量化后输出为纯色问题 )、[QAT qconfig]( QAT之qconfig使用指南 ),无完全一致案例 |

5. 请教的问题

1. VideoViT + 16 帧时序结构在 `bayes-e` 上 PTQ,对 `temporal` / `attn` 是否有已知限制或推荐导出方式?

2. **calibrated 阶段塌缩**,官方建议优先尝试:`max` vs `kl`、`per_channel: false`、`node_info` int16/CPU、分类头 int32 输出?

3. 校准日志 **batch8 → batch1 回退** 是否影响 scale?有无规避方式?

4. 若 PTQ 无法恢复,自定义 VideoViT 是否建议直接 **QAT**?有无 X5 可参考案例?

—

感谢各位大佬!

—

## 三、第二条回复 · mapper 配置附件

以下为 `cat_mall_9448_mapper_ave.yaml`(OE 内路径:`/workspace/cat_mall_9448_mapper_ave.yaml`):

```yaml

model_parameters:

onnx_model: /mnt/zy/InternViT-300M/cat-mall-aeow/cat_mall_9448.onnx

march: bayes-e

layer_out_dump: false

working_dir: /workspace/model_output

output_model_file_prefix: cat_mall_9448_ave

input_parameters:

input_name: video

input_type_rt: featuremap

input_type_train: featuremap

input_layout_rt: NCHW

input_layout_train: NCHW

input_shape: 1x16x3x224x224

norm_type: no_preprocess

calibration_parameters:

cal_data_dir: /workspace/dataset/0526_update_split_calibration_ave/cal_data_f32

cal_data_type: float32

calibration_type: kl

per_channel: true

preprocess_on: false

compiler_parameters:

compile_mode: latency

core_num: 1

optimize_level: O3

debug: false

```

—

四、第三条回复 · 补充数据(可选)

calibrated 混淆矩阵(行=真值,列=预测):

          active  eating  others  water

active 15 15 0 0

eating 14 16 0 0

others 18 11 0 1

water 10 20 0 0

```

**quant_info cosine 最低层(节选):**

```

-0.53 /temporal_gate/temporal_gate.2/MatMul

-0.05 /blocks/blocks.8/attn/MatMul

-0.04 /temporal_mha/MatMul

```

严重的掉点可以尝试QAT ,QAT这部分的内容比较深入,难度系数比较高,可以参考手册探索一下

从日志看,经过大模型分析:

VideoViT 中的 temporal、attn 模块通常包含大量复用的矩阵乘法或位置编码生成逻辑。如果模型中存在被多次调用且输入分布差异巨大的共享模块,PTQ 默认的全局统计会导致 Scale 无法兼顾所有调用场景。

  • 现象关联:提到 temporal_gateblocks.8/attn 等层 Cosine 为负,这通常意味着量化后的数值范围完全错位(例如正数被量化为负数区间,或动态范围被极端值压缩导致有效信息丢失)。

  • 参考案例:在地平线文档中,类似 gen_sineembed_for_position这种在 Decoder 各层复用的模块,若直接共享,不同层的输入范围差异会导致统计出的 scale 不准确,进而产生截断误差 。

  • 建议操作:

    1. 检查共享算子调用次数使用 hmct-debugger或中间日志查看是否有算子 called times > 1。

    2. 拆开共享模块:如果存在复用模块,建议在 PyTorch 导出 ONNX前,将复用的 Module 实例化多次(如 self.layer_0_attn, self.layer_1_attn),或者在 Mapper配置中尝试通过节点级配置隔离敏感节点。

B. Calibration Type 选择与 Batch Size回退

  • KL vs Max:对于 Attention 机制和 ViT结构,激活值分布往往呈现长尾或双峰特性。kl 校准依赖于直方图分布拟合,如果校准数据量不足或分布不均,容易拟合失败。max 虽然保守,但在分布极端情况下更稳定。

  • Batch Size 回影响:日志显示 Reset batch_size=1 and execute forward again。这说明工具检测到某些算子不支持 Batch > 1 或显存受限。单样本校准会显著增加统计噪声,导致 Scale 估计偏差。

    • 建议:确保校准数据集足够大(建议至少覆盖各类别典型样本),并尝试在配置中强制指定较小的 cal_batch_size(如果支持)或在预处理阶段确保数据独立性。

      可以求助:https://chat.oe.horizon.auto/ 尝试是否有优化思路,预计需要在模型架构层面进行调整优化