LLM Fine-tuning LoRA Clean Architecture —

LoRA คืออะไรและทำไมถึงปฏิวัติการ Fine-tune LLM

LoRA (Low-Rank Adaptation) เป็นเทคนิค Parameter-Efficient Fine-Tuning (PEFT) ที่ช่วยให้ fine-tune Large Language Models ได้โดยใช้ทรัพยากรน้อยลงอย่างมาก แทนที่จะ update weight ทั้งหมดของ model LoRA จะ freeze weights เดิมไว้และเพิ่ม trainable low-rank matrices เข้าไปในแต่ละ layer
หลักการทำงานของ LoRA คือ สำหรับ weight matrix W ขนาด d x k แทนที่จะ update W โดยตรง LoRA จะเพิ่ม delta W = B x A โดยที่ B มีขนาด d x r และ A มีขนาด r x k เมื่อ r (rank) มีค่าน้อยมากเช่น 8 หรือ 16 จำนวน trainable parameters จะลดลงอย่างมหาศาล
ตัวอย่างเช่น Llama 2 7B มี parameters 7 พันล้านตัว full fine-tuning ต้องใช้ GPU RAM มากกว่า 60GB แต่ LoRA ด้วย rank 16 มี trainable parameters เพียง 4-8 ล้านตัว (ประมาณ 0.1% ของ model) ใช้ GPU RAM แค่ 16-24GB ทำให้ fine-tune ได้บน consumer GPU เช่น RTX 4090
QLoRA (Quantized LoRA) เป็นการรวม LoRA กับ 4-bit quantization ทำให้ใช้ memory น้อยลงอีก สามารถ fine-tune model 7B ด้วย GPU RAM เพียง 6-8GB หรือ fine-tune model 70B ด้วย GPU RAM 48GB ซึ่งเป็นไปไม่ได้เลยกับ full fine-tuning
สถาปัตยกรรม LoRA และ QLoRA เชิงลึก
รายละเอียดทางเทคนิคของ LoRA architecture
LoRA Architecture Deep Dive
=== Original Weight Update ===
Full fine-tuning: W_new = W + delta_W
delta_W มีขนาด d x k (เท่ากับ W)
Parameters: d * k = ล้านๆ parameters
=== LoRA Decomposition ===
LoRA: W_new = W + B * A
W: d x k (frozen, ไม่ update)
B: d x r (trainable)
A: r x k (trainable)
r << min(d, k) เช่น r = 8, 16, 32, 64
Parameters: r * (d + k) = น้อยมาก
ตัวอย่าง: d=4096, k=4096, r=16
Full: 4096 * 4096 = 16,777,216
LoRA: 16 * (4096 + 4096) = 131,072 (0.78%)
=== LoRA Hyperparameters ===
r (rank): ขนาดของ low-rank matrices
r=8: น้อยสุด, เร็วสุด, อาจไม่พอสำหรับ task ซับซ้อน
r=16: balance ดี, เหมาะกับงานส่วนใหญ่
r=32: quality สูงขึ้น, ใช้ memory มากขึ้น
r=64: ใกล้เคียง full fine-tuning
alpha: scaling factor
alpha = r: scaling = 1 (ค่าเริ่มต้น)
alpha = 2*r: scaling = 2 (LoRA มีผลมากขึ้น)
สูตร: scaling = alpha / r
target_modules: layers ที่จะใส่ LoRA
Attention layers: q_proj, k_proj, v_proj, o_proj
เนื้อหาเกี่ยวข้อง — อ่านต่อ: smart contract coins list
MLP layers: gate_proj, up_proj, down_proj
แนะนำเริ่มจาก attention layers ก่อน
dropout: LoRA dropout
0.05-0.1: ป้องกัน overfitting
=== QLoRA Specifics ===
4-bit NormalFloat (NF4) quantization
Double quantization สำหรับ quantization constants
Paged optimizers สำหรับ memory management
Memory comparison (Llama 2 7B):
Full FP16: ~28 GB
แนะนำเพิ่มเติม — SiamCafeBook
LoRA FP16: ~16 GB
QLoRA 4-bit: ~6 GB
=== LoRA Variants ===
DoRA: Weight-Decomposed Low-Rank Adaptation
แยก magnitude กับ direction ของ weight
ผลลัพธ์ดีกว่า LoRA เล็กน้อย
AdaLoRA: Adaptive LoRA
ปรับ rank ของแต่ละ layer อัตโนมัติ
layers ที่สำคัญได้ rank สูงกว่า
LoRA+: ใช้ learning rate ต่างกันสำหรับ A และ B
B ใช้ lr สูงกว่า A ประมาณ 2-4 เท่า
Fine-tune LLM ด้วย LoRA และ Hugging Face PEFT
โค้ดสำหรับ fine-tune Llama model ด้วย QLoRA
จัดโครงสร้างโปรเจกต์แบบ Clean Architecture
โครงสร้างโปรเจกต์ที่ดีสำหรับ LLM fine-tuning
Clean Architecture สำหรับ LLM Fine-tuning Project
llm-finetune/
├── configs/
│ ├── base.yaml # base configuration
│ ├── lora_llama7b.yaml # model-specific config
│ └── lora_mistral7b.yaml
├── src/
│ ├── __init__.py
│ ├── data/
เนื้อหาเกี่ยวข้อง — ทำความเข้าใจ Model Registry กับ RBAC ABAC Policy —
│ │ ├── __init__.py
│ │ ├── dataset.py # dataset loading and processing
│ │ ├── formatter.py # prompt formatting
│ │ └── collator.py # data collation
│ ├── model/
│ │ ├── __init__.py
│ │ ├── loader.py # model loading with quantization
│ │ ├── lora_setup.py # LoRA configuration
│ │ └── merging.py # merge LoRA weights
│ ├── training/
│ │ ├── __init__.py
│ │ ├── trainer.py # custom trainer
│ │ ├── callbacks.py # training callbacks
│ │ └── metrics.py # evaluation metrics
│ ├── inference/
│ │ ├── __init__.py
│ │ ├── generate.py # text generation
แนะนำเพิ่มเติม — XM Signal
│ │ └── server.py # API server
│ └── utils/
│ ├── __init__.py
│ ├── config.py # configuration management
│ └── logging.py # logging setup
├── scripts/
│ ├── train.py # training entrypoint
│ ├── evaluate.py # evaluation script
│ ├── merge_lora.py # merge LoRA to base model
│ └── serve.py # start inference server
├── tests/
│ ├── test_data.py
│ ├── test_model.py
│ └── test_inference.py
เนื้อหาเกี่ยวข้อง — แนะนำให้อ่าน Snyk Code Security Zero Downtime Deployment —
├── Dockerfile
├── requirements.txt
└── README.md
=== configs/lora_llama7b.yaml ===
model:
name: meta-llama/Llama-2-7b-hf
quantization:
enabled: true
bits: 4
quant_type: nf4
double_quant: true
compute_dtype: bfloat16
lora:
r: 16
alpha: 32
dropout: 0.05
target_modules:
- q_proj
- k_proj
- v_proj
- o_proj
- gate_proj
- up_proj
- down_proj
bias: none
training:

