Transformers documentation
기여하기
기여하기
Transformers는 QLoRA, GPTQ, LLM.int8, AWQ 등 다양한 양자화 방법을 지원합니다. 그러나 아직 통합되지 않은 양자화 접근 방식이 여전히 많습니다. 이러한 양자화 방법을 Transformers에 추가하고 사용하는 것을 더 쉽게 하기 위해 HfQuantizer 클래스를 사용하세요. HfQuantizer는 모든 PyTorch 모듈에 적용되는 것이 아니라, 양자화 방법을 추가하기 위한 내부 헬퍼 클래스로 설계되었습니다.
이 가이드에서는 HfQuantizer에 새로운 양자화 방법을 통합하는 방법을 보여 드립니다.
요구 사항
Transformers에 새로운 양자화 방법을 통합하기 전에, 해당 방법이 다음 요구 사항을 충족하는지 확인하세요. PyTorch 모듈로 실행할 수 있는 양자화 방법만 지원됩니다.
양자화 방법은 pip으로 설치할 수 있는 Python 패키지를 통해 사용할 수 있습니다(소스에서 패키지만 설치할 수 있는 경우에도 문제없습니다). 이상적으로는 pip 패키지에 사전 컴파일된 커널이 포함되어 있어야 합니다.
이 메서드는 일반적으로 사용되는 하드웨어(CPU, GPU 등)에서 실행할 수 있습니다.
해당 메서드는 nn.Module(
~bitsandbytes.nn.Linear8bitLt,~bitsandbytes.nn.Linear4bit)로 래핑되어 있으며, 양자화된 선형 레이어는 다음 정의가 있어야 합니다.class Linear4bit(nn.Module): def __init__(self, ...): ... def forward(self, x): return my_4bit_kernel(x, self.weight, self.bias)이 방식은 nn.Linear 인스턴스를 대상 클래스로 교체하여 Transformers 모델을 쉽게 양자화할 수 있게 합니다.
양자화 방법은 직렬화 가능해야 합니다. 양자화된 가중치를 로컬에 저장하거나 Hub에 push할 수 있습니다.
양자화 커널/프라이미티브를 포함하는 패키지가 안정적(빈번한 깨지는 변경 없음)인지 확인하세요.
일부 양자화 방법은 데이터 보정을 통해 모델을 “사전 양자화”해야 할 수 있습니다(AWQ). 이 경우, Transformers에서는 추론만 지원하고, 모델 양자화 자체는 ML 커뮤니티에서 유지 관리하는 서드파티 라이브러리에 맡기는 것을 권장합니다.
새로운 HFQuantizer 클래스 생성
가장 좋은 시작점은 Finegrained Fp8과 같은 다른 양자화 방법을 살펴보는 것입니다. 총 3개의 파일을 업데이트하거나 새로 만들어야 합니다: config 파일, integration 파일, quantizer 파일.
src/transformers/utils/quantization_config.py 안에 새로운 quantization config 클래스를 생성합니다. Transformers의 src/transformers/__init__.py 파일 내부의 _import_structure에 새로운 quantization config를 추가합니다.
quantizer_your_method.py이라는 이름의 새 파일을 src/transformers/quantizers/ 안에 생성하고, [`~quantizers.HfQuantizer`]를 상속하도록 하세요. src/transformers/quantizers/auto.py의 양자화 자동 매핑에 새 양자화기 및 양자화 구성을 추가했는지 확인하세요.quantization method에 대해 다음 클래스 속성과 프로퍼티 메서드를 정의하세요:
requires_calibration: 양자화 방식에 데이터 보정 과정이 필요한지 여부.True로 설정하면 양자화된 가중치를 사용한 추론만 지원되며, 추론과 양자화를 동시에 수행할 수 없습니다.is_serializable: 해당 메서드가 직렬화 가능한지 여부를 결정하는 프로퍼티 메서드입니다.is_trainable: 양자화 방식(PEFT 방식 사용 여부와 관계없이) 위에 모델을 fine-tune할 수 있는지 여부를 결정하는 property method입니다.
validate_environment및update_dtype메서드를 작성하세요. 이 메서드들은 양자화 모델 생성 전에 호출되어 사용자가 올바른 구성을 사용하는지 확인합니다. 구현 예시를 확인하려면 다른 양자화기를 참고하세요._process_model_before_weight_loading메서드를 작성합니다. Transformers에서는 가중치를 로드하기 전에 양자화된 모델이 먼저"meta"디바이스에서 초기화됩니다. 즉,_process_model_before_weight_loading메서드는 모델 스켈레톤을 조작하여 일부 모듈(nn.Linear)을 대상 모듈(양자화 모듈)로 교체하는 역할을 담당합니다.
transformers/src/integrations/ 폴더에 새 파일을 생성하고 해당 폴더의 __init__.py 파일에서 관련 메서드를 노출하여 모듈 교체 로직이나 기타 유틸리티 메서드를 정의할 수 있습니다.
양자화가 온더플라이 양자화를 지원하는 경우, 양자화기 클래스에
get_quantize_ops메서드를 추가합니다. Transformers에서는 각 텐서를 물리적으로 생성한 후 일련의 다양한 연산을 적용합니다. 이 경우 양자화 연산은 마지막에 수행됩니다.ConversionOps의 하위 클래스인XXXQuantize를 생성하고convert메서드를 추가해야 합니다.convert메서드에서는 가중치를 양자화하고 양자화된 매개변수의 딕셔너리를 반환해야 합니다.양자화가 사전 양자화 가중치 로딩을 지원하는 경우, 양자화기 클래스에
get_weight_conversions메서드를 추가합니다. transformers에서는 여러 텐서를 수집하고 그 위에 연산을 적용할 수 있습니다. 이는 체크포인트에 있는 텐서를 다시 그룹화하여 양자화 텐서를 재구성해야 하는 경우에 특히 유용합니다.필요한 경우
_process_model_after_weight_loading메서드를 작성하세요. 이 메서드는 가중치를 로드한 후 모델을 조작해야 하는 추가 기능을 구현할 수 있게 합니다.모든 것을 문서화하세요!
docs/source/en/quantization아래에 새 파일을 추가하여 양자화 방법이 문서화되었는지 확인하세요.docker/transformers-quantization-latest-gpu안의 nightly Dockerfile에 패키지를 추가하고,tests/quantization/xxx에 새로운 테스트 파일을 추가하여 테스트를 추가해야 합니다. 구현 방식을 확인하려면 기존 양자화 메서드를 참고해 보세요.
파일 개요
| 파일 | 목적 |
|---|---|
utils/quantization_config.py | QuantizationConfigMixin을 상속받는 YourMethodConfig를 정의합니다 |
quantizers/quantizer_your_method.py | HfQuantizer를 상속받아 YourMethodHfQuantizer를 구현합니다 |
integrations/your_method.py | ConversionOps 하위 클래스 및 헬퍼 함수 구현 |
quantizers/auto.py | AUTO_QUANTIZER_MAPPING과 AUTO_QUANTIZATION_CONFIG_MAPPING에 quantizer와 config를 등록합니다 |
docs/source/en/quantization/your_method.md | 사용자를 위한 문서 사용 |
tests/quantization/your_method/ | 통합 테스트 추가 |
get_quantize_ops와 get_weight_conversions 이해하기
이 두 메서드는 가중치 로딩을 위한 서로 다른 시나리오를 처리합니다. 각각을 언제 사용해야 하는지 이해하는 것이 필수적입니다.
get_quantize_ops — 실시간 양자화
양자화되지 않은 체크포인트(예: float16/bfloat16 가중치)를 로드하면서 로드 중에 양자화를 수행할 때 이 방법을 사용합니다.
Checkpoint: model.safetensors (float16 weights for example)
↓
get_quantize_ops → YourQuantize.convert()
↓
Result: Quantized weights in memoryconvert 메서드는 한 번에 하나의 텐서를 받아서 양자화하고, 양자화된 매개변수의 사전(dict)을 반환할 수 있습니다. 예를 들어:
class YourQuantize(ConversionOps):
def convert(self, input_dict, model, full_layer_name, missing_keys, **kwargs):
# input_dict = {"layer.weight": <float16 tensor>}
value = list(input_dict.values())[0]
module, tensor_name = get_module_from_name(model, full_layer_name)
# Quantize and assign
quantized, scale, zero_point = your_quantize_fn(value)
return {full_layer_name: quantized, full_layer_name + ".scale": scale, full_layer_name + ".zero_point": zero_point}get_weight_conversions — 사전 양자화된 체크포인트 로드
양자화된 가중치가 여러 개의 개별 구성 요소(예: data, scale, zero point)로 저장되어 있고, 로딩 시 이를 하나의 텐서로 결합해야 하는 사전 양자화 체크포인트를 로드할 때 이 기능을 사용합니다. 모든 양자화 방식이 이 재구성 단계를 요구하지는 않습니다. 예를 들어 FP8과 같은 일부 방식은 가중치와 스케일을 그대로 로드할 뿐 결합하지 않습니다. 반면 torchao와 같은 방식은 저장된 여러 구성 요소로부터 양자화 텐서를 다시 조립해야 합니다.
Checkpoint: model.safetensors (quantized components)
- layer._weight_qdata
- layer._weight_scale
- layer._weight_zero_point
↓
get_weight_conversions → WeightConverter + YourDeserialize.convert()
↓
Result: Reconstructed quantized tensor → layer.weightWeightConverter는 source_patterns에 따라 관련 텐서를 수집한 후, 이를 사용자의 convert 메서드로 전달합니다:
def get_weight_conversions(self):
if self.pre_quantized:
return [
WeightConverter(
source_patterns=["_weight_qdata", "_weight_scale", "_weight_zero_point"],
target_patterns="weight",
operations=[YourDeserialize(self)],
),
]
return []
class YourDeserialize(ConversionOps):
def convert(self, input_dict, model, full_layer_name, **kwargs):
# input_dict contains all collected tensors
# Reconstruct the quantized tensor from components
reconstructed_tensor = reconstruct_from_components(input_dict)
return {full_layer_name: reconstructed_tensor}