浮点数及其在 AI 中的应用

SEO教程2025-09-0230
    正在检查是否收录...

浮点数

参考文档:
计算机中的定点数与浮点数
量化感知训练(Quantization-aware-training)探索-从原理到实践
Wikipedia IEEE 754
FP8, BF16, and INT8: How Low-Precision Formats Are Revolutionizing Deep Learning Throughput
A Survey of Quantization Methods for Efficient Neural Network Inference

小数在计算机系统中的表示

在计算机发展的过程中出现了两种小数的表示形式:定点数与浮点数,但是这两种表示形式并不能与数学里的实数划等号,实数的范围是无限的,而作为计算机对数值的存储格式,定点数和浮点数是有限的,二者都是对实数集有限并且离散的近似。

定点格式通过固定小数点的预设位置来定义数值,而浮点格式则采用类似科学计数法的原理,通过指数域动态调整小数点的位置,从而在广泛数值范围内取得平衡。值得注意的是,这两种格式并不仅限于表示小数,通过特定的位模式配置,它们同样能够精确且有效地表示整数。

定点数

在1940年代计算机诞生初期,普通采用定点数进行小数运算。定点数指小数点的位置在存储时是预先

约定固定

的,无需用物理比特来存储小数点信息,因此节省了存储空间。具体而言,一个数值会被当作一个整体的二进制数来存储。其实际数值的确定,依赖于我们如何解释这个二进制序列:我们

约定

它的某一位是小数点所在的位置,该位之前的部分是整数位,之后的部分是小数位。计算机中的定点数主要有两种类型(例如纯整数型、纯小数型或Q格式等)。

十进制数 25.125 可用定点数表示如下:

  • 整数部分 25 的二进制为 11001
  • 小数部分 0.125 的二进制为 .001
  • 合并后得 11001.001,即对应十进制的 25.125

定点数的表示范围和精度在设计时即已固定。其可表示的数值之间的最小间隔为精度,该精度不可动态调整,表示范围也受限于整数部分的位宽。因此,定点数难以同时表达极大或极小的数值。

例如,假设使用16位定点数,并约定低8位为小数部分。则:

  • 其能表示的最大值约为 \(2^8 - 2^{-8} = 255.996\),
  • 最小精度为 \(2^{-8} \approx 0.004\)。
  • 对于超出此范围的数(如 10000.0 或 0.0001),该格式既无法表示,也无法保证有效精度。

浮点数

针对定点数表示范围和精度固定的问题,计算机科学家提出了浮点数表示法。所谓“浮点”,是指小数点的位置可以根据数值大小动态调整,而不再固定于某一位置。该表示方法类似于科学计数法,将一个数分解为尾数(有效数字)和指数(表示数量级)两部分,从而实现在有限位数内同时表达极大或极小的数值,并保持相对稳定的有效位数。

例如,十进制数 25.125 在十进制浮点表示中可写为 \(2.5125 \times 10^{1}\),其二进制形式也遵循类似结构,该表示法将数值分解为符号、指数和尾数三个部分,分别存储,从而在有限位宽下兼具宽广的表示范围和灵活的精度控制。

按照工业界标准 IEEE 754 中规定的数据格式,浮点数由符号位(S,Sign),阶码位(E,Exponent)和尾数位(F,Fraction)三个部分构成。

IEEE 754 标准

格式名称 总位数 符号位 阶码位数 尾数位数 阶码偏置值
Binary16 16 bit 1 5 10 15
Binary32 32 bit 1 8 23 127
Binary64 64 bit 1 11 52 1023
Binary128 128 bit 1 15 112 16383
Binary256 256 bit 1 19 236 262143

为了解决不同计算机厂商采用浮点数表示方法不一致所导致的程序移植困难问题——同一段计算程序在不同机器上可能产生不同结果——IEEE 微处理器标准委员会(Microprocessor Standards Committee)于1985年正式发布了 IEEE 754-1985 浮点数算术标准。该标准历经多次修订与更新,目前最新的版本为2019年发布的 IEEE 754-2019。

IEEE 754 标准定义了五种基本格式,这些格式以其数值基数及其交换编码中使用的位数来命名。二进制浮点数有三种基本格式(编码长度分别为 32 位、64 位或 128 位),而十进制浮点数则有两种基本格式(编码长度分别为 64 位或 128 位)。其中 binary32(FP32) 和 binary64(FP64) 格式分别对应 IEEE 754-1985 标准中的单精度与双精度格式。符合标准的实现方案必须至少完整支持其中一种基本格式。

IEEE 754 标准规定了三个部分,分别是符号位、阶码位和尾数位,下面是 32 位浮点数示例:

