Transformers documentation

Dışa aktarımların kuantizasyonu

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v5.22.2).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Dışa aktarımların kuantizasyonu

Her export yapılandırması, dışa aktarma sırasında modeli kuantize eden bir quantizer alabilir. Kuantizatörler transformers.exporters.quantizers içinde yer alır ve her biri dışa aktarmanın sabit bir noktasında çalışır: torch.export FX grafiğinde, herhangi bir dönüştürmeden önce veya bir arka ucu dönüştürdüğü modele.

QuantizerKantize ederDynamoONNXExecuTorchOpenVINO
PT2EQuantizerPyTorch 2 Export (PT2E) kuantizasyonuna sahip FX grafiği🟢🟢🟢🟢
NNCFTorchFXQuantizerFX grafiği, NNCF ile🟢🟢🟢 (yalnızca ağırlık)🟢
OnnxRuntimeQuantizerONNX modeli, onnxruntime.quantization ile🔴🟢🔴🔴
NNCFOnnxQuantizerNNCF ile NNCF🔴🟢🔴🔴
NNCFOpenVINOQuantizerNNCF ile NNCF içeren OpenVINO modeli🔴🔴🔴🟢

Dışa aktarma, izleme işleminden önce kuantizatörü arka ucu ve yüklü paketlerle karşılaştırır; bu nedenle bir uyumsuzluk durumunda hata erken aşamada yakalanır. Dışa aktarıcılarda olduğu gibi, her kuantizatör test edildiği paket sürümlerini listeler ve sürümleriniz farklı olduğunda uyarı verir.

Aşağıdaki örnek, bir duygu sınıflandırıcısını ONNX Runtime ile int8'e kuantize eder ve ardından çalıştırır.

from transformers import AutoModelForSequenceClassification, AutoTokenizer
from transformers.exporters import OnnxConfig, OnnxExporter, OnnxRuntimeQuantizer

model_id = "distilbert/distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForSequenceClassification.from_pretrained(model_id)

texts = [
    "A wonderful, heartfelt film.",
    "The plot was dull and the acting worse.",
    "I would watch it again tomorrow.",
    "Two hours I will never get back.",
]
calibration_dataset = [tokenizer(text, return_tensors="pt") for text in texts]
inputs = tokenizer("An absolute delight from start to finish.", return_tensors="pt")

config = OnnxConfig(dynamic=True, quantizer=OnnxRuntimeQuantizer(calibration_dataset=calibration_dataset))
onnx_program = OnnxExporter().export(model, inputs, config)

logits = onnx_program(**inputs)[0]
print(model.config.id2label[int(logits.argmax())])  # POSITIVE

PT2E

PT2EQuantizer, torchao veya hedef çalışma zamanından gelen bir PT2E kuantizatörünü sarmalar ve FX grafiğinde (prepare_pt2e → kalibre et → convert_pt2e) çalıştırır; bu sayede her arka uçla uyumlu çalışır. Her PT2E kuantizatörü kendi kuantize/dequantize işlemlerini enjekte eder, bu nedenle çalışma zamanınızın desteklediğini seçin:

Çalıştırılacağı yerPT2E nicelendiriciŞuradan içe aktar
PyTorch inductor, ONNX Runtime (QDQ), OpenVINOX86InductorQuantizertorchao.quantization.pt2e.quantizer.x86_inductor_quantizer
ExecuTorch XNNPACK arka ucuXNNPACKQuantizerexecutorch.backends.xnnpack.quantizer.xnnpack_quantizer

ExecuTorch için, ExecuTorch'ün kendi XNNPACKQuantizer'ını sarmalayın:

from executorch.backends.xnnpack.quantizer.xnnpack_quantizer import (
    XNNPACKQuantizer,
    get_symmetric_quantization_config,
)
from transformers.exporters import ExecutorchConfig, PT2EQuantizer

xnnpack = XNNPACKQuantizer().set_global(get_symmetric_quantization_config())
config = ExecutorchConfig(backend="xnnpack", quantizer=PT2EQuantizer(xnnpack, calibration_dataset=calibration_dataset))

~HfExporter.export_for_generation üzerinden üretken modelleri kuantize edin. Burada calibration_dataset, inputs gibi generate argümanlarını içerir ve her bileşen, kendisi için yakalanan girdiler üzerinde kalibre edilir. Sadece metin içeren bir modelin prefill ve decode bileşenleri vardır; çok modlu bir model ise prefill'ini modül kodlayıcılarına (örneğin image_encoder), projeksiyoncusuna, language_model ve lm_head bileşenlerine (bkz. export_for_generation nasıl çalışır) daha da böler.

