[Daily morning study] LoRA์ PEFT (Parameter-Efficient Fine-Tuning)
#daily morning study
์ PEFT๊ฐ ํ์ํ๊ฐ
LLM์ ํน์ ๋๋ฉ์ธ์ ๋ง๊ฒ ํ์ธํ๋ํ๋ ค๋ฉด ์ ์ฒด ํ๋ผ๋ฏธํฐ๋ฅผ ์ ๋ฐ์ดํธํด์ผ ํ๋ค. GPT-3๋ 175B, LLaMA-2๋ 70B ํ๋ผ๋ฏธํฐ๋ฅผ ๊ฐ๋๋ค. ์ด ๋ชจ๋ธ๋ค์ Full Fine-Tuningํ๋ฉด ์์ฒญ๋ GPU ๋ฉ๋ชจ๋ฆฌ์ ์๊ฐ์ด ์๋ชจ๋๋ค.
PEFT(Parameter-Efficient Fine-Tuning)๋ ๋ชจ๋ธ ์ ์ฒด ํ๋ผ๋ฏธํฐ ์ค ๊ทนํ ์ผ๋ถ๋ง ํ์ตํด์ Full Fine-Tuning์ ์คํ๋ ์ฑ๋ฅ์ ๋ฌ์ฑํ๋ ๋ฐฉ๋ฒ๋ค์ ์ด์นญ์ด๋ค.
LoRA (Low-Rank Adaptation)
ํต์ฌ ์์ด๋์ด
2021๋ Microsoft๊ฐ ๋ฐํํ ๋ ผ๋ฌธ์์ ์ ์ํ ๋ฐฉ๋ฒ. ํต์ฌ ๊ฐ์ ์ ๋ค์๊ณผ ๊ฐ๋ค.
์ฌ์ ํ์ต๋ ๋ชจ๋ธ์ ๊ฐ์ค์น ํ๋ ฌ์ ๋ฎ์ ๋ด์ฌ์ ์ฐจ์(low intrinsic dimension)์ ๊ฐ์ง๋ค. ์ฆ, ํ์ธํ๋ ๊ณผ์ ์์ ์ค์ ๋ก ๋ณํํ๋ ์ ๋ณด๋์ ์ ์ฒด ํ๋ผ๋ฏธํฐ ์์ ๋นํด ํจ์ฌ ์๋ค.
์ด ๊ฐ์ ์๋, ๊ฐ์ค์น ๋ณํ๋ ฮW๋ฅผ ๋ ๊ฐ์ ์ ๋ญํฌ ํ๋ ฌ๋ก ๋ถํดํ๋ค.
W' = W + ฮW = W + B ร A
W: ์๋ ์ฌ์ ํ์ต ๊ฐ์ค์น (๊ณ ์ , ํ์ต ์ ํจ)A: shape(r, d_in)โ ๋๋ค ๊ฐ์ฐ์์์ผ๋ก ์ด๊ธฐํB: shape(d_out, r)โ 0์ผ๋ก ์ด๊ธฐํr: rank (ํ์ดํผํ๋ผ๋ฏธํฐ, ๋ณดํต 4~64)
์ด๊ธฐํํ ๋ B=0์ด๋ฏ๋ก ํ์ต ์์ ์ ฮW=0์ด ๋ณด์ฅ๋๋ค. ์ฆ, ํ์ต ์ด๊ธฐ์๋ ์๋ ๋ชจ๋ธ๊ณผ ๋์ผํ๊ฒ ๋์ํ๋ค.
ํ๋ผ๋ฏธํฐ ์ ๊ฐ ํจ๊ณผ
์๋ ๊ฐ์ค์น ํ๋ ฌ์ด d ร k ํฌ๊ธฐ๋ผ๋ฉด:
| ๋ฐฉ์ | ํ์ต ํ๋ผ๋ฏธํฐ ์ |
|---|---|
| Full Fine-Tuning | d ร k |
| LoRA (rank r) | r ร (d + k) |
์: d=4096, k=4096, r=8 ์ด๋ฉด
- Full: 16,777,216๊ฐ
- LoRA: 65,536๊ฐ โ ์ฝ 256๋ฐฐ ๊ฐ์
์ถ๋ก ์ ์ค๋ฒํค๋ ์์
ํ์ต์ด ๋๋๋ฉด W + BรA๋ฅผ ๋ฏธ๋ฆฌ ํฉ์ณ์ W์ ๋ณํฉํ ์ ์๋ค. ๋ฐ๋ผ์ ์ถ๋ก ๋จ๊ณ์์๋ ์ถ๊ฐ ์ฐ์ฐ์ด ์ ํ ์๋ค.
# ํ์ต ํ ๊ฐ์ค์น ๋ณํฉ ์์
merged_weight = pretrained_W + lora_B @ lora_A
์ฃผ์ PEFT ๊ธฐ๋ฒ ๋น๊ต
1. Adapter
Transformer์ ๊ฐ ๋ ์ด์ด์ ์์ ๋ณ๋ชฉ(bottleneck) ๋ ์ด์ด๋ฅผ ์ฝ์ ํ๋ค. ์ค์ง ์ด ์ด๋ํฐ ๋ ์ด์ด๋ง ํ์ตํ๋ค.
[๊ธฐ์กด ๋ ์ด์ด] โ [Down-projection] โ [Non-linear] โ [Up-projection] โ [๊ธฐ์กด ๋ ์ด์ด ์ถ๋ ฅ์ ๋ํจ]
- ์ฅ์ : ๊ตฌํ์ด ์ง๊ด์
- ๋จ์ : ์ถ๋ก ์ ์ด๋ํฐ ์ฐ์ฐ์ด ์ง๋ ฌ๋ก ์ถ๊ฐ๋์ด ๋ ์ดํด์ ์ฆ๊ฐ
2. Prefix Tuning
์ ๋ ฅ ์ํ์ค ์์ ํ์ต ๊ฐ๋ฅํ โ๊ฐ์ ํ ํฐ(prefix)โ์ ๋ถ์ฌ ๋ชจ๋ธ ๋์์ ์ ๋ํ๋ค. ํ๋กฌํํธ ํ๋๊ณผ ์ ์ฌํ์ง๋ง ๋ชจ๋ ๋ ์ด์ด์ prefix๋ฅผ ์ถ๊ฐํ๋ค.
[PREFIX ํ ํฐ๋ค] + [์ค์ ์
๋ ฅ ํ ํฐ๋ค] โ Transformer
- ์ฅ์ : ๋ชจ๋ธ ๊ตฌ์กฐ ๋ณ๊ฒฝ ์์
- ๋จ์ : ์ํ์ค ๊ธธ์ด๊ฐ ๋์ด๋ ์ปจํ ์คํธ ์ฐฝ ์๋ชจ
3. Prompt Tuning
Prefix Tuning์ ๋จ์ํ ๋ฒ์ . ์ ๋ ฅ ์๋ฒ ๋ฉ ๋ ์ด์ด์๋ง ํ์ต ๊ฐ๋ฅํ soft prompt๋ฅผ ์ถ๊ฐํ๋ค.
- ์ฅ์ : ๊ฐ์ฅ ํ๋ผ๋ฏธํฐ ์๊ฐ ์ ์
- ๋จ์ : ๋ชจ๋ธ์ด ํด์๋ก ์ฑ๋ฅ์ด ์ข๊ณ , ์์ ๋ชจ๋ธ์์๋ Full Fine-Tuning ๋๋น ์ฑ๋ฅ ์ฐจ์ด๊ฐ ํผ
4. IAยณ (Infused Adapter by Inhibiting and Amplifying Inner Activations)
์ดํ ์ ์ ํค(K), ๊ฐ(V), ํผ๋ํฌ์๋ ๋ ์ด์ด์ ํ์ฑํ์ ํ์ต ๊ฐ๋ฅํ ์ค์ผ์ผ๋ง ๋ฒกํฐ๋ฅผ ๊ณฑํ๋ ๋ฐฉ์. LoRA๋ณด๋ค ํ๋ผ๋ฏธํฐ ์๊ฐ ํจ์ฌ ์ ๋ค.
๊ธฐ๋ฒ ๋น๊ต ์์ฝ
| ๊ธฐ๋ฒ | ์ถ๊ฐ ํ๋ผ๋ฏธํฐ | ์ถ๋ก ์ค๋ฒํค๋ | ๊ตฌํ ๋ณต์ก๋ |
|---|---|---|---|
| Full Fine-Tuning | ์ ์ฒด | ์์ | ๋ฎ์ |
| Adapter | ์ ์ | ์์ (์ง๋ ฌ) | ๋ณดํต |
| Prefix Tuning | ์ ์ | ์์ (์ปจํ ์คํธ) | ๋ณดํต |
| Prompt Tuning | ๋งค์ฐ ์ ์ | ์์ (์ปจํ ์คํธ) | ๋ฎ์ |
| LoRA | ์ ์ | ์์ (๋ณํฉ ๊ฐ๋ฅ) | ๋ฎ์ |
| IAยณ | ๋งค์ฐ ์ ์ | ์์ | ๋ฎ์ |
QLoRA
QLoRA๋ LoRA์ 4๋นํธ ์์ํ(Quantization)๋ฅผ ๊ฒฐํฉํ ๋ฐฉ๋ฒ์ด๋ค. 2023๋ ๋ฐํ๋์์ผ๋ฉฐ, ๋จ์ผ 48GB GPU์์ 65B ํ๋ผ๋ฏธํฐ ๋ชจ๋ธ์ ํ์ธํ๋ํ ์ ์๊ฒ ํด์คฌ๋ค.
ํต์ฌ ๊ตฌ์ฑ ์์:
- NF4 (NormalFloat4): ์ ๊ท๋ถํฌ๋ฅผ ๊ฐ์ ํ 4๋นํธ ๋ฐ์ดํฐ ํ์
- Double Quantization: ์์ํ ์์๋ฅผ ๋ค์ ์์ํํด ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ ์ ์ฝ
- Paged Optimizers: GPU OOM ๋ฐ์ ์ CPU ๋ฉ๋ชจ๋ฆฌ๋ก ์๋ ์คํ๋ก๋
# QLoRA ์ฌ์ฉ ์์ (Hugging Face + PEFT ๋ผ์ด๋ธ๋ฌ๋ฆฌ)
from transformers import AutoModelForCausalLM, BitsAndBytesConfig
from peft import LoraConfig, get_peft_model
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_use_double_quant=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16
)
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-2-7b-hf",
quantization_config=bnb_config,
device_map="auto"
)
lora_config = LoraConfig(
r=8, # rank
lora_alpha=32, # ์ค์ผ์ผ๋ง ๊ณ์
target_modules=["q_proj", "v_proj"], # ์ ์ฉํ ๋ ์ด์ด
lora_dropout=0.1,
bias="none"
)
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# ์ถ๋ ฅ ์: trainable params: 4,194,304 || all params: 6,742,609,920 || trainable%: 0.0622
LoRA์ ์ฃผ์ ํ์ดํผํ๋ผ๋ฏธํฐ
| ํ๋ผ๋ฏธํฐ | ์๋ฏธ | ๋ณดํต ๊ฐ |
|---|---|---|
r (rank) | ์ ๋ญํฌ ํ๋ ฌ์ ์ฐจ์. ํด์๋ก ํํ๋ ฅโ, ๋ฉ๋ชจ๋ฆฌโ | 4, 8, 16, 64 |
lora_alpha | ์ค์ผ์ผ๋ง ๊ณ์. ์ค์ ์ค์ผ์ผ์ alpha/r | 16, 32 |
target_modules | LoRA๋ฅผ ์ ์ฉํ ๋ ์ด์ด ์ด๋ฆ | q_proj, v_proj ๋ฑ |
lora_dropout | ๊ณผ์ ํฉ ๋ฐฉ์ง ๋๋กญ์์ ๋น์จ | 0.05~0.1 |
lora_alpha/r ๋น์จ์ด ์ค์ง์ ์ธ ํ์ต๋ฅ ์ค์ผ์ผ์ฒ๋ผ ์๋ํ๋ค. alpha=r์ผ ๋ ์ค์ผ์ผ 1.0์ด๋ค.
์ด๋ค ๋ ์ด์ด์ LoRA๋ฅผ ์ ์ฉํ ๊น
Transformer์ Attention ๊ฐ์ค์น์ ์ฃผ๋ก ์ ์ฉํ๋ค:
q_proj(Query ํ๋ ฌ)v_proj(Value ํ๋ ฌ)k_proj(Key ํ๋ ฌ)o_proj(Output ํ๋ ฌ)- ํผ๋ํฌ์๋ ๋ ์ด์ด:
gate_proj,up_proj,down_proj
๋ ผ๋ฌธ์์๋ Q์ V์๋ง ์ ์ฉํด๋ ์ถฉ๋ถํ ์ฑ๋ฅ์ ์ป์ ์ ์๋ค๊ณ ๋ณด๊ณ ํ๋ค. ๋ชจ๋ ๋ ์ด์ด์ ์ ์ฉํ๋ฉด ์ฑ๋ฅ์ ๋ ์ข์ง๋ง ๊ทธ๋งํผ ํ์ต ํ๋ผ๋ฏธํฐ๊ฐ ๋์ด๋๋ค.
LoRA ๋ณํ๋ค
- LoRA+: A์ B์ ํ์ต๋ฅ ์ ๋ค๋ฅด๊ฒ ์ค์ ํด ๋ ํจ์จ์ ์ธ ํ์ต
- DoRA (Weight-Decomposition LoRA): ๊ฐ์ค์น๋ฅผ ํฌ๊ธฐ(magnitude)์ ๋ฐฉํฅ(direction)์ผ๋ก ๋ถํดํด LoRA ์ ์ฉ
- AdaLoRA: ๋ ์ด์ด๋ณ๋ก rank๋ฅผ ์ค์๋์ ๋ฐ๋ผ ์๋์ผ๋ก ์กฐ์
- LoftQ: ์์ํ์ LoRA ์ด๊ธฐํ๋ฅผ ํจ๊ป ์ต์ ํ
์ค๋ฌด ์ ํ ๊ธฐ์ค
- ๋ฉ๋ชจ๋ฆฌ๊ฐ ๋๋ํ๊ณ ์ฑ๋ฅ์ด ์ค์ โ Full Fine-Tuning
- GPU ๋ฉ๋ชจ๋ฆฌ๊ฐ ์ ํ์ ์ด๊ณ ์ถ๋ก ์๋๊ฐ ์ค์ โ LoRA
- ๊ทน๋จ์ ์ผ๋ก ์ ์ ๋ฉ๋ชจ๋ฆฌ, ๋ํ ๋ชจ๋ธ โ QLoRA
- ํ์คํฌ ๊ฐ ์ ํ์ด ์ฆ์(๋ฉํฐํ์คํฌ) โ Adapter ๋๋ LoRA (๊ฐ ํ์คํฌ๋ง๋ค ์ด๋ํฐ ๊ต์ฒด)
- ํ๋กฌํํธ๋ง์ผ๋ก ๊ฐ๋จํ ์ ์ฉ โ Prompt Tuning
LoRA๋ ํ์ฌ ๊ฐ์ฅ ๋๋ฆฌ ์ฐ์ด๋ PEFT ๊ธฐ๋ฒ์ด๋ค. HuggingFace์ peft ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ๋ช ์ค๋ก ์ ์ฉํ ์ ์๊ณ , ํ์ต ํ ๊ฐ์ค์น๋ฅผ ๋ณํฉํ๋ฉด ์ถ๋ก ์ค๋ฒํค๋๋ ์๋ค. ์ค์ ํ๋ก๋์
์์ ๋๋ฉ์ธ ํนํ ๋ชจ๋ธ์ ๋ง๋ค ๋ QLoRA + LoRA ์กฐํฉ์ด ์ฌ์ค์ ํ์ค์ผ๋ก ์๋ฆฌ์ก์๋ค.