BleachNick's picture
upload required packages
87d40d2

A newer version of the Gradio SDK is available: 5.9.1

Upgrade

Low-Rank Adaptation of Large Language Models (LoRA)

[[open-in-colab]]

ํ˜„์žฌ LoRA๋Š” [UNet2DConditionalModel]์˜ ์–ดํ…์…˜ ๋ ˆ์ด์–ด์—์„œ๋งŒ ์ง€์›๋ฉ๋‹ˆ๋‹ค.

LoRA(Low-Rank Adaptation of Large Language Models)๋Š” ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ ๊ฒŒ ์‚ฌ์šฉํ•˜๋ฉด์„œ ๋Œ€๊ทœ๋ชจ ๋ชจ๋ธ์˜ ํ•™์Šต์„ ๊ฐ€์†ํ™”ํ•˜๋Š” ํ•™์Šต ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ์ด๋Š” rank-decomposition weight ํ–‰๋ ฌ ์Œ(์—…๋ฐ์ดํŠธ ํ–‰๋ ฌ์ด๋ผ๊ณ  ํ•จ)์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์ƒˆ๋กœ ์ถ”๊ฐ€๋œ ๊ฐ€์ค‘์น˜๋งŒ ํ•™์Šตํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—๋Š” ๋ช‡ ๊ฐ€์ง€ ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์ด์ „์— ๋ฏธ๋ฆฌ ํ•™์Šต๋œ ๊ฐ€์ค‘์น˜๋Š” ๊ณ ์ •๋œ ์ƒํƒœ๋กœ ์œ ์ง€๋˜๋ฏ€๋กœ ๋ชจ๋ธ์ด ์น˜๋ช…์ ์ธ ๋ง๊ฐ ๊ฒฝํ–ฅ์ด ์—†์Šต๋‹ˆ๋‹ค.
  • Rank-decomposition ํ–‰๋ ฌ์€ ์›๋ž˜ ๋ชจ๋ธ๋ณด๋‹ค ํŒŒ๋ผ๋ฉ”ํ„ฐ ์ˆ˜๊ฐ€ ํ›จ์”ฌ ์ ์œผ๋ฏ€๋กœ ํ•™์Šต๋œ LoRA ๊ฐ€์ค‘์น˜๋ฅผ ์‰ฝ๊ฒŒ ๋ผ์›Œ๋„ฃ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • LoRA ๋งคํŠธ๋ฆญ์Šค๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์›๋ณธ ๋ชจ๋ธ์˜ ์–ดํ…์…˜ ๋ ˆ์ด์–ด์— ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค. ๐Ÿงจ Diffusers๋Š” [~diffusers.loaders.UNet2DConditionLoadersMixin.load_attn_procs] ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•˜์—ฌ LoRA ๊ฐ€์ค‘์น˜๋ฅผ ๋ชจ๋ธ์˜ ์–ดํ…์…˜ ๋ ˆ์ด์–ด๋กœ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค. scale ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ํ†ตํ•ด ๋ชจ๋ธ์ด ์ƒˆ๋กœ์šด ํ•™์Šต ์ด๋ฏธ์ง€์— ๋งž๊ฒŒ ์กฐ์ •๋˜๋Š” ๋ฒ”์œ„๋ฅผ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์„ฑ์ด ํ–ฅ์ƒ๋˜์–ด Tesla T4, RTX 3080 ๋˜๋Š” RTX 2080 Ti์™€ ๊ฐ™์€ ์†Œ๋น„์ž์šฉ GPU์—์„œ ํŒŒ์ธํŠœ๋‹์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค! T4์™€ ๊ฐ™์€ GPU๋Š” ๋ฌด๋ฃŒ์ด๋ฉฐ Kaggle ๋˜๋Š” Google Colab ๋…ธํŠธ๋ถ์—์„œ ์‰ฝ๊ฒŒ ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ’ก LoRA๋Š” ์–ดํ…์…˜ ๋ ˆ์ด์–ด์—๋งŒ ํ•œ์ •๋˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. ์ €์ž๋Š” ์–ธ์–ด ๋ชจ๋ธ์˜ ์–ดํ…์…˜ ๋ ˆ์ด์–ด๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์ด ๋งค์šฐ ํšจ์œจ์ ์œผ๋กœ ์ฃป์€ ์„ฑ๋Šฅ์„ ์–ป๊ธฐ์— ์ถฉ๋ถ„ํ•˜๋‹ค๋Š” ๊ฒƒ์„ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด LoRA ๊ฐ€์ค‘์น˜๋ฅผ ๋ชจ๋ธ์˜ ์–ดํ…์…˜ ๋ ˆ์ด์–ด์— ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ธ ์ด์œ ์ž…๋‹ˆ๋‹ค. LoRA ์ž‘๋™ ๋ฐฉ์‹์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ Using LoRA for effective Stable Diffusion fine-tuning ๋ธ”๋กœ๊ทธ๋ฅผ ํ™•์ธํ•˜์„ธ์š”!

cloneofsimo๋Š” ์ธ๊ธฐ ์žˆ๋Š” lora GitHub ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์—์„œ Stable Diffusion์„ ์œ„ํ•œ LoRA ํ•™์Šต์„ ์ตœ์ดˆ๋กœ ์‹œ๋„ํ–ˆ์Šต๋‹ˆ๋‹ค. ๐Ÿงจ Diffusers๋Š” text-to-image ์ƒ์„ฑ ๋ฐ DreamBooth์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฐ€์ด๋“œ๋Š” ๋‘ ๊ฐ€์ง€๋ฅผ ๋ชจ๋‘ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

๋ชจ๋ธ์„ ์ €์žฅํ•˜๊ฑฐ๋‚˜ ์ปค๋ฎค๋‹ˆํ‹ฐ์™€ ๊ณต์œ ํ•˜๋ ค๋ฉด Hugging Face ๊ณ„์ •์— ๋กœ๊ทธ์ธํ•˜์„ธ์š”(์•„์ง ๊ณ„์ •์ด ์—†๋Š” ๊ฒฝ์šฐ ์ƒ์„ฑํ•˜์„ธ์š”):

huggingface-cli login

Text-to-image

์ˆ˜์‹ญ์–ต ๊ฐœ์˜ ํŒŒ๋ผ๋ฉ”ํ„ฐ๋“ค์ด ์žˆ๋Š” Stable Diffusion๊ณผ ๊ฐ™์€ ๋ชจ๋ธ์„ ํŒŒ์ธํŠœ๋‹ํ•˜๋Š” ๊ฒƒ์€ ๋Š๋ฆฌ๊ณ  ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. LoRA๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด diffusion ๋ชจ๋ธ์„ ํŒŒ์ธํŠœ๋‹ํ•˜๋Š” ๊ฒƒ์ด ํ›จ์”ฌ ์‰ฝ๊ณ  ๋น ๋ฆ…๋‹ˆ๋‹ค. 8๋น„ํŠธ ์˜ตํ‹ฐ๋งˆ์ด์ €์™€ ๊ฐ™์€ ํŠธ๋ฆญ์— ์˜์กดํ•˜์ง€ ์•Š๊ณ ๋„ 11GB์˜ GPU RAM์œผ๋กœ ํ•˜๋“œ์›จ์–ด์—์„œ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•™์Šต[[dreambooth-training]]

Naruto BLIP ์บก์…˜ ๋ฐ์ดํ„ฐ์…‹์œผ๋กœ stable-diffusion-v1-5๋ฅผ ํŒŒ์ธํŠœ๋‹ํ•ด ๋‚˜๋งŒ์˜ ํฌ์ผ“๋ชฌ์„ ์ƒ์„ฑํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์‹œ์ž‘ํ•˜๋ ค๋ฉด MODEL_NAME ๋ฐ DATASET_NAME ํ™˜๊ฒฝ ๋ณ€์ˆ˜๊ฐ€ ์„ค์ •๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค. OUTPUT_DIR ๋ฐ HUB_MODEL_ID ๋ณ€์ˆ˜๋Š” ์„ ํƒ ์‚ฌํ•ญ์ด๋ฉฐ ํ—ˆ๋ธŒ์—์„œ ๋ชจ๋ธ์„ ์ €์žฅํ•  ์œ„์น˜๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

export MODEL_NAME="runwayml/stable-diffusion-v1-5"
export OUTPUT_DIR="/sddata/finetune/lora/naruto"
export HUB_MODEL_ID="naruto-lora"
export DATASET_NAME="lambdalabs/naruto-blip-captions"

ํ•™์Šต์„ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— ์•Œ์•„์•ผ ํ•  ๋ช‡ ๊ฐ€์ง€ ํ”Œ๋ž˜๊ทธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  • --push_to_hub๋ฅผ ๋ช…์‹œํ•˜๋ฉด ํ•™์Šต๋œ LoRA ์ž„๋ฒ ๋”ฉ์„ ํ—ˆ๋ธŒ์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
  • --report_to=wandb๋Š” ํ•™์Šต ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ค‘์น˜ ๋ฐ ํŽธํ–ฅ ๋Œ€์‹œ๋ณด๋“œ์— ๋ณด๊ณ ํ•˜๊ณ  ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค(์˜ˆ๋ฅผ ๋“ค์–ด, ์ด ๋ณด๊ณ ์„œ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”).
  • --learning_rate=1e-04, ์ผ๋ฐ˜์ ์œผ๋กœ LoRA์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ๋” ๋†’์€ ํ•™์Šต๋ฅ ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด์ œ ํ•™์Šต์„ ์‹œ์ž‘ํ•  ์ค€๋น„๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค (์ „์ฒด ํ•™์Šต ์Šคํฌ๋ฆฝํŠธ๋Š” ์—ฌ๊ธฐ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค).

