问题分析
虽然 Softmax 已移到 CPU,但问题已转移到其他敏感算子。从新日志看到:
| 节点 | 余弦相似度 | 问题 |
|---|---|---|
/blocks_ts.4/attn_t/Softmax |
0.688 | |
/blocks_st.3/attn_t/Softmax |
0.754 | |
/blocks_st.3/attn_t/v_linear/MatMul |
0.869 | |
/blocks_st.3/mlp_t/act/Mul_1 |
0.812 | |
/blocks_st.3/mlp_t/fc2/MatMul |
0.813 | |
/norm/ReduceMean |
0.824 |
核心原因:
- 50 条校准数据严重不足(时序模型需要 300-500 条)
- Attention 的 v_linear 对量化极敏感(仍用 int8)
- 深层网络误差累积(layer 3-4 恶化明显)
- max_percentile=0.99999 过高,放大了异常值影响
紧急解决方案(按优先级执行)
步骤 1:修改 YAML 配置(关键算子用 int16)
# config_final.yaml
model_parameters:
onnx_model: ./motionbert_lite_120.onnx
march: bayes-e
working_dir: motionbert_lite_model_output_final
layer_out_dump: true
node_info:
# ========== 所有 Attention 的 v_linear 强制 int16(最关键)==========
/blocks_st.0/attn_s/v_linear/MatMul:
ON: BPU
InputType: int16
OutputType: int16
/blocks_st.0/attn_t/v_linear/MatMul:
ON: BPU
InputType: int16
OutputType: int16
/blocks_st.1/attn_s/v_linear/MatMul:
ON: BPU
InputType: int16
OutputType: int16
/blocks_st.1/attn_t/v_linear/MatMul:
ON: BPU
InputType: int16
OutputType: int16
/blocks_st.2/attn_s/v_linear/MatMul:
ON: BPU
InputType: int16
OutputType: int16
/blocks_st.2/attn_t/v_linear/MatMul:
ON: BPU
InputType: int16
OutputType: int16
/blocks_st.3/attn_s/v_linear/MatMul:
ON: BPU
InputType: int16
OutputType: int16
/blocks_st.3/attn_t/v_linear/MatMul:
ON: BPU
InputType: int16
OutputType: int16
/blocks_st.4/attn_s/v_linear/MatMul:
ON: BPU
InputType: int16
OutputType: int16
/blocks_st.4/attn_t/v_linear/MatMul:
ON: BPU
InputType: int16
OutputType: int16
# blocks_ts 层同理配置所有 v_linear...
# ========== 深层 MLP 层用 int16 ==========
/blocks_st.3/mlp_s/fc1/MatMul:
ON: BPU
InputType: int16
OutputType: int16
/blocks_st.3/mlp_s/fc2/MatMul:
ON: BPU
InputType: int16
OutputType: int16
/blocks_st.3/mlp_t/fc1/MatMul:
ON: BPU
InputType: int16
OutputType: int16
/blocks_st.3/mlp_t/fc2/MatMul:
ON: BPU
InputType: int16
OutputType: int16
/blocks_st.4/mlp_s/fc1/MatMul:
ON: BPU
InputType: int16
OutputType: int16
/blocks_st.4/mlp_s/fc2/MatMul:
ON: BPU
InputType: int16
OutputType: int16
/blocks_st.4/mlp_t/fc1/MatMul:
ON: BPU
InputType: int16
OutputType: int16
/blocks_st.4/mlp_t/fc2/MatMul:
ON: BPU
InputType: int16
OutputType: int16
# ========== 输出头保持 int16 ==========
/head/MatMul:
ON: BPU
InputType: int16
OutputType: int16
calibration_parameters:
cal_data_dir: ./calibration_data_120
cal_data_type: float32
calibration_type: kl # 改用 KL 散度
max_percentile: 0.9999 # 从 0.99999 降低到 0.9999
per_channel: true
步骤 2:增加校准数据(必须执行)
# 50 条对时序模型远远不够,生成 300-500 条
# 覆盖:静止、慢速、快速、遮挡、不同视角
# 示例脚本
python3 generate_calibration_data.py \
--input_dir ./original_dataset \
--num_samples 400 \
--output_dir ./calibration_data_400 \
--cover_all_actions \
--sequence_length 120
# 修改 YAML 中的校准数据路径
calibration_parameters:
cal_data_dir: ./calibration_data_400
步骤 3:重新量化并验证
# 使用新配置重新量化
hb_mapper --config config_final.yaml
# 检查关键算子相似度
cat motionbert_lite_model_output_final/motionbert_lite_quant_info.json | \
grep -E "v_linear|Softmax|mlp_t/fc2"
# 预期 v_linear 相似度应提升到 0.95+
预期效果对比
| 指标 | 当前 | 步骤 1 后 | 步骤 1+2 后 |
|---|---|---|---|
| v_linear 相似度 | 0.86-0.87 | 0.95+ | 0.98+ |
| 深层 MLP 相似度 | 0.81-0.85 | 0.90+ | 0.95+ |
| Softmax 相似度 | 0.68-0.75 | 0.90+ | 0.98+ |
| 最终输出相似度 | 0.998944 | 0.9995+ | 0.9998+ |
| 关键点抖动 | 明显 | 减轻 | 基本消除 |
如果仍不满足(QAT 方案)
如果 PTQ 调优后仍有抖动,QAT 是必经之路:
# QAT 配置示例
from horizon_plugin_pytorch.quantization import QConfig, prepare_qat
qconfig = QConfig(
activation={'dtype': 'int8'},
weight={'dtype': 'int8'},
op_specific={
'MatMul': {
'activation': {'dtype': 'int16'}, # Attention 层用 int16
'weight': {'dtype': 'int8'}
},
'Softmax': {'activation': {'dtype': 'float32'}}, # Softmax 用 FP32
}
)
model = prepare_qat(model, qconfig)
# 微调 5-10 个 epoch
# ...
model = convert(model)
参考社区精华帖:
需要确认
- 当前板端 MPJPE 误差:浮点模型 vs 量化模型各是多少?
- 抖动具体表现:帧间位置跳变幅度(毫米)?
- 是否有原训练数据集:可用于 QAT 微调?
先执行步骤 1 和 2,通常能解决 90% 以上的 Transformer 量化精度问题。完成后请反馈新的量化报告。