Optimum 文档

优化

您正在查看 main 版本,该版本需要从源代码安装. 如果您想要常规 pip 安装,请查看最新的稳定版本 (v1.24.0)。
Hugging Face's logo
加入 Hugging Face 社区

并获得增强的文档体验

开始使用

优化

🤗 Optimum Intel 提供了一个 openvino 包,使您能够使用 NNCF 框架在 🤗 Hub 上托管的许多模型上应用各种模型量化方法。

量化是一种通过降低权重和/或激活的精度来减少推理计算和内存成本的技术,例如 8 位或 4 位等较低精度的数据类型。

优化支持矩阵

点击 ✅ 复制相应优化案例的命令/代码。

任务
(OV 模型类)
仅权重化 混合量化 完全量化 混合精度量化
数据无关 数据感知
CLIPythonCLIPythonCLIPythonCLIPythonCLIPython
文本生成
(OVModelForCausalLM)
图像-文本到文本
(OVModelForVisualCausalLM)
文本到图像
(OVStableDiffusionPipeline)
自动语音识别
(OVModelForSpeechSeq2Seq)

仅权重化

量化可以应用于模型的线性层、卷积层和嵌入层,从而可以在内存受限的设备上加载大型模型。例如,当应用 8 位量化时,生成的模型将比其 fp32 版本小 4 倍。对于 4 位量化,内存减少理论上可以达到 8 倍,但实际上更接近 6 倍。

8 位

对于 8 位权重量化,您可以提供 quantization_config 等于 OVWeightQuantizationConfig(bits=8),以加载 8 位模型权重

from optimum.intel import OVModelForCausalLM, OVWeightQuantizationConfig

model_id = "helenai/gpt2-ov"
quantization_config = OVWeightQuantizationConfig(bits=8)
model = OVModelForCausalLM.from_pretrained(model_id, quantization_config=quantization_config)

# Saves the int8 model that will be x4 smaller than its fp32 counterpart
model.save_pretrained(saving_directory)

视觉-语言管道中语言模型的权重可以以类似的方式量化

model = OVModelForVisualCausalLM.from_pretrained(
    "llava-hf/llava-v1.6-mistral-7b-hf",
    quantization_config=quantization_config
)

如果未提供 quantization_config,则当模型参数超过 10 亿时,默认情况下将以 8 位导出模型。您可以使用 load_in_8bit=False 禁用它。

4 位

4 位权重量化可以以类似的方式实现

from optimum.intel import OVModelForCausalLM, OVWeightQuantizationConfig

quantization_config = OVWeightQuantizationConfig(bits=4)
model = OVModelForCausalLM.from_pretrained(model_id, quantization_config=quantization_config)

或者对于视觉-语言管道

model = OVModelForVisualCausalLM.from_pretrained(
    "llava-hf/llava-v1.6-mistral-7b-hf",
    quantization_config=quantization_config
)

您可以调整量化参数以实现更好的性能准确性权衡,如下所示

quantization_config = OVWeightQuantizationConfig(
    bits=4,
    sym=False,
    ratio=0.8,
    quant_method="awq",
    dataset="wikitext2"
)

注意:OVWeightQuantizationConfig 也接受其构造函数中未列出的关键字参数。在这种情况下,此类参数将直接传递给 nncf.compress_weights() 调用。这对于将其他参数传递给量化算法非常有用。

默认情况下,量化方案将是 不对称,要使其 对称,您可以添加 sym=True

对于 4 位量化,您还可以在量化配置中指定以下参数

  • group_size 参数将定义用于量化的组大小,-1 将导致按列量化。
  • ratio 参数控制 4 位和 8 位量化之间的比率。如果设置为 0.9,则表示 90% 的层将被量化为 int4,而 10% 将被量化为 int8

较小的 group_sizeratio 值通常会提高准确性,但会牺牲模型大小和推理延迟。

4 位权重压缩模型的质量可以通过采用以下数据依赖方法之一进一步提高

  • AWQ,即激活感知量化,是一种调整模型权重以实现更精确的 4 位压缩的算法。它可以稍微提高压缩 LLM 的生成质量,但需要大量的额外时间和内存才能在校准数据集上调整权重。请注意,模型中可能没有匹配的模式来应用 AWQ,在这种情况下,它将被跳过。
  • 尺度估计是一种调整量化尺度以最小化原始层和压缩层之间 L2 误差的方法。提供数据集是运行尺度估计的必要条件。使用此方法也会产生额外的时间和内存开销。
  • GPTQ 以逐层方式优化压缩权重,以最小化压缩层和原始层的激活之间的差异。
  • LoRA 修正通过利用低秩自适应来减轻权重压缩期间引入的量化噪声。

数据感知算法可以一起或单独应用。为此,请将相应参数与数据集一起提供给 4 位 OVWeightQuantizationConfig。例如

quantization_config = OVWeightQuantizationConfig(
    bits=4,
    sym=False,
    ratio=0.8,
    quant_method="awq",
    scale_estimation=True,
    gptq=True,
    dataset="wikitext2"
)

注意:GPTQ 和 LoRA 修正算法不能同时应用。

完全量化

当应用后训练完全量化时,权重和激活都被量化。要对激活应用量化,需要额外的校准步骤,包括将 calibration_dataset 馈送到网络,以估计量化激活参数。

