소비자 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

구성 요소최소권장
GPURTX 3090 (24 GB) – RTX 3080에서도 동작RTX 3090
시스템 RAM16 GB32 GB
사용 가능한 저장소50 GB50 GB+
OSLinux/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
최종 loss0.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을 낮춥니다.
  • 파인튜닝 시점:
Back to Blog

관련 글

더 보기 »