accelerate launch train_dreambooth_lora.py \
  --pretrained_model_name_or_path=$MODEL_NAME  \
  --instance_data_dir=$INSTANCE_DIR \
  --output_dir=$OUTPUT_DIR \
  --instance_prompt="a photo of sks dog" \
  --resolution=512 \
  --train_batch_size=1 \
  --gradient_accumulation_steps=1 \
  --checkpointing_steps=100 \
  --learning_rate=1e-4 \
  --report_to="wandb" \
  --lr_scheduler="constant" \
  --lr_warmup_steps=0 \
  --max_train_steps=500 \
  --validation_prompt="A photo of sks dog in a bucket" \
  --validation_epochs=50 \
  --seed="0" \
  --push_to_hub

์ถ”๋ก [[dreambooth-inference]]

์ด์ œ [StableDiffusionPipeline]์—์„œ ๊ธฐ๋ณธ ๋ชจ๋ธ์„ ๋ถˆ๋Ÿฌ์™€ ์ถ”๋ก ์„ ์œ„ํ•ด ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

>>> import torch
>>> from diffusers import StableDiffusionPipeline

>>> model_base = "runwayml/stable-diffusion-v1-5"

>>> pipe = StableDiffusionPipeline.from_pretrained(model_base, torch_dtype=torch.float16)

๊ธฐ๋ณธ ๋ชจ๋ธ์˜ ๊ฐ€์ค‘์น˜ ์œ„์— ํŒŒ์ธํŠœ๋‹๋œ DreamBooth ๋ชจ๋ธ์—์„œ LoRA ๊ฐ€์ค‘์น˜๋ฅผ ๋ถˆ๋Ÿฌ์˜จ ๋‹ค์Œ, ๋” ๋น ๋ฅธ ์ถ”๋ก ์„ ์œ„ํ•ด ํŒŒ์ดํ”„๋ผ์ธ์„ GPU๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. LoRA ๊ฐ€์ค‘์น˜๋ฅผ ํ”„๋ฆฌ์ง•๋œ ์‚ฌ์ „ ํ›ˆ๋ จ๋œ ๋ชจ๋ธ ๊ฐ€์ค‘์น˜์™€ ๋ณ‘ํ•ฉํ•  ๋•Œ, ์„ ํƒ์ ์œผ๋กœ 'scale' ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์–ด๋Š ์ •๋„์˜ ๊ฐ€์ค‘์น˜๋ฅผ ๋ณ‘ํ•ฉํ•  ์ง€ ์กฐ์ ˆํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

๐Ÿ’ก 0์˜ scale ๊ฐ’์€ LoRA ๊ฐ€์ค‘์น˜๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„ ์›๋ž˜ ๋ชจ๋ธ์˜ ๊ฐ€์ค‘์น˜๋งŒ ์‚ฌ์šฉํ•œ ๊ฒƒ๊ณผ ๊ฐ™๊ณ , 1์˜ scale ๊ฐ’์€ ํŒŒ์ธํŠœ๋‹๋œ LoRA ๊ฐ€์ค‘์น˜๋งŒ ์‚ฌ์šฉํ•จ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. 0๊ณผ 1 ์‚ฌ์ด์˜ ๊ฐ’๋“ค์€ ๋‘ ๊ฒฐ๊ณผ๋“ค ์‚ฌ์ด๋กœ ๋ณด๊ฐ„๋ฉ๋‹ˆ๋‹ค.

>>> pipe.unet.load_attn_procs(model_path)
>>> pipe.to("cuda")
# LoRA ํŒŒ์ธํŠœ๋‹๋œ ๋ชจ๋ธ์˜ ๊ฐ€์ค‘์น˜ ์ ˆ๋ฐ˜๊ณผ ๊ธฐ๋ณธ ๋ชจ๋ธ์˜ ๊ฐ€์ค‘์น˜ ์ ˆ๋ฐ˜ ์‚ฌ์šฉ

>>> image = pipe(
...     "A picture of a sks dog in a bucket.",
...     num_inference_steps=25,
...     guidance_scale=7.5,
...     cross_attention_kwargs={"scale": 0.5},
... ).images[0]
# ์™„์ „ํžˆ ํŒŒ์ธํŠœ๋‹๋œ LoRA ๋ชจ๋ธ์˜ ๊ฐ€์ค‘์น˜ ์‚ฌ์šฉ

>>> image = pipe("A picture of a sks dog in a bucket.", num_inference_steps=25, guidance_scale=7.5).images[0]
>>> image.save("bucket-dog.png")