浮点数及其在 AI 中的应用

  1. 符号位 (Sign bit - S):

  • 定义:

    表示数字的正负
  • 长度:

    通常为 1 位
  • 规则:

    0 代表正数 (+),1 代表负数 (-)
  1. 指数位 (Exponent bits - E):

  • 定义:

    决定数值的大小范围(量级),即小数点可以“浮动”的范围。它存储的不是实际指数,而是一个经过“偏置 (Bias)”处理的值
  • 长度:

    不同格式位数不同(例如 float32 是 8 位,float16 是 5 位)
  • 规则:

    存储的值 = 实际指数 + 偏置值 (Bias)。偏置值是一个预设的正整数(如 float32 中是 127),目的是让存储的指数始终为非负数,便于硬件比较。实际指数 = 存储值 - Bias。特殊的指数位模式(全0或全1)用于表示特殊值
  1. 尾数位 (Mantissa bits - F):

  • 定义:

    决定数值的精度(有效数字)。它存储的是有效数字的小数部分。
  • 长度:

    不同格式位数不同(例如 float32 是 23 位,float16 是 10 位)
  • 规则:

    对于“规格化 (normalized)”的数,其形式通常为(二进制)。为了节省空间,整数部分的 '1' 是

    隐含

    的,不实际存储。尾数位 F 存储的是小数点后的部分。因此,有效精度(Significand)等于 1 (隐含位) + 尾数位数。例如,float32 有 23 个尾数位,提供 24 位精度。

规格化数与非规格化数

在 IEEE 754 标准中规定了两种数值表示方式,分别是

规格化数(Normalized Numbers)

非规格化数(Denormalized Numbers)

,规格化数是最标准且最常用的表示形式,其特点是指数位 E 不全为 0 也不全为 1,并且其尾数部分隐含一个前导

‘1’

。该表示方法能够以最高效的方式表示绝大多数的实数。

以单精度 Binary32(FP32)为例,其阶码占 8 位,尾数部分占 23 位。由于规格化数的尾数隐含了最高位的 ‘1’,其实际有效精度达到了 24 位。然而,这种设计也意味着规格化数的尾数最小值始终为 1.0,因此无法表示数值 0。

更重要的是,规格化数在零附近存在一个

下溢间隙

:最小的正规格化数为 \(1.0 \times 2^{-126}\),而比它更小的正数(在 0 与 \(1.0 \times 2^{-126}\) 之间)无法用规格化形式表示。如果没有其他机制,计算结果若落入此区间,将因下溢而被舍入至零,导致精度突然丢失。非规格化数的设计正是为了填补这个间隙,实现从数值到零的平滑过渡,该表示形式的特点是

指数位全为 0

,且

尾数非零

,并且尾数部分

不再隐含 ‘1’

  • 规格化数:

    \(Value = (-1)^S \times (1+F) \times 2^{E-Bias}\)

    • S:符号位(0 表示正,1 表示负)
    • F:尾数位
    • E:指数位存储的值
    • Bias:指数偏置值
  • 非规格化数:

    \(Value = (-1)^S \times (0 + F) \times 2 ^{(-Bais + 1 )}\)

    • S:符号位
    • F:尾数位
    • Bais:指数偏置值

上面出现了一个新的名词:偏置值(Bais),这是因为如果直接用

补码

表示指数,在进行两个浮点数比较时,需要硬件支持补码的比较,电路更复杂。因此 IEEE 754 使用在阶码位使用一个

无符号整数

,但实际真正的阶码要减去一个

偏置(Bais)

$Bais = 2^{bit_E-1} - 1$

例如,对于 Binary32 格式来说,其阶码为 8 位,Bias 为 \(2^{8-1}-1=127\),则实际阶码位存储的值为实际指数 + 127。

  • 存储值 0 → 实际指数 = -127
  • 存储值 127 → 实际指数 = 0
  • 存储值 255 → 特殊值(Inf/NaN)

这样的设计能够

简化比较

,这也是该设计的核心目的,通过

Bias

,所有合法的指数(包括负指数)存入指数位后都变成非负整数。这使得硬件可以直接按无符号整数比较指数位来判断哪个浮点数的范围更大,极大简化了比较逻辑。 此时能够

无需额外的符号位

来表示指数的正负。并且通过

预留特殊值

,将指数位的全 0 和全 1 模式保留,用于明确表示 0、无穷大、NaN(非数字)等特殊情况。

特殊值的表示