from torchao.quantization.pt2e.quantizer.x86_inductor_quantizer import (
    X86InductorQuantizer,
    get_default_x86_inductor_quantization_config,
)
from transformers import AutoModelForCausalLM, AutoTokenizer
from transformers.exporters import DynamoConfig, DynamoExporter, PT2EQuantizer

model_id = "meta-llama/Llama-3.2-1B"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(model_id)

prompts = ["The capital of France is", "Photosynthesis turns sunlight into", "The first moon landing was in"]
calibration_dataset = [tokenizer(prompt, return_tensors="pt") for prompt in prompts]
inputs = tokenizer("Once upon a time", return_tensors="pt")

x86 = X86InductorQuantizer().set_global(get_default_x86_inductor_quantization_config())
config = DynamoConfig(dynamic=True, quantizer=PT2EQuantizer(x86, calibration_dataset=calibration_dataset))
components = DynamoExporter().export_for_generation(model, inputs, config)  # {"prefill": ..., "decode": ...}

OpenVINO'da PT2E ağırlıkları, OpenVINO'nun FakeQuantize'e dönüştürüp int8'e sıkıştırdığı quantize/dequantize çiftlerinin arkasında tam hassasiyette kalır.

ONNX Runtime

OnnxRuntimeQuantizer varsayılan olarak quantize_static çalıştırır (int8 QDQ aktivasyonları ve ağırlıkları, calibration_dataset üzerinde kalibre edilir), yukarıdaki örnekteki gibi, bir OnnxRuntimeStaticConfig argümanlarıyla. Bir OnnxRuntimeDynamicConfig ile quantize_dynamic çalıştırır (int8 ağırlıklar, çalışma zamanında kuantize edilen aktivasyonlar, kalibrasyon yok).

from transformers.exporters import OnnxRuntimeDynamicConfig, OnnxRuntimeStaticConfig

config = OnnxConfig(
    quantizer=OnnxRuntimeQuantizer(OnnxRuntimeStaticConfig(per_channel=True), calibration_dataset=calibration_dataset)
)
config = OnnxConfig(quantizer=OnnxRuntimeQuantizer(OnnxRuntimeDynamicConfig()))

NNCF

Yukarıdaki tablodaki üç NNCF kuantizatörü, varsayılan olarak nncf.quantize çalıştırır (int8 aktivasyonlar ve ağırlıklar, calibration_dataset üzerinde kalibre edilir, başka bir değer geçirmediğiniz sürece model_type=nncf.ModelType.TRANSFORMER kullanılır) ve argümanları bir NNCFQuantizationConfig nesnesinin argümanlarıdır. Bir NNCFWeightCompressionConfig ile nncf.compress_weights çalıştırırlar (yalnızca ağırlık için int8 veya int4, int4 için AWQ ve ölçek tahmini, ayrıca OpenVINO üzerinde GPTQ ve LoRA düzeltmesi). ExecuTorch yalnızca NNCFTorchFXQuantizer'ın yalnızca ağırlık içeren sonucunu düşürür.

import nncf
from transformers.exporters import (
    DynamoConfig,
    NNCFOnnxQuantizer,
    NNCFOpenVINOQuantizer,
    NNCFTorchFXQuantizer,
    NNCFWeightCompressionConfig,
    OnnxConfig,
    OpenVINOConfig,
    OpenVINOExporter,
)

int4 = NNCFWeightCompressionConfig(mode=nncf.CompressWeightsMode.INT4_SYM, group_size=128)

# OpenVINO: int8 activations and weights, or weight-only int4
openvino_int8 = OpenVINOConfig(quantizer=NNCFOpenVINOQuantizer(calibration_dataset=calibration_dataset))
openvino_int4 = OpenVINOConfig(quantizer=NNCFOpenVINOQuantizer(int4))
# ONNX: weight-only int4, as ONNX Runtime's `MatMulNBits`
onnx_int4 = OnnxConfig(quantizer=NNCFOnnxQuantizer(int4))
# Dynamo: int8 on the FX graph
dynamo_int8 = DynamoConfig(quantizer=NNCFTorchFXQuantizer(calibration_dataset=calibration_dataset))

ov_model = OpenVINOExporter().export(model, inputs, openvino_int4)

Int8 aktivasyonları int8 matmullarını çalıştırır; VNNI olmayan CPU'larda (yalnızca AVX2 destekli Intel ve AMD Zen 2 ile daha eski mimariler) bu işlemler doygunluğa ulaşır, bu nedenle bu ortamlarda daha düşük doğruluk bekleyin. Yalnızca ağırlık sıkıştırması, matmulları kayan nokta aralığında tutar.

