9.3 Parameter-Efficient Fine-Tuning (PEFT)
Parameter-Efficient Fine-Tuning (PEFT)은 사전 학습 weight 대부분을 고정하고 작은 과업별 state만 학습합니다. gradient와 optimizer state 비용을 낮추고, 하나의 베이스 모델에 여러 adapter를 운영하며, rollback을 단순화할 수 있습니다. 그러나 activation memory가 사라지는 것은 아니며 베이스 모델, 토크나이저, 템플릿, 어댑터, 런타임은 하나의 호환 단위입니다.
메모리 예산부터 계산하기
Full fine-tuning에서는 model weight, 필요 시 master weight, gradient, optimizer moment, activation, temporary kernel, communication buffer, checkpoint를 분리해 계산합니다. “70B는 수 TB가 필요하다”는 문장은 precision, optimizer, sharding, sequence length, microbatch, activation recomputation 가정이 있어야 의미가 있습니다.
LoRA는 고정한 베이스 weight의 optimizer state와 gradient를 제거하지만 forward activation은 batch와 sequence length에 따라 증가합니다. Gradient checkpointing은 추가 연산으로 activation memory를 줄입니다. FSDP나 ZeRO는 모델 관련 state를 여러 장치에 분산하고, tensor/context parallelism은 한 장치에 들어가지 않는 layer나 sequence를 나눕니다. 모델 크기만 보고 선택하지 말고 측정한 memory worksheet를 기준으로 선택합니다.
LoRA: Low-Rank Update
고정한 에 대해 LoRA는 다음 update를 학습합니다.
, 이고 입니다. 한 factor를 0으로 초기화하면 시작 시 함수가 바뀌지 않습니다 [1].
결정 변수는 rank 만이 아닙니다. rank, , learning rate, supervised token 기준 effective batch, token budget, dropout, target module을 함께 sweep합니다. q_proj/v_proj는 저렴한 baseline이고 all-linear는 더 많은 memory와 checkpoint 크기를 쓰는 대신 용량이 커질 수 있습니다. 새 token, domain vocabulary, output calibration이 필요할 때만 embedding이나 lm_head 학습을 고려하고 tied weight 동작을 기록합니다.
교육용 Merge 의미론
아래 모듈은 멱등(idempotent) merge/unmerge 계약을 보여 주는 교육용 코드입니다. 실제 injector는 임의의 random layer를 만들지 말고 pretrained module을 감싸야 하며 bias/dtype/device와 sharding을 보존하고 출력 동등성을 검사해야 합니다.
import torch
import torch.nn as nn
class LoRAWrapper(nn.Module):
def __init__(self, base: nn.Linear, rank=16, alpha=32):
super().__init__()
self.base = base
self.base.requires_grad_(False)
self.A = nn.Parameter(torch.empty(rank, base.in_features, device=base.weight.device))
self.B = nn.Parameter(torch.zeros(base.out_features, rank, device=base.weight.device))
nn.init.kaiming_uniform_(self.A, a=5 ** 0.5)
self.scale = alpha / rank
self.merged = False
def delta(self):
return (self.B @ self.A).to(self.base.weight.dtype) * self.scale
def forward(self, x):
if self.merged:
return self.base(x)
return self.base(x) + (x @ self.A.T @ self.B.T) * self.scale
@torch.no_grad()
def merge(self):
if not self.merged:
self.base.weight.add_(self.delta())
self.merged = True
@torch.no_grad()
def unmerge(self):
if self.merged:
self.base.weight.sub_(self.delta())
self.merged = False
반복 merge() 호출, merge 후 unmerge 복원, merge 전후 출력을 dtype에 맞는 tolerance로 검사합니다. merge 상태를 표시하려고 고정한 base weight를 trainable로 바꾸면 안 됩니다.
QLoRA: 양자화 저장과 부동소수점 Update
QLoRA는 고정한 베이스 weight를 4-bit NF4로 저장하고, 선택적으로 quantization constant에 double quantization (이중 양자화) 을 적용하며, dequantize한 값을 이용해 연산하는 동안 LoRA parameter만 학습합니다 [2]. 보통 지원 하드웨어에서는 BF16, 그렇지 않으면 충분히 검증한 FP16을 쓰는 연산 dtype (compute dtype) 은 storage dtype과 다릅니다.
import torch
from transformers import AutoModelForCausalLM, BitsAndBytesConfig
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
model_id = "your-pinned-base-checkpoint"
quant = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_use_double_quant=True,
bnb_4bit_compute_dtype=torch.bfloat16,
)
model = AutoModelForCausalLM.from_pretrained(
model_id, quantization_config=quant, device_map="auto"
)
model = prepare_model_for_kbit_training(model, use_gradient_checkpointing=True)
model = get_peft_model(model, LoraConfig(
r=16,
lora_alpha=32,
target_modules="all-linear",
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM",
))
이 설정은 출발점이지 보편 recipe가 아닙니다. kernel/backend 지원, normalization과 output head dtype, peak memory, trainable parameter 이름, gradient checkpointing과 cache의 상호작용을 확인합니다. 양자화 오차 때문에 최적 learning rate와 rank가 달라질 수 있습니다.
Adapter 선택과 배포
최소한 저렴한 LoRA baseline, target module 또는 rank를 늘린 설정, 예산이 허용할 때 full fine-tuning을 비교합니다. data order, token budget, evaluation, tuning effort를 같게 유지합니다. DoRA, prompt tuning 등도 유용할 수 있지만 한 아키텍처나 vision benchmark 결과가 모든 LLM의 보편 순위를 뜻하지는 않습니다.
배포 artifact bundle을 함께 버전 관리합니다.
- base checkpoint revision과 hash
- tokenizer 파일, chat template, special-token map, generation config
- adapter method/config/weight와 library version
- precision과 quantization configuration
- dataset manifest, code/config/container, evaluation report
잘못된 base에 올바른 adapter를 올리면 그럴듯하지만 무효한 출력이 나올 수 있습니다. 명시적 compatibility guard를 둡니다. merged 배포에서는 선택한 floating-point dtype으로 merge하고 새 immutable checkpoint로 저장한 뒤 unmerged inference와 logit/generation을 비교합니다. 4-bit weight로 직접 merge하는 과정이 무손실·가역적이라고 가정하지 말고, 원래 base와 adapter를 rollback용으로 보존합니다.
LoRA Parameter Efficiency Calculator
Full Fine-Tuning
Matrix W (d × d)
LoRA
Matrices A (d × r) + B (r × d)
실행 및 Release Gate
token-normalized loss, trainable/frozen parameter 수, adapter module별 gradient norm, nonfinite, peak allocated/reserved memory, tokens/s, data wait, domain/length slice를 관측합니다. 정확한 재시작을 위해 adapter와 함께 optimizer, scheduler, scaler, RNG, sampler, data cursor를 저장합니다.
예상하지 않은 base parameter가 trainable이거나 target module이 없거나, overflow가 반복되거나, memory가 선언한 headroom을 넘거나, held-out 회귀가 gate를 넘으면 중단합니다. paired domain, base-retention, safety, format/tool, latency, cost 평가를 통과한 뒤에만 배포합니다. adapter unload와 last-known-good base 전환을 모두 연습합니다.
Quizzes
Quiz 1: 학습 파라미터가 1% 미만인 LoRA도 OOM이 날 수 있는 이유는 무엇인가요?
LoRA는 trainable gradient와 optimizer state를 크게 줄이지만, 고정 weight, activation, temporary kernel, communication buffer, 평가 비용은 남습니다. 특히 긴 sequence와 microbatch가 activation memory를 지배할 수 있습니다.
Quiz 2: QLoRA의 storage dtype과 compute dtype은 어떻게 다른가요?
고정한 베이스 weight는 4-bit NF4로 저장하지만, 행렬 연산은 BF16 같은 부동소수점으로 dequantize한 값을 사용합니다. adapter weight와 optimizer state도 부동소수점 표현으로 학습합니다.
Quiz 3: merge가 멱등이어야 하는 이유는 무엇인가요?
두 번째 merge가 같은 delta를 다시 더하면 안 되기 때문입니다. 명시적인 merged state와 검증한 unmerge 동작은 조용한 weight 손상을 막고 rollback을 감사 가능하게 합니다.
Quiz 4: 배포 가능한 adapter를 식별하려면 어떤 파일이 필요한가요?
정확한 base revision, tokenizer와 chat template, special-token·generation configuration, adapter config와 weight, precision·quantization 설정, code/library version, evaluation report가 최소 계약입니다.
References
- Hu, E. J., et al. (2021). LoRA: Low-Rank Adaptation of Large Language Models. arXiv:2106.09685.
- Dettmers, T., et al. (2023). QLoRA: Efficient Finetuning of Quantized LLMs. arXiv:2305.14314.
- Hugging Face. PEFT documentation. Documentation.