IEEE 754 标准定义了特殊的位模式来表示这几个重要的值,主要利用了指数位的保留模式(全0 和 全1):

  1. 零 (Zero):

  • 指数位 (E): 全 0
  • 尾数位 (F): 全 0
  • 符号位 (S): S=0 表示 +0,S=1 表示 -0。区分正负零有助于处理涉及无穷大或下溢时的符号问题
  1. 无穷大 (Infinity / Inf):

  • 指数位 (E): 全 1
  • 尾数位 (F): 全 0
  • 符号位 (S): S=0 表示 +Infinity,S=1 表示 -Infinity。通常由上溢(结果超出最大可表示范围)或除以零产生
  1. 非数字 (Not a Number / NaN):

  • 指数位 (E): 全 1
  • 尾数位 (F): 非零 (任何不全是0的模式)
  • 符号位 (S): 通常无意义,但存在。NaN 用于表示无效操作的结果,如 0/0sqrt(-1)Inf - Inf 等NaN 具有传染性,任何涉及 NaN 的运算结果通常还是 NaN
类型 符号位 S (1 位) 指数位 E (8 位) 尾数位 F (23 位) 含义说明
+0 0 0000 0000 000…000 正零
-0 1 0000 0000 000…000 负零
+∞ 0 1111 1111 000…000 正无穷大
-∞ 1 1111 1111 000…000 负无穷大
NaN 0 或 1 1111 1111 非零(如 100…0) 非数字 NaN

其他浮点数格式

在 AI 模型的训练与推理过程中,需要大量浮点数来存储和计算模型参数。以

FP32

(32 位浮点数)为例,每 GiB 内存可容纳约

2.68 亿个数值

。若模型规模达到

175B(1750 亿)参数

,仅权重部分就需要约

653 GiB

的存储空间,这已经远超单卡 GPU 的显存容量。为了降低存储与计算开销,各大厂商纷纷提出了多种

IEEE 754 标准之外的低精度格式

,如

BF16、FP8、FP4

等,用以在精度与效率之间取得平衡。

BF16

是谷歌为深度学习设计的 16 位浮点格式,它以牺牲部分精度为代价保留了与 FP32 相同的数值范围,从而在训练中兼顾了内存效率和稳定性。

FP8(如 E4M3、E5M2)

在存储和计算效率上优于 BF16 和 FP16,常用于权重、激活和梯度张量,在缩放与裁剪技术支持下已能支撑大规模模型的训练与推理。**FP4 **则以极低的精度换取极致压缩,主要用于推理阶段的极限优化或混合精度训练中的部分张量表示。

UE8M0

前一阵出了一个挺火的新闻,DeepSeek 宣称引入

UE8M0

格式支持下一代国产芯片。

浮点数及其在 AI 中的应用
通过对 DeepSeek-v3.1 模型配置文件的查阅,可以确认该架构确实引入了此类数据格式。不过,该格式并不用于基础的数据表示,而是专门用于缩放因子的存储与计算。

 { ... ... ... "quantization_config": { "activation_scheme": "dynamic", "fmt": "e4m3", "quant_method": "fp8", "weight_block_size": [ 128, 128 ], "scale_fmt": "ue8m0" }, ... ... ... } 

UE8M0

是一种无符号的 FP8 格式,其结构由

8 位指数位

0 位尾数位

构成。该格式通过完全舍弃尾数精度,换取了极大的数值表示范围,因此属于一种专用的指数表示格式。UE8M0 并非用于通用计算,而是一种高效的缩放因子表示工具。在该格式中,由于尾数位为 0,所有数值都是严格的 2 的指数倍(即 \(2^E\)),数值分布呈离散的指数增长特性。相比传统浮点数,UE8M0 放弃了精细的数值表示能力,而专注于覆盖极大的动态范围。

主要特性

  1. 无尾数位

    :UE8M0 的数值仅由指数决定,每个编码对应一个精确的 2 的幂次值。
  2. 数值离散性

    :由于没有尾数,数值之间的间隔随着指数增大而呈指数增长。例如,指数为 1 的值为 2,指数为 2 的值为 4,指数为 10 的值为 1024,数值间距随着指数增大而逐渐加大。
  3. 精度低

    :该格式无法表示除 2 的幂次之外的数值,数值精度非常有限。

NVIDIA 在 Blackwell 架构中使用了 MX microscaling 技术,即将张量划分为小块,并为每个块分配独立缩放因子。这些缩放因子的编码采用了

E8M0(8 位指数、0 位尾数)

格式,它是 OCP 标准中定义的一种无尾数浮点指数格式,适合作为幂次缩放因子使用。

OCP 对于该种格式的定义如下:

浮点数及其在 AI 中的应用
浮点数及其在 AI 中的应用
尽管 NVIDIA 官方将该数据类型命名为

E8M0

,而 DeepSeek 称之为

UE8M0

,但两者是否有所区别?

我个人认为

答案是否定的。NVIDIA 所使用的 E8M0 格式本身并不包含符号位,而 DeepSeek 命名中的 “U” 即代表“无符号”(Unsigned),因此这两个名称

我认为

实际指向同一种数据格式。不过,由于目前未能找到 DeepSeek 官方对 UE8M0 的明确定义,在缺乏关键细节(如

偏置值具体数值、无穷大及非数字的表示方式

等)的情况下,我暂时无法完全断定二者在所有实现细节上完全一致。唯有在获得更完整的格式定义之后,才能做出最终结论。

浮点数精度对深度学习训练和推理的影响

降低数值表示精度一直是加速深度学习训练与推理的重要手段。训练中常用的浮点类型包括

IEEE FP32 单精度

[1]、

NVIDIA 的 TF32

IEEE FP16 半精度

以及

BFloat16

[2]。然而,这些格式在许多实际应用中仍难以兼顾计算效率与结果质量。在推理阶段,

定点 INT8

是较为流行的选择,但在部分场景中难以满足精度需求。为此,

NVIDIA 提出了 FP8 格式

,它能够显著降低存储与带宽压力,并提升训练和推理速度。但与此同时,FP8 的数值精度和表示范围有限,且尚未形成通用标准,因而在兼容性上存在局限。

NVIDIA FP8 的两种格式:E4M3 与 E5M2

这里以 NVIDIA FP8 的

E4M3

(4 位指数 + 3 位尾数)和

E5M2

(5 位指数 + 2 位尾数)两种格式为例,介绍一下不同精度对训练与推理的影响。FP8格式的设计遵循

实用主义

原则:首先,由于深度学习模型中权重/激活值与梯度具有不同的动态范围需求,这直接催生了

两种编码格式

(E4M3和E5M2)的并存;其次,为最大限度利用有限位宽,采用基于软件的每张量缩放因子方案,其

灵活性

远胜于固定的指数偏置硬件方案;最后,该标准仅精确定义数据存储的二进制格式,而将具体转换实现细节留给开发人员,从而在保证兼容性的同时维持了实现的自由度。

FP8 E4M3 格式

E4M3 格式并未严格遵循 IEEE 754 的设计规则。在该格式下,指数位

不再预留全 1 表示无穷大

,而仅保留一个特殊编码用于表示 NaN。这一修改取消了无穷大的表示方式,从而将原本分配给无穷大的编码扩展到有限数值范围,使该格式能够覆盖更大的数值区间。例如,它可以表示 240、256、288、320、352、384、416 和 448 等较大的数值。需要注意的是,这些数值在表示上是

离散

的,并非连续覆盖,这是由于浮点数在数值越大时,尾数部分能提供的有效精度越低所导致的。

在该格式下:

  • 规格化数:

    \(Value = (-1)^S \times (1+F) \times 2^{E-Bias}\)

    • S:符号位(0 表示正,1 表示负)
    • F:尾数位
    • E:指数位存储的值,

      不再预留全 1 表示无穷大

    • Bias:指数偏置值,\(2^{bit_E-1}-1 = 7\)
  • 非规格化数:

    \(Value = (-1)^S \times (0 + F) \times 2 ^{(-Bais + 1 )}\)

    • S:符号位
    • F:尾数位
    • Bais:指数偏置值
尾数 (M) 二进制值 1 + M 最终数值 \((1+M) \times 2 ^{1111_2 - Bias}\)
000 0.0 1.0 1.0 * 256 = 256
001 0.125 1.125 1.125 * 256 = 288
010 0.25 1.25 1.25 * 256 = 320
011 0.375 1.375 1.375 * 256 = 352
100 0.5 1.5 1.5 * 256 = 384
101 0.625 1.625 1.625 * 256 = 416
110 0.75 1.75 1.75 * 256 = 448
111 0.875 1.875 1.875 * 256 = 480【这个编码被用于表示NaN】

在这里会产生一个问题:如果希望表示 260,但 FP8 E4M3 并不能精确表示该值,它只能将其近似为 256,从而产生较大的误差。因此,在实际计算中,首先需要对原始数据进行缩放,使数值落在 FP8 E4M3 可表示的范围内,从而尽量减少量化误差。

