• **Fine-tuning(๋ฏธ์„ธ์กฐ์ •)**์€ ์‚ฌ์ „ํ•™์Šต๋œ ๋ชจ๋ธ์˜ ๊ฐ€์ค‘์น˜๋ฅผ ์ถœ๋ฐœ์ ์œผ๋กœ ๋‚ด ๋ฐ์ดํ„ฐ์— ๋งž์ถฐ ์ถ”๊ฐ€ ํ•™์Šตํ•˜๋Š” ๊ธฐ๋ฒ•
  • ์ฒ˜์Œ๋ถ€ํ„ฐ(scratch) ํ•™์Šตํ•˜์ง€ ์•Š๊ณ  ๊ธฐ์กด ์ง€์‹์„ ์žฌํ™œ์šฉํ•˜๋Š” ์ „์ดํ•™์Šต(transfer learning)์˜ ํ•œ ๋ฐฉ์‹
  • ์ ์€ ๋ฐ์ดํ„ฐยท๋น„์šฉ์œผ๋กœ ํŠน์ • ๋„๋ฉ”์ธยท์ž‘์—…์— ๋ชจ๋ธ์„ ํŠนํ™”์‹œํ‚ค๋Š” ๋งž์ถคํ™” ๋ฐฉ๋ฒ•
  • ์ „์ฒด ๊ฐ€์ค‘์น˜ ๋˜๋Š” ์ผ๋ถ€(LoRA ๋“ฑ)๋งŒ ๊ฐฑ์‹ ํ•˜๋Š” ์œ ์—ฐํ•œ ํ•™์Šต ์ „๋žต

ํ•ด๋‹น ๊ฐœ๋…์ด ํ•„์š”ํ•œ ์ด์œ 

  • ๋Œ€ํ˜• ๋ชจ๋ธ์„ scratch๋ถ€ํ„ฐ ํ•™์Šตํ•˜๋ฉด ๋ฐ์ดํ„ฐยทGPUยท์‹œ๊ฐ„ยท๋น„์šฉ์ด ๋ง‰๋Œ€
  • ๋Œ€๋ถ€๋ถ„์˜ ์‹ค๋ฌด๋Š” โ€œ๋ฒ”์šฉ ๋ชจ๋ธ โ†’ ๋‚ด ๋„๋ฉ”์ธ ํŠนํ™”โ€๋งŒ ํ•„์š”ํ•œ ์ œํ•œ๋œ ์š”๊ตฌ
  • ๊ณต๊ฐœ ๊ฐ€์ค‘์น˜(open weights)๋ฅผ ์ถœ๋ฐœ์ ์œผ๋กœ ์“ฐ๋ฉด ์ ์€ ์ž์›์œผ๋กœ ์ถฉ๋ถ„

AS-IS (scratch ํ•™์Šต) vs TO-BE (fine-tuning)

flowchart LR
    subgraph A["AS-IS โ€” ์ฒ˜์Œ๋ถ€ํ„ฐ ํ•™์Šต"]
        A1["๋นˆ ๋ชจ๋ธ<br/>(๋žœ๋ค ๊ฐ€์ค‘์น˜)"] --> A2["๊ฑฐ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ + ์ˆ˜๋งŽ์€ GPU<br/>์ˆ˜์ฃผ~์ˆ˜๊ฐœ์›”, ์ˆ˜์–ต์›"] --> A3[์™„์„ฑ ๋ชจ๋ธ]
    end
    subgraph B["TO-BE โ€” fine-tuning"]
        B1["๊ณต๊ฐœ ๊ฐ€์ค‘์น˜<br/>(์ด๋ฏธ ๋˜‘๋˜‘ํ•จ)"] --> B2["๋‚ด ๋ฐ์ดํ„ฐ ์†Œ๋Ÿ‰<br/>GPU ์ ๊ฒŒ, ์ˆ˜์‹œ๊ฐ„~์ˆ˜์ผ"] --> B3[๋„๋ฉ”์ธ ํŠนํ™” ๋ชจ๋ธ]
    end

fine-tuning ๋ฐฉ๋ฒ• 3๊ฐ€์ง€

๋ฐฉ๋ฒ•๋ฌด์—‡์„ ๊ฐฑ์‹ ์ž์›๋น„๊ณ 
Full fine-tuning๋ชจ๋“  ๊ฐ€์ค‘์น˜ํผ (๋Œ€ํ˜• GPU)๊ฐ€์žฅ ๊ฐ•๋ ฅํ•˜์ง€๋งŒ ๋ฌด๊ฒ๊ณ  ๋น„์Œˆ
LoRA (PEFT)์ž‘์€ ์–ด๋Œ‘ํ„ฐ ๊ฐ€์ค‘์น˜๋งŒ์ ์Œ์‹ค๋ฌด์—์„œ ๊ฐ€์žฅ ํ”ํ•จ
QLoRA์–‘์žํ™” + LoRA๋งค์šฐ ์ ์Œ๋‹จ์ผ ์†Œ๋น„์ž๊ธ‰ GPU๋„ ๊ฐ€๋Šฅ
  • PEFT(Parameter-Efficient Fine-Tuning) = ์ผ๋ถ€ ํŒŒ๋ผ๋ฏธํ„ฐ๋งŒ ํ•™์Šตํ•ด ํšจ์œจ์„ ๋†’์ด๋Š” ๊ณ„์—ด, LoRA๊ฐ€ ๋Œ€ํ‘œ.

LoRA๋Š” ์™œ ๊ฐ€๋ฒผ์šด๊ฐ€ โ€” ์ง๊ด€

