Transformers 文档
量化概念
并获得增强的文档体验
开始使用
量化概念
量化通过使用低精度数据类型(如 8 位整数或 int8)而非标准 32 位浮点数 (float32) 来表示模型权重和/或激活,从而减少大型机器学习模型(例如 Transformers 库中的模型)的内存占用和计算成本。
降低模型精度带来多项显著优势
- 更小的模型尺寸:低精度数据类型需要更少的存储空间。例如,一个 int8 模型大约比其 float32 版本小 4 倍。
- 更快的推理:在兼容硬件上(CPU 和 GPU 通常具有 int8 操作的专用指令),对低精度数据类型(特别是整数)进行操作可以显著加快速度。这会降低延迟。
- 更低的能耗:更快的计算和更小的内存传输通常意味着更低的功耗。
量化的主要权衡是*效率*与*准确性*。降低精度可以节省资源,但不可避免地会引入小错误(量化噪声)。目标是使用适当的方案(仿射/对称)、粒度(每张量/通道)和技术(PTQ/QAT)来最大限度地减少此错误,以便模型在其目标任务上的性能尽可能少地下降。
以下部分将介绍量化方案、粒度和技术。
量化方案
核心思想是将原始 float32 权重和激活中的值范围映射到 int8 所表示的更小范围(通常为).
本节介绍一些量化技术的工作原理。

仿射量化
最常见的方法是仿射量化。对于给定的 float32 张量(如层的权重),它找到最小值和最大值值。此范围映射到 int8 范围,通常为.
有两种主要方法进行此映射:*对称*和*非对称*。对称和非对称量化之间的选择决定了 float32 范围如何映射到 int8 范围。
- 对称:此方法假设原始 float32 范围围绕零对称()。此范围对称映射到 int8 范围,例如,。一个关键特征是 float32 值直接映射到 int8 值。这只需要一个参数,即**比例()**,来定义映射。它可以简化计算,但如果原始数据分布并非自然地以零为中心,则准确性可能会降低。
- 非对称(仿射):此方法不假设数据以零为中心。它将 float32 的精确范围映射到完整的 int8 范围,例如。这需要两个参数:一个**比例()**和一个**零点()**。
比例():一个正的 float32 数,表示 float32 范围和 int8 范围之间的比率。
零点():一个 int8 值,对应于 float32 值.
在对称量化中,Z 通常固定为 0。
有了这些参数,float32 值,。可以使用以下公式量化为 int8()。
int8 值,,可以通过以下公式反量化回近似 float32。

在推理过程中,像矩阵乘法这样的计算是使用 int8 值()执行的,结果在传递给下一层之前,会反量化回 float32(通常在内部使用 int32 等更高精度累加类型)。
int4 和权重打包

int4 量化进一步减小了模型大小和内存使用(与 int8 相比减少了一半)。同样的仿射或对称量化原则适用,将 float32 范围映射到 int4 可表示的 16 个可能值(对于有符号 int4)。
int4 量化的一个关键方面是**权重打包**。由于大多数硬件无法在内存中原生处理 4 位数据类型,因此通常将两个 int4 值打包成一个 int8 字节用于存储和传输。例如,第一个值可能占用低 4 位,第二个值占用字节的高 4 位(`packed_byte = (val1 & 0x0F) | (val2 << 4)`)。
即使没有原生 int4 计算,int4 仍然有益,因为主要好处来自内存带宽的减少。将打包的 int4 权重(存储为 int8)从内存(RAM 或 VRAM)加载到计算单元的速度是加载 int8 权重的两倍。对于大型模型,内存访问通常是一个显著的瓶颈。更快的传输速度带来的加速可以抵消即时解包和反量化的计算开销,从而实现整体更快的推理,尤其是在内存受限的场景中。
然而,int4 量化通常会导致比 int8 更大的精度损失。对于 int4 来说,通常需要像 GPTQ 或 AWQ 这样的高级量化技术才能获得良好的性能。
FP8 量化 (A8W8)

FP8 有两种常见变体。
- E4M3:1 个符号位,4 个指数位,3 个尾数位。提供更高的精度(更多尾数位)但动态范围更小(更少指数位)。
- E5M2:1 个符号位,5 个指数位,2 个尾数位。提供更宽的动态范围但精度较低。
FP8 用于 *A8W8* 量化方案,该方案将激活 (A) 和权重 (W) 都量化为 8 位精度。
虽然 int8 得到广泛支持,但高效的 FP8 计算需要较新 GPU(如 NVIDIA H100/H200/B100 和 AMD Instinct MI300 系列)中特有的硬件功能。如果没有原生的硬件加速,FP8 的优势可能无法完全实现。
Transformers 通过特定的后端支持 FP8,例如 FBGEMM、FineGrainedFP8 和 compressed-tensors。当使用适当的硬件和配置时,这些后端处理底层的 FP8 转换和计算。
粒度
量化参数(和)可以通过两种方式计算。
- 每张量:整个张量使用一组和。更简单,但如果张量内数据值差异很大,则精度较低。
- 每通道(或每组/块):每个通道或组使用单独的和。精度更高,性能更好,但成本是略微增加复杂性和内存。

量化技术
量化技术主要有两种类型。
- 训练后量化 (PTQ):在模型完全训练*后*应用量化。
- 量化感知训练 (QAT):在训练*期间*通过插入“伪量化”操作来模拟量化效果,这些操作模拟量化的舍入误差。这使得模型能够适应量化,通常会带来更好的准确性,尤其是在较低位宽下。
Transformers 中的量化
Transformers 集成了多个量化后端,例如 bitsandbytes、torchao、compressed-tensors 等(有关更多后端,请参阅量化概述)。
所有后端都统一在 `HfQuantizer` API 和相关的 `QuantizationConfig` 类下。您可以通过实现自定义 `HfQuantizer` 和 `QuantizationConfig` 来集成您自己的自定义量化后端,如贡献指南中所示。
Transformers 中量化的典型工作流程是:
- 选择适合您的硬件和用例的量化方法(请参阅概述或选择量化方法指南以帮助您)。
- 从 Hugging Face Hub 加载预量化模型,或者加载 float32/float16/bfloat16 模型并使用 `QuantizationConfig` 应用特定量化方法。
下面的示例演示了加载一个 8B 参数模型并使用 bitsandbytes 将其量化为 4 位。
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
model_id = "meta-llama/Llama-3.1-8B-Instruct"
quantization_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_compute_dtype=torch.bfloat16
)
model = AutoModelForCausalLM.from_pretrained(
model_id,
quantization_config=quantization_config,
torch_dtype=torch.bfloat16,
device_map="auto"
)
资源
要更深入地探讨量化和相关性能优化概念,请查看以下资源。
- 使用 Hugging Face 进行量化基础
- 深入了解量化
- 🤗 量化技术简介 💗🧑🍳
- EfficientML.ai 讲座 5 - 量化第一部分
- 从第一性原理实现深度学习的Brrrr
- 使用 PyTorch 加速生成式 AI 第二部分:LLM 优化