본문 바로가기
AI2025년 3월 30일7분 읽기

LoRA vs QLoRA vs Full Fine-tuning 비교 분석

YS
김영삼
조회 671

파인튜닝의 필요성

사전 학습된 LLM을 특정 도메인이나 태스크에 맞게 조정하는 파인튜닝은 모델 성능을 크게 향상시킵니다. 하지만 70B 파라미터 모델의 전체 파인튜닝에는 수백 GB의 VRAM이 필요하여, 효율적인 대안인 LoRA와 QLoRA가 등장했습니다.

Full Fine-tuning

모든 파라미터를 업데이트하는 전통적인 방식입니다. 최고 성능을 낼 수 있지만 메모리와 비용이 가장 많이 듭니다.

# Full Fine-tuning 기본 설정
from transformers import AutoModelForCausalLM, TrainingArguments, Trainer

model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-2-7b-hf",
    torch_dtype=torch.bfloat16,
)

training_args = TrainingArguments(
    output_dir="./full-ft-output",
    per_device_train_batch_size=1,
    gradient_accumulation_steps=16,
    learning_rate=2e-5,
    num_train_epochs=3,
    bf16=True,
    gradient_checkpointing=True,     # 메모리 절약
    deepspeed="ds_config_zero3.json", # 멀티 GPU 분산
)
# 7B 모델 기준: ~120GB VRAM (BF16 + optimizer states)

LoRA (Low-Rank Adaptation)

LoRA는 원본 가중치를 고정하고, 작은 저차원 행렬만 학습합니다. 원래 가중치 행렬 W에 저랭크 분해 BA를 추가하여 W' = W + BA로 업데이트합니다. 학습 파라미터가 전체의 0.1-1%에 불과하여 메모리를 크게 절약합니다.

from peft import LoraConfig, get_peft_model, TaskType

# LoRA 설정
lora_config = LoraConfig(
    task_type=TaskType.CAUSAL_LM,
    r=16,                          # 랭크 (보통 8-64)
    lora_alpha=32,                 # 스케일링 팩터
    lora_dropout=0.05,
    target_modules=[               # 적용 대상 레이어
        "q_proj", "k_proj", "v_proj", "o_proj",
        "gate_proj", "up_proj", "down_proj"
    ],
    bias="none",
)

model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-2-7b-hf",
    torch_dtype=torch.bfloat16,
)
peft_model = get_peft_model(model, lora_config)
peft_model.print_trainable_parameters()
# trainable params: 33,554,432 || all params: 6,771,970,048 || trainable%: 0.4955
# 7B 모델 기준: ~18GB VRAM

QLoRA (Quantized LoRA)

QLoRA는 베이스 모델을 4비트로 양자화한 뒤 LoRA를 적용합니다. NF4 양자화와 이중 양자화를 통해 메모리를 극적으로 줄이면서도 LoRA와 유사한 성능을 달성합니다.

from transformers import BitsAndBytesConfig

# 4비트 양자화 설정
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",           # NormalFloat4
    bnb_4bit_compute_dtype=torch.bfloat16,
    bnb_4bit_use_double_quant=True,      # 이중 양자화
)

model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-2-7b-hf",
    quantization_config=bnb_config,
    device_map="auto",
)

# 이후 LoRA 적용은 동일
peft_model = get_peft_model(model, lora_config)
# 7B 모델 기준: ~6GB VRAM (단일 RTX 4090으로 가능)

성능 및 비용 비교

항목Full FTLoRAQLoRA
VRAM (7B)~120GB~18GB~6GB
VRAM (70B)~800GB~160GB~36GB
학습 속도기준2-3x 빠름LoRA 대비 약간 느림
성능 (벤치)100%97-99%95-97%
어댑터 크기모델 전체10-100MB10-100MB
GPU 요구8x A1001-2x A1001x RTX 4090

LoRA 랭크(r) 선택 가이드

  • r=8: 간단한 스타일/포맷 변경, 리소스 제한 환경
  • r=16-32: 일반적인 도메인 적응, 대부분의 사용 사례에 권장
  • r=64-128: 복잡한 태스크, 새로운 지식 주입이 필요할 때
  • lora_alpha: 보통 r의 2배로 설정하면 안정적
# 학습 완료 후 어댑터 병합
merged_model = peft_model.merge_and_unload()
merged_model.save_pretrained("./merged-model")

# 또는 어댑터만 저장 (추후 동적 로딩)
peft_model.save_pretrained("./lora-adapter")
# 추론 시 로딩
from peft import PeftModel
base = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-hf")
model = PeftModel.from_pretrained(base, "./lora-adapter")

대부분의 실무 사용 사례에서 QLoRA는 비용 대비 성능이 가장 우수합니다. 단일 소비자 GPU로도 70B급 모델을 파인튜닝할 수 있어 접근성이 크게 향상되었습니다.

댓글 0

아직 댓글이 없습니다.
Ctrl+Enter로 등록