模型量化
用更少的 bit 换取更低的存储与带宽
建议阅读:约 19 分钟
学习目标
本章关键词
| 关键词 | 解释 | ESP32 工程类比 |
|---|---|---|
| Scale | 整数码与真实数值之间的比例系数。 | 像 ADC 的量程和每个码的物理含义。 |
| Zero-point | 映射中代表真实零值的整数偏移。 | 像传感器零偏校正后的基准码。 |
| 校准集 | 用于估计激活范围的代表性输入样本。 | 像用真实工况标定 ADC,而非只输入中间值。 |
| Per-channel | 为不同权重通道分别使用量化参数。 | 像为不同传感器通道分别做增益标定。 |
承上:回顾与定位
上一章建立了从训练状态到模型包的交付契约;本章开始改变数值表示,用可测误差换取存储、带宽和 kernel 机会。
历史发展脉络
神经网络量化并非简单追随移动芯片而出现。早期数字与模拟神经硬件就必须面对有限字长;深度学习扩大模型后,研究从“有限精度能否工作”转向压缩、低比特训练与整数算子协同设计。今天的 PTQ、QAT、per-channel 和代表性校准,是数十年精度—存储—硬件权衡的工程化结果。
有限字长被作为神经计算的系统设计问题
Neural Network Number Systems 比较了数字神经网络中的定点、浮点和指数数值表示。早期工作已经意识到,位宽选择同时影响电路成本、动态范围和计算误差,而不是单纯更换文件 dtype。
Neural Network Number Systems 原始论文记录 ↗Deep Compression 把量化放进完整模型压缩流水线
Deep Compression 将剪枝、训练后权值共享式量化和 Huffman 编码组合,展示模型存储与内存访问可大幅削减。它强化了一个工程事实:压缩方案必须连同编码开销、解码路径和目标硬件一起评估。
Deep Compression 原始论文 ↗低比特权重与激活进入训练过程
Quantized Neural Networks 在前向和反向计算中引入低精度权重与激活,并研究极低 bit 表示。量化不再只是模型训练完成后的包装,而可以在训练时显式暴露误差,让参数适应离散码本。
Quantized Neural Networks 原始论文 ↗整数算术从输入贯穿到输出
Jacob 等人给出面向整数算术推理的量化方案与训练流程,同时量化权重和激活,并处理比例因子、zero-point 与累加。算法设计开始明确对接 ARM CPU 和整数加速器,而非只报告文件缩小。
CVPR 整数推理原始论文 ↗PTQ 校准成为端侧工具链的标准阶段
LiteRT 的全整数量化流程使用代表性数据估计输入与中间激活范围,并允许把模型 I/O 也设为整数。当前实践因而强调校准数据、算子覆盖和目标硬件实测,而不把 int8 标签当作性能保证。
LiteRT 全整数量化官方教程 ↗类比图解
把连续山景印成一张只有有限色阶的版画
摄影师拥有层次丰富的原片,但印刷机每种颜色只有有限档位。制版师先观察整组照片的最暗与最亮区域,再决定每一格色阶覆盖多大范围;落在两格之间的颜色要舍入,超出纸张量程的高光和阴影只能压成同一个极值。分色制版则像为每个通道单独选量程。
类比的边界: 图像色阶主要诉诸视觉感受,模型误差却会在多层算子中累积,并以任务指标而非“看起来相似”衡量。真实整数 kernel 还涉及偏置尺度、int32 累加、requantize 和硬件指令,版画类比无法说明这些算术约束。
本章讲解
先从可逆近似公式看清三个误差入口
仿射量化用 q=round(x/scale)+zero_point,再把 q 限制到整数范围;反量化只得到格点上的近似值。误差分别来自格距造成的舍入、范围不足造成的饱和,以及统计范围被异常值拉宽后的分辨率浪费。实现时应分别统计量化 MSE、上下界命中率与零点映射,三者混成一个准确率数字很难定位。
对称、非对称与 per-channel 是后端契约选择
对称量化通常令 zero-point 为零,乘法路径更简单;非对称量化能更充分利用偏斜分布的整数范围。per-channel 可为每个输出通道设置 scale,常能缓解权重通道间幅度差异,却要求 kernel 知道量化轴并加载多组参数。选择前应查询目标 runtime 的 dtype、轴和算子限制,不能只凭 PC 精度。
校准不是抽几张“典型图”,而是覆盖激活状态空间
权重范围可以直接扫描,中间激活却由输入和前置层共同决定。代表性数据应覆盖光照、静默、饱和传感器、类别边界和设备噪声,并沿真实前处理进入模型。可按层查看直方图与裁剪比例,发现少量离群值是否支配 scale;若生产分布改变,原校准表也应视为需要重新验证的版本化资产。
整数卷积仍需要高位累加与正确的尺度接力
int8 输入与 int8 权重的乘积通常进入更宽的累加器,偏置尺度应与输入 scale×权重 scale 对齐,输出再经 multiplier、shift 或等价操作 requantize。任何一处零点补偿、舍入规则或饱和次序不同,都可能造成系统偏差。用极小矩阵手算累加与边界值,是验证自定义 kernel 最有效的单元测试之一。
把精度回归与性能验收放在同一张层级报告里
先比较 float 与量化模型的最终任务指标,再对输出漂移最大的样本逐层定位 SQNR、余弦相似度或最大绝对误差;同时从 profile 检查是否出现 Quantize/Dequantize 岛和 float fallback。若文件缩小却执行更慢,问题可能是缺少整数 kernel、布局转换或频繁重标度,而不是量化算法本身失败。
动态过程演示
浮点波形如何落入 256 个整数格
动画先伸缩一把覆盖实测数据的标尺,再让每个浮点点吸附到最近格位;超界点会撞上红色挡板,随后整数流进入累加器。
扫描分布 · activation samples → min/max/histogram
样本点铺开成直方图,长尾以另一颜色标出
激活范围必须由代表性真实输入估计
循环 / 返回条件: 若误差或饱和超限,播放器回到分布扫描,可切换校准样本、量化轴或范围策略;若性能不达标,则回到整数 kernel 检查 fallback 与转换边界。
查看静态全景图
float x ──(x/scale)+zp──► int8 q ──runtime kernel──► int8/float output
代码或命令示例
q = round(x / scale + zero_point)
q = clip(q, -128, 127)
x_hat = (q - zero_point) * scale动手实验
实验记录与导出
工程陷阱
核心测试
完成 3 道单选题后提交;提交前不会显示答案。
在 GitHub 上讨论本章
登录 GitHub 后提问、补充实测或分享你的实现;评论会保存在本课程的 GitHub Discussions 中。
评论区需要 JavaScript;也可以直接打开 GitHub 讨论区: 打开 GitHub 讨论区 ↗
延伸阅读
启下:下一章如何使用本章能力
下一章沿算子契约进入 layout、tiling、fusion 与硬件 kernel。
下一天: Day 4 · 算子与 Kernel