본문 바로가기
C.W.K.
Stream
Lesson 05 of 06 · published

PEFT와 LoRA: 매개변수 효율 미세 조정

~14 min · peft, lora, adapter, fine-tune

Level 0텐서 탐구자
0 XP0/62 lessons0/13 achievements
0/120 XP to next level120 XP to go0% complete

70억 매개변수 모델의 약 0.1%만 학습해도 큰 효과를 얻어

10억 매개변수 모델을 전체 미세 조정하려면 10억 개의 기울기와 옵티마이저 상태를 저장하고, 체크포인트에도 10억 개의 매개변수를 담아야 해. 개인용 GPU 한 장에는 들어가지 않을 수 있고 결과물도 매우 커져. LoRA(저랭크 적응)는 이 비용을 크게 줄여.

LoRA의 발상

원본 가중치는 동결해. 적응할 선형 계층마다 작은 변화량 ΔW = B @ A를 더하고, A(rank, in_features), B(out_features, rank) 모양으로 둬. rank=8이고 in/out=4096이라면 계층마다 학습할 매개변수는 8*4096 + 4096*8 = 65,536개야. 전체 미세 조정의 4096*4096 = 16,777,216개와 비교하면 약 0.4% 크기에 불과해.

어댑터가 처음에는 변화량 0을 만들도록 초기화되므로 0단계의 모델은 사전 학습 모델과 똑같이 동작해. 학습 중에는 어댑터만 갱신하고, 추론할 때는 그대로 두어 작은 추가 비용을 내거나 원본 가중치에 병합해 추가 비용을 없앨 수 있어.

PEFT 라이브러리가 해 주는 일

Hugging Face의 peft 라이브러리는 LoRA, AdaLoRA, IA³, 프롬프트 조정 등을 구현해. transformers와 자연스럽게 통합되어 모델을 감싸고 평소처럼 학습한 뒤 몇 MB짜리 어댑터만 저장할 수 있어.

이 방식이 판을 바꾼 이유

  • 70억 매개변수 Llama를 24GB 개인용 GPU에서도 미세 조정할 수 있어.
  • 어댑터 체크포인트가 GB가 아니라 MB 단위라 공유, 버전 관리, A/B 테스트가 쉬워.
  • 전체 매개변수를 복제하지 않고도 작업별 어댑터를 여러 개 묶어 관리할 수 있어.
  • '동결한 기본 모델 + 작은 어댑터' 조합 덕분에 호스팅 환경의 LLM 미세 조정도 비용 면에서 현실적인 선택이 돼.

Code

LoRA로 모델 감싸기: 최소 예·python
# pip install peft transformers
from peft import LoraConfig, get_peft_model, TaskType
from transformers import AutoModelForSequenceClassification

base = AutoModelForSequenceClassification.from_pretrained(
    "bert-base-uncased", num_labels=2,
)

lora_cfg = LoraConfig(
    task_type=TaskType.SEQ_CLS,
    r=8,                              # rank — bigger = more capacity, more params
    lora_alpha=32,                    # scaling factor
    lora_dropout=0.1,
    target_modules=["query", "value"], # adapt Q and V in attention
)

model = get_peft_model(base, lora_cfg)
model.print_trainable_parameters()
# trainable params: 294,912 || all params: 109,777,410 || trainable%: 0.27%
어댑터만 저장하고 불러오기·python
from peft import PeftModel
from transformers import AutoModelForSequenceClassification

# After training:
model.save_pretrained("my-lora-adapter")     # tiny — usually a few MB

# Load on a fresh base model
base = AutoModelForSequenceClassification.from_pretrained(
    "bert-base-uncased", num_labels=2,
)
model = PeftModel.from_pretrained(base, "my-lora-adapter")

# For inference — merge the adapter into the base for zero overhead
merged = model.merge_and_unload()
# `merged` is now a vanilla transformers model with ΔW baked in
target_modules 고르기: 구조 중요·python
from peft import LoraConfig

# LLaMA-family — adapt these projection names
llama_lora = LoraConfig(
    r=16, lora_alpha=32, lora_dropout=0.05,
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj"],
    task_type="CAUSAL_LM",
)

# BERT — query / value
bert_lora = LoraConfig(
    r=8, lora_alpha=32,
    target_modules=["query", "value"],
    task_type="SEQ_CLS",
)

# Or, let PEFT discover all linear layers automatically
auto_lora = LoraConfig(
    r=16, target_modules="all-linear",
    task_type="CAUSAL_LM",
)

External links

Exercise

bert-base-uncased를 r=8이고 쿼리·값 계층에 어댑터를 넣는 LoRA 설정으로 감싸 봐. model.print_trainable_parameters()의 결과를 전체 미세 조정에서 requires_grad=True인 매개변수 수와 비교해. 학습 가능한 매개변수 비율이 대략 1:400인지 확인해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.