目标:将某组数据核心分布映射到高精度范围 [-16.0, 16.0]

  1. 计算缩放因子 (Scale)

    • 分析张量,

      忽略极端离群值

      ,找到能代表其核心分布的绝对值最大值 robust_max。例如,通过统计 99.9% 分位数得到 robust_max = 20.0
    • 缩放因子 scale = (目标高精度范围上限) / robust_max = 16.0 / 20.0 = 0.8
  2. 缩放张量

    • 将原始张量乘以该缩放因子:W_scaled = W * 0.8
    • 现在,张量中至少 99.9% 的数值被压缩到了 [-16.0, 16.0] 的目标高精度范围内。
  3. 转换为 E4M3

    • W_scaled 转换为 E4M3 格式。
    • 此时,绝大多数数值落在 E4M3 的

      高精度区

      (如指数为 3、4、5 的 binade),其

      绝对间隔低至 0.25 ~ 1.0

      ,从而实现了高精度转换。

FP8 E5M2 格式

FP8 E5M2 格式遵循 IEEE 754 的设计规则,其结构与其他浮点格式类似,但使用 5 位指数和 2 位尾数,使其能够表示更大的数值范围,同时保留有限的精度。在该格式下,依旧可以表示无穷大和非数(NaN)。

在该格式下:

  • 规格化数:

    \(Value = (-1)^S \times (1+F) \times 2^{E-Bias}\)

    • S:符号位(0 表示正,1 表示负)
    • F:尾数位
    • E:指数位存储的值
    • Bias:指数偏置值,\(2^{bit_E-1}-1 = 7\)
  • 非规格化数:

    \(Value = (-1)^S \times (0 + F) \times 2 ^{(-Bais + 1 )}\)

    • S:符号位
    • F:尾数位
    • Bais:指数偏置值

与 E4M3 相比,E5M2 在表示结构上有相似之处,也存在一些差异,E5M2 指数位更多(5 位 vs 4 位),尾数位更少(2 位 vs 3 位),这使得 E5M2 可以表示更大的数值范围,但精度略低。由于这一特点,E5M2 更适合动态范围较大、对精度要求不是非常高的场景。FP8 编码的推荐使用方式是:

E4M3 用于权重和激活张量

E5M2 用于梯度张量

。虽然有些网络仅使用 E4M3 或 E5M2 就可以完成训练,但也存在需要同时使用这两种类型的网络(或者必须将大量张量保持为 FP8)。这一点与文献 [3,4] 的结论一致:在推理和训练的前向传播中使用 E4M3 变体,而在训练的反向传播中梯度使用 E5M2 变体。

数据精度对训练的影响

本小节以论文《FP8 Formats for Deep Learning》[4] 中的实验为例展开说明。该研究以 FP16 或 BF16 格式的训练结果作为精度基准,并在实验过程中始终保持模型架构、权重初始化方式及优化器超参数不变。实验重点关注卷积和矩阵乘法等计算密集型操作(在文中统称为类GEMM操作)。除非特别说明,输入至GEMM操作的张量——包括激活值、权重和激活梯度——均被裁剪至 FP8 格式可表示的数值范围内;输出张量则仍保留较高精度,以供后续如非线性激活或归一化等操作使用。

文章首先在图像分类任务上对FP8格式进行了评估,实验基于 ImageNet ILSVRC12 数据集进行。如下表所示,除DeiT模型基于 Transformer 架构外,其余模型均为卷积神经网络(CNN)。结果表明,在使用 FP8 格式进行训练后,所得识别精度与使用 FP16 或 BF16 格式的基准结果相比均未出现显著下降,准确率差异保持在多次训练运行固有波动范围之内。

浮点数及其在 AI 中的应用
在语言翻译任务中,该研究测试了基于 Transformer 和基于 LSTM 的循环 GNMT 神经网络。模型在 WMT 2016 英语→德语数据集上进行训练,并在 newstest2014 测试集上采用 sacreBLEU 进行评估。结果表明,使用 FP8 格式所得的翻译质量与 FP16 或 BF16 基准结果相比未出现显著下降,其性能差异完全处于多次训练运行固有的波动范围之内。

浮点数及其在 AI 中的应用
在观察完语言翻译模型在不同数据精度的比较后,文章深入了训练内部,通过对比训练损(困惑度),证明 FP8 格式能在训练过程中保持稳定,下表中 Transformer 类模型在 Wikipedia 数据集上进行训练,GPT 类模型在 The Pile 数据集的一个变体上进行训练。

浮点数及其在 AI 中的应用
与在图像分类测试中的观察结果一致,FP8 训练的损失结果相对 FP16 或者 BF 16 数据格式并未出现明显下降。整个的损失曲线如下图所示。

浮点数及其在 AI 中的应用

数据精度对推理的影响

