๐ค PEFT ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ถ์, ์ต๋ ๊ท๋ชจ ๋ชจ๋ธ์ ํ๋ผ๋ฏธํฐ ํจ์จ์ ํ์ธํ๋ ๊ฐ๋ฅ
TL;DR
Hugging Face๊ฐ ๐ค PEFT ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ถ์ํ์ผ๋ฉฐ, ๋ํ ์ธ์ด ๋ชจ๋ธ์ ๋ช ๋ฉ๊ฐ๋ฐ์ดํธ ์์ค์ ํ์ต ๊ฐ๋ฅํ ๊ฐ์ค์น๋ง์ผ๋ก ํ๋ผ๋ฏธํฐ ํจ์จ์ ํ์ธํ๋(PEFT)ํ ์ ์๊ฒ ํ์ฌ, ์ผ๋ฐ ์๋น์์ฉ GPU์์๋ ์ต๋ ๊ท๋ชจ ๋ชจ๋ธ์ ์ ์ฉํ ์ ์๊ฒ ๋ง๋ค์์ต๋๋ค.
๋๊ธฐ: PEFT๊ฐ ์ค์ํ ์ด์
PEFT ๋ฐฉ๋ฒ์ ์ฌ์ ํ์ต๋ ๋ชจ๋ธ์ ๋๋ถ๋ถ์ ๊ณ ์ ํ ์ฑ ์ถ๊ฐ ํ๋ผ๋ฏธํฐ ์๋๋ง ํ์ตํฉ๋๋ค. ์ด๋ ์ฐ์ฐ ๋ฐ ์ ์ฅ ๋น์ฉ์ ๋ชจ๋ ์ค์ด๊ณ , ์ฌ์์ ๋ง๊ฐ์ ๋ฐฉ์งํ๋ฉฐ, ๋ฐ์ดํฐ๊ฐ ์ ์ ์ํฉ์์ ์ ์ฒด ํ์ธํ๋๋ณด๋ค ๋ ์ข์ ์ฑ๋ฅ์ ๋ณด์ด๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค. ์ด ์ ๊ทผ๋ฒ์ ํ ์คํธ, ๋น์ , ์ค๋์ค ๋ฑ ๋ค์ํ ๋ชจ๋ฌ๋ฆฌํฐ์ ์ ์ฉ ๊ฐ๋ฅํ๋ฉฐ, ์์ ์ด๋ํฐ ์ฒดํฌํฌ์ธํธ๋ฅผ ํตํด ํ๋์ ๊ธฐ๋ณธ ๋ชจ๋ธ์ด ์ฌ๋ฌ ๋ค์ด์คํธ๋ฆผ ์์ ์ ์ํํ๋๋ก ํฉ๋๋ค.
์ง์๋๋ PEFT ๊ธฐ๋ฒ
๐ค PEFT ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ํ์ฌ ๋๋ฆฌ ์ธ์ฉ๋๋ ๋ค ๊ฐ์ง ๋ฐฉ๋ฒ์ ๊ตฌํํ๊ณ ์์ต๋๋ค:
- LoRA โ ๋ํ ์ธ์ด ๋ชจ๋ธ์ ์ ๋ญํฌ ์ ์ (Hu et al., 2021).
- Prefix Tuning โ PโTuning v2, ๊ฐ ํธ๋์คํฌ๋จธ ๋ ์ด์ด ์์ ํ์ต ๊ฐ๋ฅํ ๋ฒกํฐ๋ฅผ ์ถ๊ฐํฉ๋๋ค.
- Prompt Tuning โ ์์ ์ ๋ฐ์ ๊ฑธ์ณ ํ๋กฌํํธ ๊ธฐ๋ฐ ์ ์์ ํ์ฅํฉ๋๋ค.
- PโTuning โ GPT ์คํ์ผ ๋ชจ๋ธ์ ์ํ ์ฐ์ ํ๋กฌํํธ๋ฅผ ์ง์ ์ต์ ํํฉ๋๋ค.
์ถ๊ฐ์ ์ธ ๋ฐฉ๋ฒ๋ค์ ํฅํ ๋ฆด๋ฆฌ์ค์์ ์ ๊ณต๋ ์์ ์ ๋๋ค.
๋ํ์ ์ธ ์ฌ์ฉ ์ฌ๋ก
- ๋
ธํธ๋ถ GPU(11โฏGB RAM)์์ 3โฏB ํ๋ผ๋ฏธํฐ T0 ๋ชจ๋ธ ํ์ธํ๋ โ LoRA์ ๐ค Accelerate์ DeepSpeed ํตํฉ์ ์ฌ์ฉํฉ๋๋ค. ์์ ์คํฌ๋ฆฝํธ
peft_lora_seq2seq_accelerate_ds_zero3_offload.py๋ Googleย Colab์์ ์คํ๋ฉ๋๋ค. - Colab์์
bitsandbytes๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ด์ฉํ OPTโ6.7B์ INT8 LoRA ํ๋ โ 8๋นํธ ์์ํ์ PEFT๋ฅผ ๊ฒฐํฉํ๋ฉด ์ ํ๋ GPU ๋ฉ๋ชจ๋ฆฌ์์๋ ๋์ํจ์ ๋ณด์ฌ์ค๋๋ค. - ์๋น์์ฉ GPU(RTXโฏ2080โฏTi, RTXโฏ3080)์์ LoRA๋ฅผ ์ด์ฉํ Stable Diffusion DreamBooth โ T4(16โฏGB) ์ธ์คํด์ค์์ ์คํ๋๋ ๊ณต๊ฐ Gradio ๋ฐ๋ชจ๊ฐ ์ ๊ณต๋ฉ๋๋ค.
์ด ์์๋ค์ ์ด์ ์ ์์ญ GB์ VRAM์ด ํ์ํ๋ ๋ชจ๋ธ๋ค์ ์ด์ ๋๋ถ๋ถ์ ์ค๋ฌด์๊ฐ ์ ๊ทผ ๊ฐ๋ฅํ ํ๋์จ์ด์์ ์ ์์ํฌ ์ ์์์ ๋ณด์ฌ์ค๋๋ค.
๋น ๋ฅธ ์์: LoRA๋ก bigscience/mt0-large ํ์ธํ๋
from transformers import AutoModelForSeq2SeqLM
from peft import get_peft_model, LoraConfig, TaskType
model_name = "bigscience/mt0-large"
model = AutoModelForSeq2SeqLM.from_pretrained(model_name)
peft_cfg = LoraConfig(
task_type=TaskType.SEQ_2_SEQ_LM,
inference_mode=False,
r=8,
lora_alpha=32,
lora_dropout=0.1,
)
model = get_peft_model(model, peft_cfg)
model.print_trainable_parameters()
# โ trainable params: 2,359,296 | all params: 1,231,940,608 | trainableโฏ%: 0.19
ํ์ต ๋ฃจํ์ ๋๋จธ์ง ๋ถ๋ถ์ ๋ณ๊ฒฝ๋์ง ์์ต๋๋ค. ํ์ต์ด ๋๋ ํ์๋ ์ด๋ํฐ ํ์ผ๋ง ์ ์ฅ๋ฉ๋๋ค:
model.save_pretrained("output_dir") # creates adapter_config.json + adapter_model.bin (~19โฏMB)
์ถ๋ก ์ ์ํด ๋ก๋ํ๋ ค๋ฉด:
from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
from peft import PeftModel, PeftConfig
peft_id = "smangrul/twitter_complaints_bigscience_T0_3B_LORA_SEQ_2_SEQ_LM"
cfg = PeftConfig.from_pretrained(peft_id)
base = AutoModelForSeq2SeqLM.from_pretrained(cfg.base_model_name_or_path)
model = PeftModel.from_pretrained(base, peft_id)
tokenizer = AutoTokenizer.from_pretrained(cfg.base_model_name_or_path)
model.eval().to("cuda")
inputs = tokenizer("Tweet text : @HondaCustSvc ...", return_tensors="pt")
with torch.no_grad():
out = model.generate(inputs["input_ids"].to("cuda"), max_new_tokens=10)
print(tokenizer.decode(out[0], skip_special_tokens=True))
# โ "complaint"
์ด๋ํฐ ์ฒดํฌํฌ์ธํธ๋ ๋ช ๋ฉ๊ฐ๋ฐ์ดํธ์ ๋ถ๊ณผํ์ง๋ง, ์ ์ฒด ํ์ธํ๋์ ํ์ ํ๋ ์ฑ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
ํฅํ ๋ฐฉํฅ
Hugging Face๋ IAยณ ๋ฐ ๋ณ๋ชฉ ์ด๋ํฐ์ ๊ฐ์ ์ถ๊ฐ PEFT ๋ณํ์ ์ถ๊ฐํ ๊ณํ์
๋๋ค. ํฅํ ์ฌ์ฉ ์ฌ๋ก๋ก๋ Colab์์ whisper-large์ INT8 ํ์ต๊ณผ RLHF ๊ตฌ์ฑ ์์(์ ์ฑ
๋ฐ ๋ญ์ปค ๋ชจ๋ธ)์ PEFT๋ฅผ ์ ์ฉํ๋ ๊ฒ์ด ํฌํจ๋ฉ๋๋ค. ์ปค๋ฎค๋ํฐ ๊ธฐ์ฌ๋ GitHub ์ ์ฅ์๋ฅผ ํตํด ์ฅ๋ ค๋ฉ๋๋ค.
๊ฒฐ๋ก
๐ค PEFT๋ ํ๋์จ์ด, ์ฐ์ฐ ๋ฐ ์ ์ฅ ์ฅ๋ฒฝ์ ํฌ๊ฒ ๋ฎ์ถ๋ฉด์ ์ ํ์ฑ์ ์ ์งํจ์ผ๋ก์จ ์ต๋ ๊ท๋ชจ ๋ชจ๋ธ์ ์ ์์ ๋ฏผ์ฃผํํฉ๋๋ค. ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๐ค Transformers ๋ฐ ๐ค Accelerate์์ ์ํํ ํตํฉ์ ์ ๊ณตํ์ฌ ๊ธฐ์กด ํ์ดํ๋ผ์ธ์ PEFT๋ฅผ ์ฝ๊ฒ ์ ์ฉํ๊ณ ์์ ๊ฐ์ ๊ฐ๋ฒผ์ด ์ด๋ํฐ๋ฅผ ๊ณต์ ํ ์ ์๊ฒ ํฉ๋๋ค.