量化为什么会有损失:从量化误差到精度下降

1. 引言

模型量化通过降低模型参数和计算过程中的数值精度,将原本使用 FP32 等高精度浮点数据表示的模型转换为 INT8 等低比特整数模型,从而降低模型存储空间、减少计算开销,并提升模型在边缘设备上的推理效率。

然而,模型量化带来的收益并不是没有代价的。

在 FP32 模型中,一个参数可以表示为:

复制代码
0.123456

经过 INT8 量化后:

复制代码
16

虽然整数形式更加紧凑,但是原始浮点数据中的部分信息已经无法完全保留。

这种从高精度数据表示转换为低精度数据表示过程中产生的信息差异,就是量化误差(Quantization Error)。

量化误差是模型量化过程中不可避免的问题,也是影响量化模型最终精度的重要因素。

因此,理解模型量化为什么会产生损失,需要从量化过程本身出发。

本文主要介绍:

  • 什么是量化损失
  • 量化损失产生的本质原因
  • 舍入误差如何产生
  • 截断误差如何产生
  • 为什么量化误差会影响模型最终精度

2. 量化损失的概念

2.1 从浮点表示到整数表示

神经网络模型中的主要数据包括:

  • 权重(Weight)
  • 偏置(Bias)
  • 激活值(Activation)

训练阶段通常使用 FP32 或 FP16 表示这些数据。

例如:

diff 复制代码
FP32:

0.127
0.456
-0.832

这些浮点数据可以表示非常丰富的数值变化。

而 INT8 的表示范围有限:

css 复制代码
[-128,127]

因此,需要通过量化过程建立浮点空间和整数空间之间的映射关系。

量化过程可以表示为:

markdown 复制代码
浮点值

    ↓

除以 Scale

    ↓

取整

    ↓

整数值

数学表达:

ini 复制代码
quantized_value = round(real_value / scale)

其中:

  • real_value:原始浮点值
  • scale:量化比例
  • quantized_value:量化后的整数值

由于取整操作会改变原始数值,因此量化后的整数只能近似表示原始浮点值。


2.2 量化损失的定义

量化损失描述的是:

量化前后的数值差异。

完整过程:

复制代码
FP32

  ↓

量化

  ↓

INT8

  ↓

反量化

  ↓

近似 FP32

例如:

原始浮点值:

复制代码
0.523

量化:

复制代码
52

假设:

ini 复制代码
scale = 0.01

反量化:

ini 复制代码
52 × 0.01

=0.520

因此:

ini 复制代码
量化误差

=0.523 - 0.520

=0.003

这个差值就是量化过程中产生的信息损失。


3. 量化损失产生的本质

3.1 连续空间映射到离散空间

量化产生误差的根本原因是:

连续浮点空间需要映射到有限离散整数空间。

FP32:

erlang 复制代码
0.10001
0.10002
0.10003
...

理论上可以表示连续变化。

而 INT8:

erlang 复制代码
0
1
2
...

只能表示有限数量的离散状态。

因此,多个不同的浮点值可能会映射到同一个整数值。

例如:

量化前:

复制代码
0.101
0.102
0.103

量化后:

复制代码
13
13
13

那么:

复制代码
0.101
0.102
0.103

之间的细微差异就无法恢复。

这就是量化损失产生的根本原因。


3.2 Scale 决定量化精度

Scale 决定了整数空间中的一个单位对应多少浮点变化。

例如:

ini 复制代码
scale = 0.01

表示:

复制代码
INT8 增加 1

对应 FP32 增加 0.01

如果:

ini 复制代码
INT8 = 50

对应:

ini 复制代码
50 × 0.01

=0.5

如果:

ini 复制代码
INT8 = 51

对应:

ini 复制代码
51 × 0.01

=0.51

因此:

整数之间的最小间隔:

复制代码
0.01

就是当前量化精度。

Scale 越小:

复制代码
一个整数单位代表的浮点范围越小

↓

量化精度越高

Scale 越大:

复制代码
一个整数单位代表的浮点范围越大

↓

量化误差增加

因此,Scale 的选择直接影响量化效果。


4. 舍入误差(Rounding Error)

