深度学习笔记--模型的量化

张开发
2026/4/11 0:10:34 15 分钟阅读

分享文章

深度学习笔记--模型的量化
一、模型的量化在深度学习中量化是指将模型中的数值主要是权重和激活值从高精度数据类型通常是 32 位浮点数FP32转换为低精度数据类型例如 8 位整数INT8的过程。它的核心目的是压缩模型和加速推理同时尽量保持模型的精度不显著下降。1.1 为什么需要量化减少模型体积INT8 占用的内存是 FP32 的 1/4。例如一个 100MB 的 FP32 模型量化后仅约 25MB。加速计算低精度整数运算比浮点运算更快许多硬件如 CPU、GPU、NPU、DSP都支持高效的 INT8 矩阵乘法。降低功耗与带宽更小的数据量意味着更少的内存访问和能耗对移动端、嵌入式设备非常友好。1.2 量化是如何工作的量化本质上是一个映射将浮点数范围 $[x_{min}, x_{max}]$ 线性映射到整数范围例如 0~255 或 -128~127。常见公式非对称量化x_int round(x_float / scale zero_point)scale缩放因子控制步长。zero_point零点使得实数中的 0 能精确映射到整数。1.3 量化的主要类型训练后量化模型训练完成后直接对权重和激活值进行量化。简单易用但精度损失可能较大尤其对于小模型。量化感知训练在训练过程中模拟量化误差通过“伪量化”节点让模型参数适应低精度表示。通常能更好地保持精度。动态/静态量化动态量化在推理时实时计算激活值的范围静态量化则使用校准数据集预先统计激活值的范围更常用。1.4 量化的精度格式INT8最主流精度损失小加速明显。INT4 / INT2更极端压缩常用于内存极度受限的场景但精度损失大。FP16 / BF16有时也归为“半精度量化”但通常不严格称为量化因为仍是浮点。1.5 量化有什么缺点精度损失极端量化可能导致模型准确率下降尤其是对异常值敏感的任务。并非所有操作都支持某些层如 LayerNorm、Softmax通常保持浮点仅在卷积、全连接等计算密集层使用 INT8。1.6 应用场景移动端手机、手表、嵌入式设备树莓派、摄像头、边缘计算智能传感器。大语言模型的GPTQ、AWQ等量化方法使得百亿级模型能在单张 GPU 上运行。二、量化例程2.1 yolo系列的量化对于yolo系列的模型只需要通过以下的方式进行量化pt----onnx----trt 通过三步就可以实现命令如下yolo export modelyolo11n.pt formatonnx opset12 dynamicFalse ./TensorRT-8.6.1.6/targets/x86_64-linux-gnu/bin/trtexec --onnxyolo11n.onnx --saveEngineyolo11n.engine --fp16 --fp16 显式启用了 FP16 模式TensorRT 会尝试将模型的权重和计算从默认的 FP32 转换为 FP16。 如果需要其他精度 不加 --fp16默认 FP32单精度 加上 --int8INT8 量化通常需要校准数据 加上 --best让 TensorRT 自动选择最优精度FP16/INT8 等在 TensorRT 的 INT8 量化中校准数据是指一组具有代表性的输入样本用于统计模型各层的激活值中间输出的数值范围从而确定合适的量化参数scale和zero_point。2.2 为什么需要校准数据INT8 只能表示 256 个离散整数。要将 FP32 的激活值映射到 INT8需要知道该层输出值的最小值和最大值或分布。这些统计信息无法从模型权重直接推导必须喂入真实数据让模型实际运行一遍观察每层输出的数值范围。校准数据不需要标签不需要标注只需是能代表实际推理输入分布的样本例如几百张验证集图片。2.3 典型流程准备一个校准数据集通常 5001000 张图片/样本。TensorRT 在校准器如IInt8EntropyCalibrator2中跑一遍这些数据。记录每一层激活值的直方图或 min/max。选择能最小化信息损失的量化参数例如选择使 KL 散度最小的阈值。生成 INT8 引擎。2.4 注意事项校准数据必须与真实应用场景的数据分布一致。例如做自动驾驶就不能用随机噪声或 ImageNet 猫狗图来校准。数量不宜太少统计不稳定也不宜过多耗时一般 5001000 张足够。TensorRT 会忽略校准数据的标签仅用于统计数值范围。总结校准数据就是让模型“预演”一遍用于摸清每层输出的脾气从而把浮点数合理压缩成 8 位整数。三、使用一个例子说清楚量化下面用一个具体的数值例子演示FP32 → INT8的量化过程场景设定假设某一层的激活值FP32范围是[-1.0, 2.0]我们想把它映射到[-128, 127]的 INT8 范围有符号 8 位整数。已知参数实际浮点最小值x_min -1.0实际浮点最大值x_max 2.0量化后整数最小值q_min -128量化后整数最大值q_max 127第 1 步计算 scale 和 zero_pointScale缩放因子scale (x_max - x_min) / (q_max - q_min) (2.0 - (-1.0)) / (127 - (-128)) 3.0 / 255≈ 0.0117647Zero_point实数 0.0 映射到的整数zero_point round(q_min - x_min / scale) round(-128 - (-1.0) / 0.0117647) round(-128 85.0) round(-43.0) -43验证当x 0.0时q round(0.0 / scale zero_point) round(0 (-43)) -43符合预期。第 2 步量化一个具体数值取一个浮点数例如x 0.5量化公式q round(x / scale zero_point) round(0.5 / 0.0117647 (-43)) round(42.5 - 43) round(-0.5) -1 假设四舍五入-0.5 向零取整得 -1所以0.5在 INT8 中表示为-1。第 3 步反量化回浮点数近似反量化公式x_q (q - zero_point) * scale (-1 - (-43)) * 0.0117647 42 * 0.0117647 0.4941174与原始值0.5相比误差约-0.00588精度损失很小。第 4 步极端值测试x 2.0最大值q round(2.0 / 0.0117647 - 43) round(170 - 43) 127✅ 刚好到 INT8 上限。x -1.0最小值q round(-1.0 / 0.0117647 - 43) round(-85 - 43) -128✅ 刚好到 INT8 下限。总结表浮点数 (FP32)量化后 INT8反量化近似值误差2.01272.00.00.5-10.4941-0.00590.0-430.00.0-1.0-128-1.00.0这个例子展示了量化/反量化的完整过程用 scale 和 zero_point 将连续浮点值离散化到 256 个格子中。实际深度学习量化会更复杂如每通道量化、KL 散度校准但核心原理完全相同。

更多文章