如果在训练阶段直接使用 FP8 格式,那么在推理阶段同样采用 FP8 格式将大大简化部署流程。这一点与传统流程形成对比:通常情况下,模型使用 FP16 或 FP32 进行训练,而在推理时转换为 INT8,需要在训练后进行量化校准(PTQ,post-training quantization),或者在训练过程中结合量化感知技术(QAT,quantization-aware training)才能保证模型的精度。然而,即使采用量化感知训练,部分 INT8 量化模型的精度仍可能无法完全恢复到使用浮点数训练时的水平。

文章对 16 位浮点训练的模型进行了 FP8 训练后量化(PTQ)评估。结果显示,FP8 PTQ 在 BERT 和 GPT 模型上均显著优于 INT8 量化,能够有效保持模型精度。

浮点数及其在 AI 中的应用

使用低精度数据格式对深度学习的影响

低精度格式(如FP8、BF16和INT8)在深度学习中日益流行的主要原因是其能够显著提升吞吐量。吞吐量是指模型在单位时间内能处理的操作数量。通过降低计算中所用数据的位宽,这些格式可大幅提高吞吐效率并减少计算开销。

  • 内存使用效率

    • 更小的内存占用:采用FP8或INT8等低精度格式,可减少计算过程中存储模型参数和中间值所需的内存占用。这一特性对于训练大规模模型尤为有利,因为它能够在有限的内存空间中容纳更多参数,从而减少对速度较慢的内存访问的依赖
    • 提升数据密度:采用更小的数据类型后,GPU内存中可用于存储模型和训练数据的比例更高,从而在内存受限的应用场景中实现更好的性能表现。
  • 计算速度得到提升

    • 减少的计算时间:由于使用的比特数更少,低精度格式(如FP16和INT8)执行相同运算所需的时钟周期比FP32更短。例如,FP16与INT8操作能够比FP32更高效地并行执行,从而显著提升计算速度。
    • 专用硬件支持:现代GPU(如NVIDIA A100)配备了专门的Tensor Core,旨在加速FP16、BF16和INT8等低精度格式的运算,使其天然适合深度学习模型的训练。

高低精度数据转换——量化

过去十年,深度学习迅速发展,尤其是大语言模型的兴起,不仅吸引了更多研究人员的投入,也使更多人从 AI 的进步中受益。然而,随着模型规模不断扩大,现有硬件已难以高效支撑超大参数模型的运行,尤其是在边缘计算、自动驾驶等对资源和实时性要求严苛的场景中,挑战更为突出。因此,必须通过

降低模型规模和计算开销

来缓解这一问题,而量化正是其中最关键的手段之一。

在神经网络中,权重和输入通常会经过归一化处理,使得数值范围相对较小;同时,激活函数在传播过程中会起到平滑作用,减弱了量化误差的累积影响。更重要的是,大多数神经网络任务(如分类)最终只关心不同类别之间的相对概率,而不是绝对数值大小,只要正确类别的概率高于其他类别即可。因此,

量化往往对大模型精度的影响有限

常用量化方法

均匀量化

均匀量化

(Uniform Quantization)是一种常见的量化方式,其核心思想是将连续的实数区间按照等间隔划分,再将每个浮点数值映射到离它最近的量化点。换句话说,均匀量化的步长(scale)在整个区间内保持不变,因此实现简单、计算高效。

$Q(r) = Int(\frac{r}{S}) - Z )$
$\tilde{r} = S(Q(r) + Z)$

上面两个公式分别对应均匀量化公式和反量化公式。其中,\(Q\) 表示量化函数,\(r\) 为输入值(可以是激活值或权重),\(S\) 为缩放因子,\(Z\) 为零点,\(Int(\cdot)\) 表示将输入映射到整数域的操作。需要注意的是,反量化得到的 \(\tilde{r}\) 由于经历了取整或舍入过程,通常不会与原始值 \(r\) 完全一致。

在均匀量化中有两个比较重要的量化方法,分别是

对称量化

以及

非对称量化。

对称量化与非对称量化

非对称量化

中,缩放因子\(S\)的定义为:

$S = \frac{\beta-\alpha}{2^b -1}$

其中\([\alpha, \beta]\)表示裁剪范围,\(b\)是量化位宽(若目标类型是 INT8,则\(b = 8\))。通常情况下,会直接选用原始数据中的最小值和最大值分别作为\(\alpha\)和\(\beta\),即\(\alpha = r_{min}, \beta = r_{max}\),此时往往满足\(- \alpha \not= \beta\)。

相比之下,

对称量化

要求区间关于零点,即\(\left | \alpha \right| = \left| \beta \right|\),因此通常会选用