Kalibrasyon

Bir kuantizatörün calibration_dataset özniteliği, model girdilerinden oluşan bir yinelemedir; örneğin bir tokenizer çıktıları listesi veya partileri model girdilerine birleştiren bir DataLoader. Bu, düz bir öznitelik olduğundan, kuantizatörü oluşturduktan sonra da ayarlayabilirsiniz (quantizer.calibration_dataset = samples). Bu özniteliği atarsanız, veriye ihtiyaç duyan bir kuantizatör, uyarı vererek dışa aktarımın kendi örnek girdileri üzerinde kalibre edilir; çünkü tek bir örnek, gözlemlenen aralıkları bozabilir. Veriye ihtiyaç duymayan kuantizatörler (dinamik ONNX Runtime kuantizasyonu, int8 ağırlık sıkıştırması) bu özniteliği asla okumaz.

Bileşen başına farklı bir tarif

{component: config} sözlüğünü ~HfExporter.export_for_generation fonksiyonuna iletin; böylece her bileşen kendi koşullarına göre kuantize edilir. Yukarıdaki model için prefill için statik int8 ve decode için daha hafif dinamik int8:

dynamic_x86 = X86InductorQuantizer().set_global(get_default_x86_inductor_quantization_config(is_dynamic=True))

config = {
    "prefill": DynamoConfig(dynamic=True, quantizer=PT2EQuantizer(x86)),
    "decode": DynamoConfig(dynamic=True, quantizer=PT2EQuantizer(dynamic_x86)),
}
components = DynamoExporter().export_for_generation(model, inputs, config)

dict, decompose_for_generation() tarafından üretilen her bileşeni adlandırmalıdır (çok modlu bir model, kodlayıcılarını ekler ve language_model ile lm_head bileşenlerini ayırabilir). Yapılandırmasında kuantizör tanımlanmamış bir bileşen tam hassasiyette kalır. Bu dict'te, bir kuantizörün calibration_dataset alanı, generate kwargs'ları değil, bileşenin forward kwargs'larını içerir.

Kantlayıcı ekleyin

Quantizer'lar transformers.exporters.quantizers içinde yer alır; her araç zinciri ve temsil için bir sınıf bulunur. ExportQuantizer'ı alt sınıflandırın ve şunları bildirin:

  • quantizes_fx_graph: torch.export FX grafiği için, herhangi bir dönüştürme yapılmadan önce (böylece her arka uç sonucu alır) True veya bir arka ucun dönüştürdüğü model için (onnx_ir.Model, openvino.Model) varsayılan olan False.
  • supported_formats: kuantize ettiği dışa aktarma biçimleri. Dışa aktarma, izleme (tracing) öncesinde diğer tüm biçimleri reddeder.
  • required_packages ve isteğe bağlı olarak min_versions ile tested_versions: ne içe aktardığı. Dışa aktarma, izleme (tracing) öncesinde bunların yüklü olup olmadığını kontrol eder, minimum sürümün altında ise hata fırlatır ve sürüm test edilen sürümden farklıysa uyarı verir.

Ardından quantize(model, sample_inputs, export_format) işlevini uygulayın. model, FX grafı veya arka uç modelidir ve sample_inputs, dışa aktarmanın kendi girdileridir. CalibrationSet üzerinde kalibrasyon yapın: bu set, kuantizatörün calibration_dataset değerini (varsa) veya yoksa sample_inputs değerini okur ve transformers.exporters.quantizers.utils içinden bir besleme ile her örneği modelin kendi girdilerine eşler (FX grafı için traced_inputs, ONNX için onnx_feed, OpenVINO için openvino_feed).

from transformers.exporters import ExportFormat
from transformers.exporters.quantizers import CalibrationSet, ExportQuantizer
from transformers.exporters.quantizers.utils import onnx_feed


class MyOnnxQuantizer(ExportQuantizer):
    supported_formats = (ExportFormat.ONNX,)
    required_packages = ("my_toolkit",)
    tested_versions = {"my_toolkit": "1.0.0"}

    def quantize(self, model, sample_inputs, export_format):
        import my_toolkit

        names = [graph_input.name for graph_input in model.graph.inputs]
        calibration = CalibrationSet(self.calibration_dataset, sample_inputs, lambda sample: onnx_feed(names, sample))
        return my_toolkit.quantize(model, calibration_feeds=list(calibration))
Update on GitHub