Transformers documentation
Dışa aktarımların kuantizasyonu
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.
| Quantizer | Kantize eder | Dynamo | ONNX | ExecuTorch | OpenVINO |
|---|---|---|---|---|---|
| PT2EQuantizer | PyTorch 2 Export (PT2E) kuantizasyonuna sahip FX grafiği | 🟢 | 🟢 | 🟢 | 🟢 |
| NNCFTorchFXQuantizer | FX grafiği, NNCF ile | 🟢 | 🟢 | 🟢 (yalnızca ağırlık) | 🟢 |
| OnnxRuntimeQuantizer | ONNX modeli, onnxruntime.quantization ile | 🔴 | 🟢 | 🔴 | 🔴 |
| NNCFOnnxQuantizer | NNCF ile NNCF | 🔴 | 🟢 | 🔴 | 🔴 |
| NNCFOpenVINOQuantizer | NNCF 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())]) # POSITIVEPT2E
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ğı yer | PT2E nicelendirici | Şuradan içe aktar |
|---|---|---|
| PyTorch inductor, ONNX Runtime (QDQ), OpenVINO | X86InductorQuantizer | torchao.quantization.pt2e.quantizer.x86_inductor_quantizer |
| ExecuTorch XNNPACK arka ucu | XNNPACKQuantizer | executorch.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.exportFX grafiği için, herhangi bir dönüştürme yapılmadan önce (böylece her arka uç sonucu alır)Trueveya bir arka ucun dönüştürdüğü model için (onnx_ir.Model,openvino.Model) varsayılan olanFalse.supported_formats: kuantize ettiği dışa aktarma biçimleri. Dışa aktarma, izleme (tracing) öncesinde diğer tüm biçimleri reddeder.required_packagesve isteğe bağlı olarakmin_versionsiletested_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))