AI-深度学习

从零搭建视觉模型 23:量化与精度对比

展开合集目录
  1. 从零搭建视觉模型 01:图片进入模型后发生了什么
  2. 从零搭建视觉模型 02:Python 起步,写给 C/C++ 开发者
  3. 从零搭建视觉模型 03:从像素到张量的基础概念
  4. 从零搭建视觉模型 04:图片如何变成张量
  5. 从零搭建视觉模型 05:MLP 入门,从手算到图片输入
  6. 从零搭建视觉模型 06:亲手搭建一个小型 CNN
  7. 从零搭建视觉模型 07:模型怎样预测类别:分数、概率与决策
  8. 从零搭建视觉模型 08:让模型开始学习,损失、梯度与训练循环
  9. 从零搭建视觉模型 09:数据集、标签与数据划分
  10. 从零搭建视觉模型 10:损失函数与优化器:怎样把错误变成更新
  11. 从零搭建视觉模型 11:批次、训练轮次与学习率
  12. 从零搭建视觉模型 12:训练第一个真实图片分类器
  13. 从零搭建视觉模型 13:过拟合、数据增强与正则化
  14. 从零搭建视觉模型 14:验证、测试与错误分析
  15. 从零搭建视觉模型 15:保存模型、恢复训练与独立推理
  16. 从零搭建视觉模型 · 综合实践:实现 MLP,从损失计算、训练到 ONNX 推理
  17. 从零搭建视觉模型 16:ResNet 与残差连接
  18. 从零搭建视觉模型 17:预训练、迁移学习与微调
  19. 从零搭建视觉模型 18:轻量模型与计算成本
  20. 从零搭建视觉模型 19:目标检测与 YOLO:从类别到目标框
  21. 从零搭建视觉模型 20:图像分割与 U-Net:给每个像素一个判断
  22. 从零搭建视觉模型 21:注意力与视觉 Transformer
  23. 从零搭建视觉模型 22:从训练模型到 ONNX
  24. 从零搭建视觉模型 23:量化与精度对比
  25. 从零搭建视觉模型 24:从摄像头输入到部署验收
  26. 从零搭建视觉模型 25:发展历史、主流分类与当前格局
从零搭建视觉模型 23:量化与精度对比的封面

学习初稿 · 第 23 课。 本篇已开放网页阅读,用于先建立完整认识。文中手算值和示意记录不代表真实训练成绩;真实数据训练、预训练权重和板端测试以本篇具体说明为准,本篇已附代码练习,实际验证范围见文末与包内记录。

为什么把浮点数换成较少位数

权重和激活如果用更低位数表示,可能减少存储与内存流量,并利用硬件整数运算。但更少的可表示值意味着近似误差,实际速度也依赖执行后端是否提供高效内核。

量化不能自动补齐不支持的算子,也不是把文件压缩成 zip。推理时采用的数值表示和运算路径必须与模型格式、量化参数及硬件实现一起匹配。

用一个数看懂量化与反量化

一种常见仿射表示为 q=clip(round(x/s)+z),反量化为 x_hat=(q-z)×s。s 是正的缩放因子,z 是零点,clip 限制整数范围。实际实现的舍入规则与量化范围需要核对。

取 s=0.1、z=0,x=0.26,得到 q=3,恢复为 0.3,误差 0.04。这说明量化后数值通常不能完全恢复。若输入范围超出整数能表示的区间,还会发生截断,而不只是舍入。

values = [-0.26, 0.0, 0.26, 20.0]
scale, zero = 0.1, 0
qmin, qmax = -128, 127
quantized = [max(qmin, min(qmax, round(x/scale) + zero)) for x in values]
restored = [(q-zero)*scale for q in quantized]
print(quantized)
print(restored)
assert quantized == [-3, 0, 3, 127]

20.0 超过此设置的上界 12.7,误差远大于一个量化步长。真实模型需要根据张量分布与硬件支持选择范围,不能对所有层固定同一个随意的 scale。

对称、非对称与逐通道

对称量化通常围绕零安排范围,非对称量化可用零点表达偏移。逐张量使用一组量化参数,逐通道则为不同通道设置参数,可能更适合幅度差异明显的权重。是否支持、沿哪个轴量化,都由具体工具和算子决定。

