Optimum 文档
优化
并获得增强的文档体验
开始使用
优化
🤗 Optimum Intel 提供了一个 `openvino` 包,使您能够使用 NNCF 框架对 🤗 Hub 上托管的许多模型应用各种模型量化方法。
量化是一种通过使用8位或4位等低精度数据类型表示权重和/或激活来降低推理计算和内存成本的技术。
优化支持矩阵
点击 ✅ 即可复制相应优化情况的命令/代码。
任务 (OV 模型类别) | 仅权重 量化 | 混合量化 | 全量化 | 混合量化 | ||||||
---|---|---|---|---|---|---|---|---|---|---|
无数据 | 数据感知 | |||||||||
CLI | Python | CLI | Python | CLI | Python | CLI | Python | CLI | Python | |
文本生成 (OVModelForCausalLM) | – | - | ||||||||
图像-文本-文本 (OVModelForVisualCausalLM) | – | – | – | – | ||||||
文本转图像,文本转视频 (OVDiffusionPipeline) | – | – | – | – | ||||||
自动语音识别 (OVModelForSpeechSeq2Seq) | – | – | – | – | – | – | – | – | ||
特征提取 (OVModelForFeatureExtraction) | – | - | ||||||||
特征提取 (OVSentenceTransformer) | – | - | ||||||||
填充遮罩 (OVModelForMaskedLM) | – | - | ||||||||
文本到文本生成 (OVModelForSeq2SeqLM) | – | - | ||||||||
零样本图像分类 (OVModelForZeroShotImageClassification) | – | - | ||||||||
特征提取 (OVSamModel) | – | – | – | - | – | – | ||||
文本到音频 (OVModelForTextToSpeechSeq2Seq) | ✅ | – | – | – | – | – | – | – | – |
仅权重 量化
量化可应用于模型的线性、卷积和嵌入层,从而在内存受限的设备上加载大型模型。例如,当应用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_size` 和 `ratio` 值通常会提高精度,但会牺牲模型大小和推理延迟。
4位权重压缩模型的质量可以通过采用以下数据依赖方法之一进一步提高
- **AWQ**,即“激活感知量化”(Activation Aware Quantization),是一种用于调整模型权重以实现更精确的4位压缩的算法。它略微提高了压缩LLM的生成质量,但需要在校准数据集上进行权重调整,耗费大量额外时间和内存。请注意,模型中可能不存在适用于AWQ的匹配模式,在这种情况下它将被跳过。还有一种无需数据的AWQ版本,它依赖于权重的每列幅度而不是激活。
- **尺度估计**是一种调整量化尺度以最小化原始层和压缩层之间L2误差的方法。需要提供数据集才能运行尺度估计。使用此方法还会产生额外的时间和内存开销。
- **GPTQ** 以逐层方式优化压缩权重,以最小化压缩层和原始层激活之间的差异。
- **LoRA Correction** 通过利用低秩适应来缓解权重压缩过程中引入的量化噪声。
数据感知算法可以同时或单独应用。为此,请向4位 `OVWeightQuantizationConfig` 提供相应的参数以及数据集。例如
quantization_config = OVWeightQuantizationConfig(
bits=4,
sym=False,
ratio=0.8,
quant_method="awq",
scale_estimation=True,
gptq=True,
dataset="wikitext2"
)
注意:GPTQ 和 LoRA Correction 算法不能同时应用。
全量化
在应用训练后全量化时,权重和激活都将被量化。要对激活应用量化,需要额外的校准步骤,该步骤包括向网络提供 `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 流水线的编码器、解码器和带past的解码器模型将被完全量化,包括激活。
混合量化
传统的优化方法,如训练后8位量化,对稳定扩散(SD)模型效果不佳,可能导致生成结果不理想。另一方面,权重压缩在应用于稳定扩散模型时并不能显著提高性能,因为激活的大小与权重相当。U-Net 组件占据了流水线整体执行时间的大部分。因此,仅优化这一个组件可以在推理速度方面带来显著的好处,同时在不进行微调的情况下保持可接受的精度。量化扩散流水线的其余部分并不能显著提高推理性能,但可能会导致精度大幅下降。因此,建议对 U-Net 模型应用混合模式量化,并对流水线其余组件应用仅权重量化。
- U-Net:对权重和激活都应用量化
- 文本编码器、VAE 编码器/解码器:对权重应用量化
混合模式涉及MatMul和Embedding层中权重的量化,以及其他层中激活的量化,这有助于在优化后保持精度,同时减小模型大小。
`quantization_config` 用于定义优化SD流水线的优化参数。要启用混合量化,请在 `quantization_config` 中指定量化数据集。如果未定义数据集,则所有组件都将应用仅权重(weight-only)量化。
from optimum.intel import OVStableDiffusionPipeline, OVWeightQuantizationConfig
model = OVStableDiffusionPipeline.from_pretrained(
model_id,
export=True,
quantization_config=OVWeightQuantizationConfig(bits=8, dataset="conceptual_captions"),
)
更多详情请参阅相应的NNCF 文档。
混合量化
混合量化是一种将仅权重(weight-only)量化与完全量化结合的技术。在混合量化过程中,我们分别量化
- 加权层的权重到一种精度,以及
- 其他支持层的激活(可能还有权重,如果有些在第一步被跳过)到另一种精度。
默认情况下,所有加权层的权重都在第一步中进行量化。在第二步中,加权层和非加权层的激活都将被量化。如果在第一步中,某些层通过 `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
别忘了提供数据集,因为全量化校准过程需要它。
流水线量化
存在由多个组件组成的多模态流水线,例如稳定扩散或视觉语言模型。在这些情况下,可能需要对流水线的不同组件应用不同的量化方法。例如,您可能希望对视觉语言流水线中的语言模型应用 int4 数据感知仅权重(data-aware weight-only)量化,而对其他组件应用 int8 仅权重(weight-only)量化。在这种情况下,您可以使用 `OVPipelineQuantizationConfig` 类来为流水线的每个组件指定量化配置。
例如,以下代码量化了 InternVL2-1B 中语言模型的权重和激活,压缩了文本嵌入模型的权重,并跳过了视觉嵌入模型的任何量化。
from optimum.intel import OVModelForVisualCausalLM
from optimum.intel import OVPipelineQuantizationConfig, OVQuantizationConfig, OVWeightQuantizationConfig
model_id = "OpenGVLab/InternVL2-1B"
model = OVModelForVisualCausalLM.from_pretrained(
model_id,
export=True,
trust_remote_code=True,
quantization_config=OVPipelineQuantizationConfig(
quantization_configs={
"lm_model": OVQuantizationConfig(bits=8),
"text_embeddings_model": OVWeightQuantizationConfig(bits=8),
},
dataset="contextual",
trust_remote_code=True,
)
)