4.1 舍入误差产生原因

量化过程中,浮点值经过 Scale 映射后,通常会得到一个非整数结果。

例如:

ini 复制代码
real_value / scale

=12.7

但是整数无法表示:

复制代码
12.7

因此需要进行取整:

scss 复制代码
round(12.7)=13

这个过程中产生的误差,就是舍入误差。


4.2 舍入误差示例

假设:

ini 复制代码
scale = 0.1

原始浮点值:

复制代码
1.26

量化:

ini 复制代码
1.26 / 0.1

=12.6

取整:

scss 复制代码
round(12.6)

=13

反量化:

ini 复制代码
13 × 0.1

=1.3

因此:

复制代码
原始值:

1.26

量化后:

1.30

误差:

ini 复制代码
1.26 - 1.30

=-0.04

4.3 舍入误差特点

舍入误差具有以下特点:

单次误差通常较小

舍入误差只发生在整数映射过程中。

与 Scale 大小相关

Scale 越大:

复制代码
整数之间距离越大

↓

舍入误差可能越明显

多层传播会影响模型输出

单个参数的误差通常很小。

但是神经网络包含大量参数:

复制代码
卷积

  ↓

激活

  ↓

下一层计算

  ↓

多层传播

大量误差累积后,可能影响最终输出。



5. 截断误差(Clipping Error)

5.1 截断误差产生原因

除了舍入误差之外,量化过程中还存在另一类重要误差:

截断误差(Clipping Error)。

截断误差产生于:

原始数据超过量化范围,无法被目标数据类型表示。

INT8 的表示范围:

css 复制代码
[-128,127]

但是,在实际神经网络计算过程中,权重和激活值的分布并不一定完全落在这个范围内。

例如:

实际数据范围:

css 复制代码
[-200,200]

其中:

复制代码
200

已经超过 INT8 最大可表示值:

复制代码
127

因此,量化过程中需要将超出范围的数据限制到边界:

复制代码
200 → 127

这个过程称为截断(Clipping)。


5.2 截断误差示例

假设:

INT8 最大值:

复制代码
127

某个浮点激活值:

复制代码
2.5

经过 Scale 映射:

ini 复制代码
2.5 / scale

=150

但是:

INT8 最大只能表示:

复制代码
127

因此:

复制代码
150 → 127

反量化:

复制代码
127 × scale

最终恢复出的值会小于真实值:

复制代码
反量化结果 < 2.5

这部分差异就是截断误差。

与舍入误差相比,截断误差通常更大,因为它直接丢失了超过表示范围的数据。


5.3 截断误差与量化范围的关系

量化范围的选择会直接影响截断误差。

如果量化范围设置过小:

markdown 复制代码
覆盖范围不足

      ↓

大量数据超过范围

      ↓

截断增加

例如:

实际激活范围:

css 复制代码
[-5,5]

但是设置:

css 复制代码
[-1,1]

那么:

复制代码
1 以上的数据

都会被限制为最大值

大量有效信息会因此丢失。


如果量化范围设置过大:

markdown 复制代码
覆盖范围增加

      ↓

Scale 增大

      ↓

整数间隔变大

      ↓

舍入误差增加

例如:

同样使用 INT8:

范围 A:

css 复制代码
[-1,1]

范围 B:

css 复制代码
[-10,10]

虽然范围 B 可以覆盖更多数据,但是每一个整数单位代表的浮点变化更大:

范围 A:

复制代码
scale 较小

精度更高

范围 B:

复制代码
scale 较大

精度降低

因此,量化过程需要在:

复制代码
数据覆盖范围

和

表示精度

之间寻找平衡。



6. 量化误差如何影响模型精度

单个参数产生的量化误差通常非常有限。

例如:

原始值:

复制代码
0.523

量化后:

复制代码
0.520

两者之间:

复制代码
误差 = 0.003

对于单个数据点而言,这种差异通常不会产生明显影响。

但是,神经网络具有以下特点:

  • 参数数量巨大
  • 网络层级复杂
  • 特征逐层传递

因此,局部量化误差会随着网络计算不断传播。

典型传播过程:

markdown 复制代码
输入量化误差

      ↓

