소비자 GPU에서 LLM 파인튜닝: QLoRA 실용 가이드
발행: (2025년 12월 10일 오전 11:20 GMT+9)
3 min read
원문: Dev.to
Source: Dev.to
Introduction
대규모 언어 모델(LLM)을 일반 소비자용 GPU에서 파인튜닝하는 것이 이제 가능해졌습니다. QLoRA(Quantized Low‑Rank Adaptation)를 사용하면 7 B 모델을 단일 RTX 3090(24 GB VRAM)에 맞출 수 있으며, 클라우드 크레딧 없이 몇 시간 안에 학습할 수 있습니다.
- Quantization: 모델 가중치를 32‑bit에서 4‑bit로 압축합니다.
- LoRA: 전체 모델이 아니라 작은 어댑터 레이어만 학습합니다.
결과: 일반적으로 ~28 GB VRAM이 필요한 7 B 모델이 ~6 GB에 들어갑니다.
Hardware & System Requirements
| 구성 요소 | 최소 | 권장 |
|---|---|---|
| GPU | RTX 3090 (24 GB) – RTX 3080에서도 동작 | RTX 3090 |
| 시스템 RAM | 16 GB | 32 GB |
| 사용 가능한 저장소 | 50 GB | 50 GB+ |
| OS | Linux/macOS/Windows (CUDA 지원) | Linux |
Installation
pip install torch transformers peft bitsandbytes trl datasets
Model Loading & Quantization
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
import torch
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_compute_dtype=torch.bfloat16,
bnb_4bit_quant_type="nf4",
bnb_4bit_use_double_quant=True,
)
model = AutoModelForCausalLM.from_pretrained(
"mistralai/Mistral-7B-Instruct-v0.3",
quantization_config=bnb_config,
device_map="auto",
)
tokenizer = AutoTokenizer.from_pretrained("mistralai/Mistral-7B-Instruct-v0.3")
LoRA Configuration
from peft import LoraConfig, get_peft_model
lora_config = LoraConfig(
r=16, # rank
lora_alpha=32, # scaling factor
target_modules=[
"q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj"
],
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM",
)
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# trainable params: 20,971,520 || all params: 7,261,749,248
# trainable%: 0.29%
Dataset
이 가이드는 브라질 고객 서비스 대화 데이터셋을 사용합니다:
from datasets import load_dataset
dataset = load_dataset("RichardSakaguchiMS/brazilian-customer-service-conversations")
Formatting
def format_example(example):
return {
"text": f"""[INST] {example['input']} [/INST]
{example['output']}"""
}
dataset = dataset.map(format_example)
Training
from trl import SFTTrainer
from transformers import TrainingArguments
training_args = TrainingArguments(
output_dir="./output",
num_train_epochs=3,
per_device_train_batch_size=4,
gradient_accumulation_steps=4,
learning_rate=2e-4,
bf16=True,
logging_steps=10,
save_strategy="epoch",
)
trainer = SFTTrainer(
model=model,
train_dataset=dataset["train"],
args=training_args,
tokenizer=tokenizer,
max_seq_length=2048,
dataset_text_field="text",
)
trainer.train()
Optional VRAM Savings
model.gradient_checkpointing_enable() # ~20 % slower but saves memory
Faster Attention (if supported)
model = AutoModelForCausalLM.from_pretrained(
model_name,
attn_implementation="flash_attention_2"
)
Training Summary
| 지표 | 값 |
|---|---|
| 데이터셋 크기 | 10 000 examples |
| Epoch 수 | 3 |
| 배치 크기 (실제) | 4 × 4 (gradient accumulation) |
| 학습 시간 | ~4 hours |
| 최대 VRAM 사용량 | 18 GB |
| 최종 loss | 0.82 |
Inference
from peft import PeftModel
base_model = AutoModelForCausalLM.from_pretrained(
"mistralai/Mistral-7B-Instruct-v0.3",
quantization_config=bnb_config,
)
model = PeftModel.from_pretrained(base_model, "./output")
prompt = "[INST] Cliente: Quero saber do meu pedido [/INST]"
outputs = model.generate(
tokenizer.encode(prompt, return_tensors="pt"),
max_new_tokens=200,
)
print(tokenizer.decode(outputs[0]))
짧고 도메인에 특화된 질의에 대해서는 간단한 프롬프트 엔지니어링만으로도 좋은 결과를 얻을 수 있습니다.
Practical Tips
- 데이터 품질이 양보다 중요합니다: 1 000개의 고품질 예제가 100 000개의 잡음이 섞인 예제보다 종종 더 좋은 성능을 보입니다.
- 클리닝: 학습 전에 일관된 포맷을 유지하도록 정리합니다.
- 학습률 조정:
- loss가 정체될 때 → LR을 올립니다.
- loss가 급등할 때 → LR을 낮춥니다.
- loss가 진동할 때 → 배치 크기나 LR을 낮춥니다.
- 파인튜닝 시점: