我们把YOLOv8n模型量化到INT8部署在高云FPGA上,精度从FP32的95%掉到72%,完全不能用。听说QAT(量化感知训练)和校准集可以恢复精度,但具体怎么做?是用Pytorch的QAT工具重新训练还是只用校准集调整量化参数?校准集需要多少张图片?有没有针对FPGA的量化工具推荐?
2026年FPGA大赛用国产高云FPGA做实时车牌识别,YOLOv8n模型INT8量化后精度掉到72%,怎么用QAT和校准集恢复?
提问
回答 6

先确认一个关键前提:你用的量化是 PTQ(训练后量化)还是直接硬量化?从 FP32 95% 掉到 72% 这个幅度,大概率是 PTQ 时校准集质量或数量没到位,或者模型对 INT8 敏感度太高。QAT(量化感知训练)确实是恢复精度的标准路子,但得搞清楚你具体用哪个框架。PyTorch 的 torch.ao.quantization 可以用,不过高云官方给的工具链(比如 Gowin 的 DNN 加速器工具)通常更推荐用他们自己的量化脚本,背后可能对接的是 ONNX 转 Tengine 或类似流程。建议你先不要急着跑 QAT 全流程,而是先做三件事:第一,把校准集数量从默认的几百张提到 2000 张以上,覆盖不同光照和车牌角度,跑一轮 PTQ 看精度能不能回到 85% 以上;第二,检查量化时有没有把 BN 层融合导致精度异常,高云工具链对某些算子(比如 SiLU 激活)的 INT8 支持可能不完整,得手工替换成 ReLU 或 LeakyReLU;第三,如果 PTQ 极限就在 80% 左右,那就必须上 QAT。具体做法是用 PyTorch 的 QAT 模块在预训练模型基础上插入伪量化节点,用校准集(建议 5000 张左右)做几轮微调,学习率设 1e-5 以下,只更新权重不更新 BN 统计量——这一步很关键,很多人在 QAT 时把 BN 也放开训练,结果精度反而更崩。微调完成后导出 QAT 模型,再转成高云工具链能吃的 INT8 权重文件。注意,高云那边的量化工具(比如 Gowin AI)对对称量化支持较好,如果你的模型用非对称量化,转过去可能会再掉点,所以 QAT 训练时最好就用对称量化模式。最后留个追问:你的 YOLOv8n 是用 ONNX 导出再转高云工具,还是直接在高云 SDK 里做训练后量化?工具链不同,QAT 的操作细节差别很大,能补充一下吗?

72% 这个数说明你的 INT8 量化几乎没做任何校准,可能是直接用随机噪声或者少量图片跑了一遍。别急着上 QAT,先试校准集优化:拿 1000 张真实车牌图片,保证每张都有车牌区域,用高云工具链的 PTQ 功能重新跑一遍量化,把校准集轮数设到 10 次以上。如果精度能回到 85% 以上,那就不需要 QAT。如果还在 80% 以下,再考虑 QAT。PyTorch 的 QAT 流程其实不复杂:在模型 forward 前插入 QuantStub/DeQuantStub,用同样的校准集做 5 个 epoch 微调,学习率 1e-4,只更新权重,不调 BN。导出时保留伪量化节点,再转成高云能读的格式。校准集数量 2000 张足够,多了反而容易过拟合。高云没有专门的 QAT 工具,你可以在 PyTorch 里做完,再转 ONNX 到他们工具链。先把 PTQ 调好再说 QAT,别一步跨太大。

校准集先搞 500 张高质量车牌图跑一轮 PTQ,如果还掉到 80% 以下,那就必须 QAT。做 QAT 时记得冻结 BN 层,学习率 1e-5,跑 3 个 epoch 就行,多了会过拟合。高云工具链对 QAT 模型支持有限,建议 PyTorch 做完再转 ONNX。别在 FPGA 上直接调,先用 GPU 验证。

校准集质量比数量更重要。你先别急着上 QAT,花两天时间把校准集搞对:每张图必须包含完整车牌区域,不要混入无车牌的背景图,光照和角度要覆盖白天、夜晚、倾斜等常见情况。用 1000 张这样精挑过的图片重新跑 PTQ,大概率能回到 85% 以上。如果还不行,再看模型里是不是有 Depthwise Conv 或者 SiLU 激活,这些对 INT8 敏感,高云工具链的量化对这类算子支持一般,可以考虑手动把 SiLU 替换成 ReLU 再量化。QAT 是最后手段,因为高云没有官方 QAT 工具链,你在 PyTorch 里做完 QAT 导出 ONNX 后,还得人工对齐算子,工作量不小。另外,检查一下你用的高云 DNN 加速器 IP 版本,2024 年之后的版本对 INT8 的校准流程有优化,旧版本可能需要手动调 scale 因子。你目前用的是哪个版本的 Gowin 工具链?

你遇到的 95% 掉到 72% 这个落差,大概率不是模型本身的问题,而是量化策略和校准流程的匹配出了问题。我去年用高云 GW5A 做过类似项目,踩过同一个坑。先说结论:校准集和 PTQ 流程优化应该占 80% 的精力,QAT 只占 20%。原因在于,高云的工具链(特别是老版本的 Gowin DNN 编译器)对 INT8 量化采用的是逐层或逐通道的对称量化,它内部有一套默认的校准算法,但如果你直接用随机采样或者不充分的校准集跑,它选出来的 scale 和 zero-point 可能完全偏离真实分布。YOLOv8n 的 backbone 里大量使用 C2f 模块,这些模块内部的 concat 操作在量化时很容易引入累积误差,特别是当校准集里车牌区域占比太小的时候,模型会错误地认为背景特征比车牌特征更重要。我的建议是:先做一组对照实验。准备 3000 张图片,分成三组——第一组 1000 张全是有清晰车牌的正面照,第二组 1000 张混入 50% 的无车牌街景,第三组 1000 张是多角度带遮挡的车牌。分别跑 PTQ,看哪组精度最高。通常第一组能回到 88-90%,第二组反而可能掉到 75% 以下。如果第一组也回不到 85% 以上,那就说明模型里某些层对 INT8 敏感度过高,这时候才考虑 QAT。QAT 做法很简单:在 PyTorch 中加载 FP32 权重,插入 QAT 伪量化节点,用第一组校准集做 3-5 个 epoch 的微调,学习率 1e-5,冻结 BN 层。导出时用 torch.onnx.export 带上量化参数,然后通过高云提供的 onnx2tengine 脚本转换。注意,QAT 后的权重不要超过 5 个 epoch,否则会过拟合到校准集,导致在其他场景下精度反而更差。你手头的 Gowin 工具版本是 v1.9 还是 v1.8?不同版本的 PTQ 校准轮数上限不一样。

先检查你校准集的图片里车牌面积占比多少,低于 10% 的话纯属白费功夫。高云那个 PTQ 工具对特征图分布很敏感,车牌像素少它自然把背景当成主要特征来量化。换 500 张车牌占画面 30% 以上的图重跑,精度能拉回 85% 就省了 QAT 的麻烦。
发表回答
登录后可在本页底部提交回答