epochs: 3
batch_size: 4
gradient_accumulation: 4
learning_rate: 2e-4
weight_decay: 0.001
warmup_ratio: 0.03
scheduler: cosine
max_seq_length: 2048
optimizer: paged_adamw_32bit
bf16: true
max_grad_norm: 0.3
data:
dataset: timdettmers/openassistant-guanaco
prompt_template: alpaca
packing: true
=== src/model/loader.py ===
import yaml
import torch
เนื้อหาเกี่ยวข้อง — ดูเพิ่มเติมเรื่อง WordPress WooCommerce AR VR Development
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
class ModelLoader:
def __init__(self, config_path):
with open(config_path) as f:
self.config = yaml.safe_load(f)
def load_model(self):
model_cfg = self.config["model"]
bnb_config = None
if model_cfg["quantization"]["enabled"]:
q = model_cfg["quantization"]
bnb_config = BitsAndBytesConfig(
load_in_4bit=(q["bits"] == 4),
bnb_4bit_quant_type=q["quant_type"],
bnb_4bit_compute_dtype=getattr(torch, q["compute_dtype"]),
bnb_4bit_use_double_quant=q["double_quant"],
)
model = AutoModelForCausalLM.from_pretrained(
model_cfg["name"],
quantization_config=bnb_config,
device_map="auto",
trust_remote_code=True,
)
tokenizer = AutoTokenizer.from_pretrained(model_cfg["name"])
tokenizer.pad_token = tokenizer.eos_token
return model, tokenizer
Training Pipeline และ Hyperparameter Tuning
สร้าง training pipeline ที่รองรับ experiment tracking
Deploy และ Serve LoRA Model
Deploy LoRA model สำหรับ inference
FAQ คำถามที่พบบ่อย
Q: LoRA rank เท่าไหร่ดีที่สุด?
A: ขึ้นอยู่กับ task complexity สำหรับ task ง่ายเช่น sentiment classification rank 8 เพียงพอ สำหรับ task ปานกลางเช่น instruction following rank 16 เหมาะสม สำหรับ task ซับซ้อนเช่น code generation หรือ domain-specific knowledge rank 32-64 อาจจำเป็น แนะนำเริ่มจาก rank 16 แล้วทดลองเพิ่มลดดูผลลัพธ์
Q: QLoRA กับ LoRA ผลลัพธ์ต่างกันมากไหม?
A: งานวิจัยของ Dettmers et al. แสดงว่า QLoRA ให้ผลลัพธ์ใกล้เคียง full 16-bit fine-tuning มากโดยใช้ memory น้อยกว่า 4 เท่า quality loss จาก quantization น้อยมาก (ต่ำกว่า 1% ในงานส่วนใหญ่) สำหรับ GPU RAM จำกัดแนะนำใช้ QLoRA เสมอ
Q: ข้อมูลสำหรับ fine-tune ต้องมีเท่าไหร่?
A: LoRA ทำงานได้ดีกับข้อมูลน้อยกว่า full fine-tuning สำหรับ instruction tuning ข้อมูล 1,000-10,000 ตัวอย่างเพียงพอ สำหรับ domain adaptation ข้อมูล 10,000-100,000 ตัวอย่างให้ผลดี คุณภาพสำคัญกว่าปริมาณ ข้อมูลที่ curated มาอย่างดี 1,000 ตัวอย่างอาจดีกว่าข้อมูลคุณภาพต่ำ 100,000 ตัวอย่าง
Q: สามารถรวม LoRA หลายตัวเข้าด้วยกันได้ไหม?
A: ได้ สามารถ stack LoRA adapters หลายตัวได้ เช่นมี base LoRA สำหรับ instruction following แล้วเพิ่ม domain LoRA สำหรับ medical knowledge นอกจากนี้ยังสามารถ merge LoRA กลับเข้า base model แล้ว fine-tune LoRA ใหม่อีกรอบได้ ทำให้สร้าง specialized models ได้หลากหลายจาก base model เดียว





