INT4 W4A16

INT4 W4A16

vLLM은 메모리 절약과 추론 가속을 위해 가중치를 INT4로 양자화하는 것을 지원해요. 이 양자화 방법은 모델 크기를 줄이고 낮은 초당 쿼리 수(QPS) 워크로드에서 저지연을 유지하는 데 특히 유용합니다.

vLLM과 함께 사용할 준비가 된 인기 LLM의 양자화된 INT4 체크포인트 HF 컬렉션 을 방문하세요.

참고: INT4 연산은 compute capability > 8.0(Ampere, Ada Lovelace, Hopper, Blackwell)인 NVIDIA GPU에서 지원됩니다.

출처: 문서

본문

사전 준비 (Prerequisites)

vLLM으로 INT4 양자화를 사용하려면 llm-compressor 라이브러리를 설치해야 합니다.

(venv-llm-compressor) pip install llmcompressor

또한 평가를 위해 vllmlm-evaluation-harness 를 설치합니다.

(venv-vllm) pip install vllm "lm-eval[api]>=0.4.12"

vLLM과 llm-compressor는 함께 동작하지 못할 수 있으므로 별도의 환경을 사용하세요.

양자화 과정 (Quantization Process)

양자화 과정은 네 가지 주요 단계로 구성됩니다.

  1. 모델 로드
  2. 보정 데이터 준비
  3. 양자화 적용
  4. vLLM에서 정확도 평가

1. 모델 로드 (Loading the Model)

표준 transformers AutoModel 클래스로 모델과 토크나이저를 로드합니다.

from transformers import AutoTokenizer, AutoModelForCausalLM

MODEL_ID = "meta-llama/Meta-Llama-3-8B-Instruct"
model = AutoModelForCausalLM.from_pretrained(
    MODEL_ID,
    device_map="auto",
    dtype="auto",
)
tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)

2. 보정 데이터 준비 (Preparing Calibration Data)

가중치를 INT4로 양자화할 때 가중치 업데이트와 보정된 스케일을 추정할 샘플 데이터가 필요합니다. 배포 데이터와 밀접하게 일치하는 보정 데이터를 사용하는 것이 가장 좋습니다. 범용 instruction-tuned 모델에는 ultrachat 같은 데이터셋을 사용할 수 있어요.

from datasets import load_dataset

NUM_CALIBRATION_SAMPLES = 512
MAX_SEQUENCE_LENGTH = 2048

# Load and preprocess the dataset
ds = load_dataset("HuggingFaceH4/ultrachat_200k", split="train_sft")
ds = ds.shuffle(seed=42).select(range(NUM_CALIBRATION_SAMPLES))

def preprocess(example):
    return {"text": tokenizer.apply_chat_template(example["messages"], tokenize=False)}
ds = ds.map(preprocess)

def tokenize(sample):
    return tokenizer(sample["text"], padding=False, max_length=MAX_SEQUENCE_LENGTH, truncation=True, add_special_tokens=False)
ds = ds.map(tokenize, remove_columns=ds.column_names)

3. 양자화 적용 (Applying Quantization)

이제 양자화 알고리즘을 적용합니다.

from llmcompressor import oneshot
from llmcompressor.modifiers.quantization import GPTQModifier
from llmcompressor.modifiers.smoothquant import SmoothQuantModifier

# Configure the quantization algorithms
recipe = GPTQModifier(targets="Linear", scheme="W4A16", ignore=["lm_head"])

# Apply quantization
oneshot(
    model=model,
    dataset=ds,
    recipe=recipe,
    max_seq_length=MAX_SEQUENCE_LENGTH,
    num_calibration_samples=NUM_CALIBRATION_SAMPLES,
)

# Save the compressed model: Meta-Llama-3-8B-Instruct-W4A16-G128
SAVE_DIR = MODEL_ID.split("/")[1] + "-W4A16-G128"
model.save_pretrained(SAVE_DIR, save_compressed=True)
tokenizer.save_pretrained(SAVE_DIR)

이 과정은 가중치가 4비트 정수로 양자화된 W4A16 모델을 만듭니다.

4. 정확도 평가 (Evaluating Accuracy)

양자화 후 vLLM에서 모델을 로드하고 실행할 수 있습니다.

from vllm import LLM

llm = LLM("./Meta-Llama-3-8B-Instruct-W4A16-G128")

lm_eval 로 정확도를 평가할 수 있습니다.

lm_eval --model vllm \
  --model_args pretrained="./Meta-Llama-3-8B-Instruct-W4A16-G128",add_bos_token=true \
  --tasks gsm8k \
  --num_fewshot 5 \
  --limit 250 \
  --batch_size 'auto'

참고: 양자화된 모델은 bos 토큰의 존재에 민감할 수 있습니다. 평가를 실행할 때 add_bos_token=True 인자를 포함해야 합니다.

모범 사례 (Best Practices)

  • 보정 데이터는 512개 샘플로 시작하고 정확도가 떨어지면 늘립니다.
  • 보정 데이터가 특정 사용 사례에 과적합되는 것을 방지하기 위해 높은 다양성의 샘플을 포함합니다.
  • 시퀀스 길이 2048을 출발점으로 사용합니다.
  • 모델이 훈련된 채팅 템플릿 또는 instruction 템플릿을 사용합니다.
  • 모델을 미세 튜닝했다면 보정을 위해 훈련 데이터의 일부를 사용하는 것을 고려합니다.
  • 양자화 알고리즘의 핵심 하이퍼파라미터를 튜닝합니다.
    • dampening_frac 은 GPTQ 알고리즘이 가지는 영향력을 설정합니다. 낮은 값은 정확도를 개선할 수 있지만, 알고리즘이 실패하게 하는 수치적 불안정을 초래할 수 있습니다.
    • actorder 는 활성화 순서를 설정합니다. 레이어 가중치를 압축할 때 채널이 양자화되는 순서가 중요합니다. actorder="weight" 로 설정하면 추가 지연 없이 정확도를 개선할 수 있습니다.

튜닝할 수 있는 확장 양자화 레시피 예시입니다.

from compressed_tensors.quantization import (
    QuantizationArgs,
    QuantizationScheme,
    QuantizationStrategy,
    QuantizationType,
)
recipe = GPTQModifier(
    targets="Linear",
    config_groups={
        "config_group": QuantizationScheme(
            targets=["Linear"],
            weights=QuantizationArgs(
                num_bits=4,
                type=QuantizationType.INT,
                strategy=QuantizationStrategy.GROUP,
                group_size=128,
                symmetric=True,
                dynamic=False,
                actorder="weight",
            ),
        ),
    },
    ignore=["lm_head"],
    update_size=NUM_CALIBRATION_SAMPLES,
    dampening_frac=0.01,
)

트러블슈팅 및 지원 (Troubleshooting and Support)

문제가 발생하거나 기능 요청이 있으면 vllm-project/llm-compressor GitHub 저장소에 이슈를 열어 주세요. llm-compressor 의 전체 INT4 양자화 예시는 여기 에서 볼 수 있습니다.

더 알아보기 (Learn more)