这是如何在给定您自己的 calibration_dataset 的情况下,对微调的 DistilBERT 应用完全量化的方法

from transformers import AutoTokenizer
from optimum.intel import OVQuantizer, OVModelForSequenceClassification, OVConfig, OVQuantizationConfig

model_id = "distilbert-base-uncased-finetuned-sst-2-english"
model = OVModelForSequenceClassification.from_pretrained(model_id, export=True)
tokenizer = AutoTokenizer.from_pretrained(model_id)
# The directory where the quantized model will be saved
save_dir = "ptq_model"

quantizer = OVQuantizer.from_pretrained(model)

# Apply full quantization and export the resulting quantized model to OpenVINO IR format
ov_config = OVConfig(quantization_config=OVQuantizationConfig())
quantizer.quantize(ov_config=ov_config, calibration_dataset=calibration_dataset, save_directory=save_dir)
# Save the tokenizer
tokenizer.save_pretrained(save_dir)

校准数据集也可以使用您的 OVQuantizer 轻松创建

from functools import partial

def preprocess_function(examples, tokenizer):
    return tokenizer(examples["sentence"], padding="max_length", max_length=128, truncation=True)

# Create the calibration dataset used to perform full quantization
calibration_dataset = quantizer.get_calibration_dataset(
    "glue",
    dataset_config_name="sst2",
    preprocess_function=partial(preprocess_function, tokenizer=tokenizer),
    num_samples=300,
    dataset_split="train",
)

quantize() 方法应用后训练量化,并将生成的量化模型导出到 OpenVINO 中间表示 (IR)。生成的图由两个文件表示:一个描述网络拓扑的 XML 文件和一个描述权重的二进制文件。生成的模型可以在任何目标 Intel 设备上运行。

语音到文本模型量化

语音到文本 Whisper 模型可以被量化,而无需准备自定义校准数据集。请看下面的例子。

model_id = "openai/whisper-tiny"
ov_model = OVModelForSpeechSeq2Seq.from_pretrained(
    model_id,
    quantization_config=OVQuantizationConfig(
        num_samples=10,
        dataset="librispeech",
        processor=model_id,
        matmul_sq_alpha=0.95,
    )
)

这样,Whisper 管道的编码器、解码器和带过去信息的解码器模型将被完全量化,包括激活。

混合量化

传统的优化方法(如后训练 8 位量化)对于 Stable Diffusion (SD) 模型效果不佳,并可能导致生成结果不佳。另一方面,当应用于 Stable Diffusion 模型时,权重压缩并不能显着提高性能,因为激活的大小与权重相当。U-Net 组件占用了管道的大部分整体执行时间。因此,仅优化这一个组件就可以在推理速度方面带来显着的好处,同时在不进行微调的情况下保持可接受的准确性。量化扩散管道的其余部分并不能显着提高推理性能,但可能会导致显着的准确性下降。因此,建议对 U-Net 模型应用混合模式量化,而对管道组件的其余部分应用仅权重量化

  • U-Net:对权重和激活都应用量化
  • 文本编码器、VAE 编码器/解码器:对权重应用量化

混合模式涉及 MatMul 和嵌入层中权重的量化以及其他层中激活的量化,从而在优化后保持准确性的同时减小模型大小。

quantization_config 用于定义优化 SD 管道的优化参数。要启用混合量化,请在 quantization_config 中指定量化数据集。如果未定义数据集,则将对所有组件应用仅权重量化。

from optimum.intel import OVStableDiffusionPipeline, OVWeightQuantizationConfig

model = OVStableDiffusionPipeline.from_pretrained(
    model_id,
    export=True,
    quantization_config=OVWeightQuantizationConfig(bits=8, dataset="conceptual_captions"),
)

有关更多详细信息,请参阅相应的 NNCF 文档

混合精度量化

混合精度量化是一种将仅权重量化与完全量化相结合的技术。在混合精度量化期间,我们将分别量化

  1. 加权层的权重到一种精度,以及
  2. 其他支持层的激活(以及可能的权重,如果在第一步中跳过了一些)到另一种精度。

默认情况下,所有加权层的权重在第一步中被量化。在第二步中,加权层和非加权层的激活被量化。如果某些层被指示在第一步中被忽略,使用 weight_quantization_config.ignored_scope 参数,则这些层的权重和激活都被量化到 full_quantization_config 中给出的精度。

当通过 Python API 运行此类优化时,应使用 OVMixedQuantizationConfig。在这种情况下,第一步的精度应通过 weight_quantization_config 参数提供,第二步的精度应通过 full_quantization_config 参数提供。例如

model = OVModelForCausalLM.from_pretrained(
    'TinyLlama/TinyLlama-1.1B-Chat-v1.0',
    quantization_config=OVMixedQuantizationConfig(
        weight_quantization_config=OVWeightQuantizationConfig(bits=4, dtype='nf4'),
        full_quantization_config=OVQuantizationConfig(dtype='f8e4m3', dataset='wikitext2')
    )
)

要通过 CLI 应用混合量化,应使用 --quant-mode 参数。例如

optimum-cli export openvino -m TinyLlama/TinyLlama-1.1B-Chat-v1.0 --quant-mode nf4_f8e4m3 --dataset wikitext2 ./save_dir

不要忘记提供数据集,因为它在完全量化期间的校准过程中是必需的。

< > 在 GitHub 上更新