$-\alpha = \beta = max(\left| r_{max} \right|, \left| r_{min} \right|)$

由此可见,非对称量化的映射区间通常要比对称量化更为紧凑,并且在对称量化中,\(Z\)天然等于零,这在一定程度上减少了计算开销。

在对称量化中,缩放因子\(S\)通常有两种选择方式:

  • 全范围(full range)

    • \(S=\frac{2max⁡(∣r∣)} {2n−1}\)(采用向下取整的舍入方式),此时 INT8 的完整区间 [-128, 127] 都被利用
  • 受限范围(restricted range)

    • \(S = \frac{\max(|r|)}{2^{n-1}-1}\),只使用区间 [-127, 127]

受限范围量化是旧硬件兼容性的历史遗留方案,而现代硬件已全面支持精度更高的全范围量化,其通过最大化利用数值表示空间显著降低量化误差。

对称量化采用对称范围进行裁剪分区,其优势在于实现更简便。然而,当数值分布存在偏移且非对称时,这种方法的效果就显得不够理想。针对此类情况,非对称量化成为更理想的选择。

非均匀量化

与均匀量化相比,非均匀量化在固定位宽下往往能够实现更高的精度。其核心优势在于能够依据数据分布特性自适应地调整量化区间与量化步长,从而更有效地捕捉数值分布特征。非均匀量化会根据数值的密度进行动态分配:在数值分布密集的区域(如均值附近),设置较小的量化步长和更多的量化级别,以提高表示精度;而在分布稀疏的区域(如尾部),则采用较大的步长,以节省比特资源。这种“按需分配”的机制可在总比特数有限的前提下降低整体量化误差。

许多非均匀量化方法专门针对神经网络中常见的权重和激活分布进行设计,这类分布通常呈现钟形(如正态分布)并带有长尾特性。其中一种典型的方案是对数量化,其量化步长和级别呈指数增长而非线性增加,从而更好地匹配数值的动态范围,尤其适用于具有指数级数值变化范围的场景。

由于量化步长并非固定,因此计算过程中需要频繁进行非均匀的缩放,这与通用计算硬件(如GPU和CPU)高度并行化、规整化的计算模式不相兼容,导致计算效率低下。所以尽管均匀量化在理论精度上可能不如非均匀量化,但其能够最大程度匹配现有计算硬件的计算模式,最终成为实际工业部署中的主流方案。

缩放范围校准方法:动态量化与静态量化

量化方法的另一个重要区别在于确定裁剪范围的时机。权重参数的裁剪范围可以静态计算,因为在大多数情况下这些参数在推理过程中是固定的。然而,激活着会随着每个输入样本变化而变化吗,因此,激活值的量化存在两种方法:动态量化与静态量化。

在动态量化中,该范围会在运行时针对每个激活映射动态计算。这种方法需要实时计算信号的统计量(最小值、最大值、百分位数等),可能带来较高的计算开销。然而,动态量化通常能实现更高的精度,因为每个输入信号的范围都是被精确计算的。

另一种方法是静态量化,其裁剪范围是预先计算且在推理过程中保持固定的。这种方法不会增加任何计算开销,但通常会导致精度低于动态量化。

量化微调方法

在模型参数被量化之后,通常需要进行调整以恢复精度。这个过程有两种主要方式:

  1. 重新训练模型

    —— 即

    量化感知训练(Quantization-Aware Training, QAT)

  2. 不重新训练

    —— 即

    训练后量化(Post-Training Quantization, PTQ)

量化感知训练

当我们把一个已经训练好的浮点模型(如 FP32)直接量化成低比特(如 INT8)时,模型参数和中间激活值会发生

离散化误差

,导致精度下降。这种情况在复杂任务或低比特量化(INT4、二值化)中尤为严重。

量化感知训练

(Quantization-Aware Training, QAT)是一种在训练过程中引入量化约束的技术,使模型可以主动适应量化带来的精度损失,从而显著提升量化后的最终性能。

量化感知的一般阶段如下:

  • 准备阶段

    :从一个已在高精度数据格式(如 FP32)下训练完成的模型开始,该模型作为 baseline 模型。
  • 插入伪量化节点并微调

    :在 baseline 模型中引入伪量化节点,在训练数据集上对模型进行微调。伪量化节点在前向传播时会模拟推理阶段的量化行为,从而让模型在训练中逐步适应量化噪声。
  • 量化参数学习

    :在微调过程中,伪量化节点会根据数据分布动态更新并保存量化所需的关键参数(如 scale、zero-point)。

伪量化(Pseudo Quantization)