卷积计算

      ↓

激活输出变化

      ↓

下一层输入变化

      ↓

最终预测变化

6.1 分类任务中的影响

对于分类模型:

量化误差可能导致:

复制代码
类别概率变化

例如:

量化前:

makefile 复制代码
Cat: 0.62

Dog: 0.35

量化后:

makefile 复制代码
Cat: 0.56

Dog: 0.41

虽然预测结果可能保持不变,但是置信度会发生变化。

当两个类别概率接近时,量化误差可能导致分类结果发生改变。


6.2 目标检测任务中的影响

对于目标检测模型:

量化误差可能影响:

  • 分类置信度
  • 边界框回归结果
  • NMS 前后的候选框数量

例如:

量化前:

csharp 复制代码
object confidence:

0.52

量化后:

csharp 复制代码
object confidence:

0.48

如果阈值设置为:

复制代码
0.5

那么:

量化前:

复制代码
保留目标

量化后:

复制代码
被过滤

因此,小幅数值变化可能影响最终检测结果。


6.3 语义分割任务中的影响

对于语义分割模型:

量化误差可能影响:

  • 像素分类结果
  • 边界区域预测
  • 小目标区域识别

尤其对于:

  • 小目标
  • 边缘区域
  • 类别间差异较小区域

量化误差带来的影响可能更加明显。



7. 如何理解量化损失

模型量化中的损失,本质上来自两个方面:


7.1 表示精度降低

FP32:

复制代码
连续高精度空间

INT8:

复制代码
有限离散空间

由于:

复制代码
可表示的数据数量减少

因此:

复制代码
部分细节信息无法完全保留

这属于量化过程中的固有损失。


7.2 数据范围限制

除了表示精度之外,数据范围也是影响量化效果的重要因素。

如果范围设置过小:

markdown 复制代码
数据覆盖不足

      ↓

截断误差增加

如果范围设置过大:

markdown 复制代码
Scale 增大

      ↓

舍入误差增加

因此,量化过程的核心问题是:

在有限整数表示能力下,尽可能保留模型中的有效信息。


8. 总结

模型量化产生精度损失,是由浮点空间向整数空间转换这一过程决定的。

FP32 可以表示连续、高精度的数据,而 INT8 只能表示有限数量的离散整数。因此,在两个空间之间建立映射关系时,必然会产生一定的信息损失。

量化误差主要包括两类:

舍入误差

由于浮点值经过 Scale 映射后通常无法得到整数结果,需要进行取整,因此产生舍入误差。

特点:

  • 单次误差通常较小
  • 与 Scale 大小相关
  • 多层传播后可能影响模型输出

截断误差

由于数据超过量化范围,被限制到最大或最小可表示值,因此产生截断误差。

特点:

  • 误差通常较大
  • 与数据范围选择密切相关
  • 主要影响异常值和极端激活值

从本质上看,量化损失来源于:

markdown 复制代码
更高精度表示

        ↓

有限低比特表示

这个转换过程中的信息压缩。

相关推荐
2401_862880821 小时前
数据结构 --- 栈
c语言·数据结构·算法
致Great2 小时前
Qwen3.8-27B 接入 DSH 全流程实测:写代码、跑长任务,都没问题
算法
Tisfy2 小时前
LeetCode 3471.找出最大的几近缺失整数:三种情况判断
算法·leetcode·题解·分类讨论
linux-hzh3 小时前
百日算法修炼 · Day 12
算法·深度优先
额额额对了3 小时前
数据结构:二叉树
c语言·数据结构·算法
iNeuOS工业互联网3 小时前
iNeuOS_Vision_视觉分析,增加SAM3模型对实例分割和目标检测AI自动标注图片样本功能
人工智能·算法·目标检测
qeen873 小时前
【数据结构】红黑树的算法原理解析与实现
开发语言·数据结构·c++·算法·红黑树
码匠许师傅4 小时前
【C++ 面试真题】20. 聊聊 C++ 的标准库常用算法
c++·算法·面试
aqiu1111114 小时前
【算法刷题】蓝桥杯:0星际争霸(大数比较 + 多关键字自定义排序)
算法·排序·自定义排序