权重量化与激活量化是不同维度。某种低比特权重格式可能仍用浮点激活;另一种实现则把两者都量化。只写“INT8 模型”不足以说明图中每一处精度。

校准数据决定观察到的范围

训练后静态量化常用代表性数据估计激活分布;动态量化会在运行时计算部分量化参数;量化感知训练则在训练中模拟相关误差。它们适用的算子、成本和工具链不同。ONNX Runtime 量化文档

校准集通常不需要任务标签,但需要与实际输入一致的预处理和分布。只用全黑图或少量相似图片,可能无法覆盖现场激活范围。校准不是独立测试,不能用最终测试集反复调整量化策略并继续声称测试独立。

对飞机汽车分类,应覆盖两类、不同亮度与背景。若将来上摄像头,公开小图片的校准并不保证现场可靠。数据来源、数量、预处理和校准方法应随模型一起记录。

分三层比较精度

先比较单个张量的浮点与反量化误差,定位是否存在明显截断;再比较网络 logits 或其他输出;最后在同一份验证数据上计算任务指标。一个整体平均误差很小的模型,也可能在少数关键样本上翻转类别。

应保存浮点正确、量化错误的样本列表,并按类别和条件分析。误差集中在某一层时,可以检查其范围、量化轴和算子实现;是否保留部分层高精度,需要工具链支持并重新测性能。

静态量化后图里可能出现量化与反量化节点。这些节点本身不证明硬件已经使用整数加速,应查看实际后端执行与 profiling。频繁跨精度转换可能抵消收益。

一份可比较的实验表

项目 浮点基线 量化模型
数据清单与预处理 同一版本 同一版本
模型文件与哈希 实际记录 实际记录
准确率与每类指标 实测 实测
峰值内存 实测 实测
预热后延迟 同设备同边界 同设备同边界
后端与回退情况 记录 记录

本草稿覆盖数值原理与实验设计,未执行真实模型静态量化,也未生成板端性能数据。后续实现时按目标平台选择具体工具,不把一个 CPU 量化命令冒充 NPU 转换流程。

练习

  1. s=0.2、z=0,0.52 的量化与恢复值是多少?
  2. 校准是否需要真实标签?是否可以随便用几张图片?
  3. 文件缩小四倍,延迟是否一定缩小四倍?
参考答案

按本课舍入方式为 3,恢复为 0.6。校准通常不需任务标签,但输入必须有代表性且预处理一致。文件大小与执行时间受不同因素影响,算子支持、内存、转换和计算共同决定延迟。

下一课把输入、模型、后处理和性能测量接成一个完整验收流程。

配套代码练习

实验:量化舍入、截断与误差

查看完整代码:main.py
"""量化舍入、截断与误差。运行方式与练习见 README.md。"""
values = [-2.0,-0.8,0.0,0.3,0.9,2.0]
def quantize(xs,scale):
    q = [max(-127,min(127,round(x/scale))) for x in xs]
    restored = [v*scale for v in q]
    error = max(abs(a-b) for a,b in zip(xs,restored))
    clipped = sum(abs(x/scale)>127 for x in xs)
    return q,restored,error,clipped
for limit in [1.0,2.0]:
    q,restored,error,clipped = quantize(values,limit/127)
    print('校准范围:',(-limit,limit),'整数:',q,'反量化:',restored,'最大误差:',error,'截断数:',clipped)
    if limit==2.0: assert error <= (limit/127)/2 + 1e-12 and clipped==0
    else: assert clipped==2 and error==1.0
下载代码

在项目根目录执行;下载包解压后,在解压目录执行 python3 main.py。

cd 'content/posts/AI-深度学习/从零搭建视觉模型/23-量化与精度对比/code' && python3 main.py

本篇已附独立实验包,在代码卡片中查看源码、下载或复制运行命令。解压后执行 python3 main.py;依赖安装见包内 README.md。

观察目标: 范围 [-1,1] 截断两个值,最大误差 1;覆盖 [-2,2] 后无截断且误差不超过半个量化步长。

动手修改: 加入一个 20.0 的离群值,用全范围和原范围分别量化,比较普通样本误差与截断误差。

所有输入均在本篇代码中构造;运行范围和验证记录见包内 verification.md。


完整阅读目录 · 上一篇 · 下一篇