本质上是一次量化操作与一次反量化操作的组合。其核心目的是在模型训练过程中模拟推理时量化操作所引入的舍入误差,并将这种误差视为一种训练噪声,从而使网络参数逐步适应量化带来的数值扰动。通过这种方式,模型能够在训练阶段提前感知并学习补偿量化所造成的信息损失,最终显著降低模型在实际量化部署后的精度下降。

伪量化的标准运算流程主要包括裁剪、缩放、舍入和反量化四个步骤:

  1. 裁剪(Clip)

    :将输入值限制在预设的量化区间内:\(x_{\text{clip}} = \min(\max(x, x_{\text{min}}), x_{\text{max}})\)
  2. 缩放(Scale)

    :将裁剪后的值映射到目标整型范围:\(x_{\text{scaled}} = \dfrac{x_{\text{clip}}}{s}\)其中缩放因子\(s\)通常定义为\(s = \dfrac{x_{\text{max}} - x_{\text{min}}}{2^b - 1}\),\(b\)表示量化的目标位宽
  3. 舍入(Round)

    :对缩放后的值进行四舍五入取整:\(x_{\text{round}} = \text{round}(x_{\text{scaled}})\)
  4. 反量化(Dequantize)

    :将离散整数值重新映射回原始数据范围:\(x_{q} = x_{\text{round}} \times s\)

整理流程可以整合成如下表达式:\(x_{q} = round(\frac{clip(x, x_{min}, x_{max})}{s} \times s)\)

训练后量化

训练后量化

就是指在模型训练完成后,

不需要重新训练

,直接对模型进行量化处理。PTQ 的优点在于量化速度快,几乎没有额外开销,同时不依赖大量训练数据,即使数据有限或无标签的情况下也能使用;但其缺点是精度往往低于 QAT,尤其在低比特量化时更为明显。

一个典型的 PTQ 步骤包括:

  1. 获取训练好的浮点模型(通常是 FP32)

  2. 收集少量数据(用于校准):这些数据用来统计激活值的范围(min/max 或分布),从而确定量化的缩放因子(scale)和零点(zero point)。

    • 权重的量化参数可以直接从权重本身的范围计算
    • 激活的量化参数通常需要少量数据来做“校准”
  3. 应用量化公式:把 FP32 的权重和激活映射到低比特整数空间(如 INT8)

  4. 生成量化后的模型,在推理时用整数计算替代浮点计算

浮点数及其在 AI 中的应用

[1]: Dusan Stosic and Paulius Micikevicius. Accelerating ai training with nvidia tf32 tensor cores, 2021. https://
developer.nvidia.com/blog/accelerating-ai-training-with-tf32-tensor-cores/, Accessed on 2022-09-4.

[2]: Dhiraj D. Kalamkar, Dheevatsa Mudigere, Naveen Mellempudi, Dipankar Das, Kunal Banerjee, Sasikanth
Avancha, Dharma Teja Vooturi, Nataraj Jammalamadaka, Jianyu Huang, Hector Yuen, Jiyan Yang, Jongsoo Park,
Alexander Heinecke, Evangelos Georganas, Sudarshan Srinivasan, Abhisek Kundu, Misha Smelyanskiy, Bharat
Kaul, and Pradeep Dubey. A study of BFLOAT16 for deep learning training. arxiv, abs/1905.12322, 2019.

[3]: Xiao Sun, Jungwook Choi, Chia-Yu Chen, Naigang Wang, Swagath Venkataramani, Vijayalakshmi (Viji) Srini-
vasan, Xiaodong Cui, Wei Zhang, and Kailash Gopalakrishnan. Hybrid 8-bit floating point (hfp8) training and
inference for deep neural networks. In H. Wallach, H. Larochelle, A. Beygelzimer, F. d'Alché-Buc, E. Fox, and
R. Garnett, editors, Advances in Neural Information Processing Systems, volume 32. Curran Associates, Inc.,
2019.

[4]: Badreddine Noune, Philip Jones, Daniel Justus, Dominic Masters, and Carlo Luschi. 8-bit numerical formats for
deep neural networks. arXiv preprint arXiv:2206.02915, 2022

[5]: Paulius Micikevicius, Dusan Stosic, Neil Burgess, Marius Cornea, Pradeep Dubey, Richard Grisenthwaite, Sangwon Ha, Alexander Heinecke, Patrick Judd, John Kamalu, Naveen Mellempudi, Stuart Oberman, Mohammad Shoeybi, Michael Siu, and Hao Wu. FP8 formats for deep learning. arXiv preprint arXiv:2209.05433, 2022.

评论

昵称
邮箱
主页