๊ฑฐ๋Œ€ํ•œ ์›๋ณธ ๊ฐ€์ค‘์น˜ ํ–‰๋ ฌ W๋Š” ๊ทธ๋Œ€๋กœ ์–ผ๋ฆฌ๊ณ (freeze), ๊ทธ ์˜†์— ์ž‘๊ณ  ์–‡์€ ๋ณด์กฐ ํ–‰๋ ฌ ๋‘ ๊ฐœ(A, B) ๋งŒ ์ƒˆ๋กœ ํ•™์Šตํ•œ๋‹ค. ์‹ค์ œ ๋ณ€ํ™”๋Ÿ‰์„ ฮ”W โ‰ˆ BยทA๋กœ ๊ทผ์‚ฌํ•˜๋ฏ€๋กœ, ํ•™์Šตํ•  ํŒŒ๋ผ๋ฏธํ„ฐ ์ˆ˜๊ฐ€ ์›๋ณธ ๋Œ€๋น„ ์ˆ˜๋ฐฑ~์ˆ˜์ฒœ ๋ฐฐ ์ ๋‹ค.

์ถœ๋ ฅ = Wยทx  +  (BยทA)ยทx
        โ”‚          โ”‚
     ์–ผ๋ฆผ(๊ณ ์ •)   ์ด๊ฒƒ๋งŒ ํ•™์Šต (์ž‘์Œ)

๋น„์œ ํ•˜๋ฉด ๋‘๊บผ์šด ๊ต์žฌ(์›๋ณธ ๊ฐ€์ค‘์น˜)๋Š” ๊ทธ๋Œ€๋กœ ๋‘๊ณ , ์–‡์€ ํฌ์ŠคํŠธ์ž‡(์–ด๋Œ‘ํ„ฐ)์— ๋‚ด ๋ฉ”๋ชจ๋งŒ ๋ถ™์ด๋Š” ๊ฒƒ๊ณผ ๊ฐ™๋‹ค. ๊ต์žฌ๋ฅผ ํ†ต์งธ๋กœ ๋‹ค์‹œ ์“ฐ์ง€ ์•Š์•„๋„ ๋‚ด ์šฉ๋„์— ๋งž์ถฐ์ง„๋‹ค.

๊ณผ์ • (์ฝ”๋“œ ํ๋ฆ„)

# 1) ๋ฒ ์ด์Šค ๋ชจ๋ธ + ํ† ํฌ๋‚˜์ด์ € ๋กœ๋“œ (open weights)
model = AutoModelForCausalLM.from_pretrained("google/gemma-...")
 
# 2) LoRA ์–ด๋Œ‘ํ„ฐ ๋ถ€์ฐฉ (์›๋ณธ์€ freeze, ์–ด๋Œ‘ํ„ฐ๋งŒ ํ•™์Šต)
model = get_peft_model(model, LoraConfig(r=16, target_modules=["q_proj", "v_proj"]))
 
# 3) ๋‚ด ๋ฐ์ดํ„ฐ์…‹์œผ๋กœ ์ถ”๊ฐ€ ํ•™์Šต (forward โ†’ loss โ†’ backprop)
trainer = Trainer(model, train_dataset=my_dataset, ...)
trainer.train()
 
# 4) ์–ด๋Œ‘ํ„ฐ ์ €์žฅ (์ˆ˜ MB), ํ•„์š”์‹œ ์›๋ณธ๊ณผ ๋ณ‘ํ•ฉํ•ด ๋ฐฐํฌ์šฉ ๋ชจ๋ธ ์ƒ์„ฑ
model.save_pretrained("my-domain-adapter")

Gemma์— ์ ์šฉํ•˜๋ฉด

  • open weights๋ฅผ ๋ฐ›์•„ LoRA/QLoRA๋กœ ๋„๋ฉ”์ธ ํŠนํ™” ๊ฐ€๋Šฅ (์˜ˆ: โ€œ์šฐ๋ฆฌ ํšŒ์‚ฌ CS ์ฑ—๋ด‡์šฉ Gemmaโ€).
  • ๋„๊ตฌ: HuggingFace transformers + peft/trl, Unsloth, Axolotl ๋“ฑ.
  • ํ•™์Šต ํ›„ ONNX Runtime์šฉ์œผ๋กœ exportํ•˜๋ฉด GPU ์—†์ด ๋ฐฐํฌํ•  ์ˆ˜๋„ ์žˆ๋‹ค.
  • โš ๏ธ ๋ผ์ด์„ ์Šค ํ™•์ธ ํ•„์ˆ˜: Gemma๋Š” ์™„์ „ ์˜คํ”ˆ์†Œ์Šค๊ฐ€ ์•„๋‹ˆ๋ผ โ€œGemma Terms of Useโ€ ์ ์šฉ โ€” ํŒŒ์ƒ๋ฌผ ์ƒ์„ฑ์€ ํ—ˆ์šฉ๋˜๋‚˜ ๊ธˆ์ง€๋œ ์‚ฌ์šฉ ์ •์ฑ…์ด ์žˆ๋‹ค.

Knowledge Distillation๊ณผ์˜ ์ฐจ์ด

  • Fine-tuning: ๊ฐ™์€ ๋ชจ๋ธ์„ ๋‚ด ๋ฐ์ดํ„ฐ๋กœ ๋” ํ•™์Šตํ•ด ํŠนํ™” (์ง€์‹์˜ โ€œ๊ฐฑ์‹ ยท์ถ”๊ฐ€โ€).
  • Distillation: ํฐ ๋ชจ๋ธ์˜ ์ง€์‹์„ ๋‹ค๋ฅธ(์ž‘์€) ๋ชจ๋ธ๋กœ ์ด์ „ (์ง€์‹์˜ โ€œ์ด์‚ฌโ€).

์ฐธ๊ณ  ๋ฌธ์„œ