Fine-tuning
Fine-tuning là quá trình tinh chỉnh một pre-trained model trên dataset của riêng bạn để model hoạt động tốt hơn cho use case cụ thể.
📚 Bài viết liên quan:
- Generative AI - Pre-training, Fine-tuning, RLHF
- Prompt Engineering - Thay thế không cần fine-tune
- Embedding - Fine-tune embedding models
Khi nào cần Fine-tuning?
✅ Nên Fine-tune khi:
| Tình huống | Ví dụ |
|---|---|
| Cần style/tone đặc biệt | Chatbot với giọng điệu công ty |
| Domain knowledge chuyên sâu | Medical, Legal, Financial |
| Task lặp lại nhiều lần | Classify tickets, Extract data |
| Prompt Engineering không đủ | Output vẫn không đúng format |
| Giảm latency/cost | Dùng model nhỏ thay model lớn |
❌ Không nên Fine-tune khi:
| Tình huống | Lý do | Thay thế |
|---|---|---|
| Cần cập nhật data thường xuyên | Fine-tune tốn thời gian | RAG |
| Muốn model biết thông tin mới | Fine-tune không “dạy” facts | RAG |
| Budget/thời gian hạn chế | Fine-tune tốn resource | Prompt Engineering |
| Chưa thử các phương pháp khác | Có thể không cần fine-tune | Few-shot prompting |
So sánh các phương pháp
┌─────────────────────────────────────────────────────────────────┐
│ Prompt Engineering │
│ Nhanh, dễ, không tốn chi phí. Thử TRƯỚC KHI fine-tune. │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ RAG │
│ Kết hợp data riêng mà không cần train. Dùng cho facts mới. │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ Fine-tuning │
│ Thay đổi behavior của model. Dùng cho style, format, domain. │
└─────────────────────────────────────────────────────────────────┘Các loại Fine-tuning
1. Full Fine-tuning
Train lại toàn bộ parameters của model.
Pros:
✅ Kết quả tốt nhất
✅ Model adapt hoàn toàn
Cons:
❌ Cần GPU mạnh (nhiều VRAM)
❌ Dễ overfitting
❌ Tốn thời gian
❌ Chi phí cao2. LoRA (Low-Rank Adaptation)
Train thêm các adapter layers nhỏ, giữ nguyên model gốc.
Pros:
✅ Tiết kiệm VRAM (giảm ~10x)
✅ Train nhanh hơn
✅ Có thể switch giữa nhiều adapters
✅ Ít overfitting hơn
Cons:
❌ Kết quả có thể kém hơn full fine-tune
❌ Cần tune hyperparametersCách hoạt động:
Original weights: W (frozen)
LoRA adapters: A, B (trainable)
Output = W·x + A·B·x
Chỉ train A và B (rất nhỏ so với W)3. QLoRA
Kết hợp Quantization (giảm precision) + LoRA.
Pros:
✅ Cực kỳ tiết kiệm VRAM
✅ Fine-tune model 65B trên GPU 24GB
✅ Kết quả gần bằng full fine-tune
Cons:
❌ Chậm hơn 1 chút
❌ Setup phức tạp hơnFine-tuning với OpenAI
OpenAI cung cấp fine-tuning qua API, không cần GPU.
Models hỗ trợ
| Model | Use case | Cost (training) |
|---|---|---|
| gpt-4o-mini-2024-07-18 | Tốc độ, tiết kiệm | $3.00/1M tokens |
| gpt-4o-2024-08-06 | Hiệu năng cao | $25.00/1M tokens |
| gpt-3.5-turbo | Legacy | $8.00/1M tokens |
Chuẩn bị Dataset
Format JSONL:
{"messages": [{"role": "system", "content": "Bạn là trợ lý lập trình Python."}, {"role": "user", "content": "Viết hàm tính giai thừa"}, {"role": "assistant", "content": "```python\ndef factorial(n: int) -> int:\n if n <= 1:\n return 1\n return n * factorial(n - 1)\n```"}]}
{"messages": [{"role": "system", "content": "Bạn là trợ lý lập trình Python."}, {"role": "user", "content": "Viết hàm tính Fibonacci"}, {"role": "assistant", "content": "```python\ndef fibonacci(n: int) -> int:\n if n <= 1:\n return n\n return fibonacci(n-1) + fibonacci(n-2)\n```"}]}Training
from openai import OpenAI
client = OpenAI()
# 1. Upload file
file = client.files.create(
file=open("training_data.jsonl", "rb"),
purpose="fine-tune"
)
# 2. Tạo fine-tuning job
job = client.fine_tuning.jobs.create(
training_file=file.id,
model="gpt-4o-mini-2024-07-18",
hyperparameters={
"n_epochs": 3
}
)
# 3. Kiểm tra status
status = client.fine_tuning.jobs.retrieve(job.id)
print(status.status) # "running" → "succeeded"
# 4. Sử dụng fine-tuned model
response = client.chat.completions.create(
model="ft:gpt-4o-mini-2024-07-18:your-org::job-id",
messages=[
{"role": "user", "content": "Viết hàm sort list"}
]
)Best Practices
- Tối thiểu 50-100 examples cho mỗi use case
- Đa dạng examples - cover nhiều edge cases
- Quality > Quantity - data tốt quan trọng hơn nhiều data
- Consistent format - giữ format thống nhất
- Test trước với prompting - có thể không cần fine-tune
Fine-tuning với Open Source
Dùng Hugging Face Transformers + PEFT (Parameter-Efficient Fine-Tuning).
Setup
pip install transformers peft datasets accelerate bitsandbytesLoRA với Llama 2
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
import torch
# 1. Load model với quantization
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-2-7b-hf",
load_in_4bit=True,
device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-hf")
# 2. Cấu hình LoRA
lora_config = LoraConfig(
r=16, # Rank của adapter
lora_alpha=32, # Scaling factor
target_modules=["q_proj", "v_proj"], # Layers to adapt
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM"
)
# 3. Prepare model
model = prepare_model_for_kbit_training(model)
model = get_peft_model(model, lora_config)
# 4. Training (sử dụng Trainer hoặc custom loop)
# ...Sử dụng PEFT Model
from peft import PeftModel
# Load base model
base_model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-2-7b-hf",
load_in_4bit=True
)
# Load adapter
model = PeftModel.from_pretrained(base_model, "path/to/adapter")
# Inference
inputs = tokenizer("Hello, how are you?", return_tensors="pt")
outputs = model.generate(**inputs)
print(tokenizer.decode(outputs[0]))Fine-tuning Embedding Models
Tinh chỉnh embedding model cho domain cụ thể.
from sentence_transformers import SentenceTransformer, InputExample, losses
from torch.utils.data import DataLoader
# 1. Load model
model = SentenceTransformer('all-MiniLM-L6-v2')
# 2. Prepare data
train_examples = [
InputExample(texts=["Python tutorial", "Learn Python programming"], label=0.9),
InputExample(texts=["Python tutorial", "Best restaurants nearby"], label=0.1),
]
train_dataloader = DataLoader(train_examples, shuffle=True, batch_size=16)
# 3. Loss function
train_loss = losses.CosineSimilarityLoss(model)
# 4. Training
model.fit(
train_objectives=[(train_dataloader, train_loss)],
epochs=3,
warmup_steps=100
)
# 5. Save
model.save("my-fine-tuned-model")Đánh giá Fine-tuned Model
Metrics quan trọng
| Task | Metrics |
|---|---|
| Classification | Accuracy, F1, Precision, Recall |
| Generation | BLEU, ROUGE, Human eval |
| Embedding | Hit Rate, MRR, NDCG |
| Chat | Human preference, A/B testing |
Test set riêng biệt
# Chia data: 80% train, 10% validation, 10% test
# KHÔNG dùng test set trong quá trình training
from sklearn.model_selection import train_test_split
train, temp = train_test_split(data, test_size=0.2)
val, test = train_test_split(temp, test_size=0.5)A/B Testing với users
50% users → Base model
50% users → Fine-tuned model
Đo: Response quality, User satisfaction, Task completionChi phí ước tính
OpenAI Fine-tuning
Dataset: 1000 examples × ~500 tokens/example = 500K tokens
Epochs: 3
Total training tokens: 1.5M
Cost (gpt-4o-mini): 1.5M × $3/1M = $4.50
Cost (gpt-4o): 1.5M × $25/1M = $37.50
+ Inference cost (higher than base model)Self-hosted
GPU rental (A100 80GB): ~$2-3/hour
Training time: 4-8 hours
Total: $8-24
+ Infra costs (hosting, monitoring)Bài tập thực hành 🧪
Bài 1: Fine-tune với OpenAI
- Tạo 50-100 training examples (JSONL format)
- Upload và tạo fine-tuning job
- So sánh kết quả với base model
Bài 2: LoRA với Hugging Face
- Cài đặt environment với PEFT
- Fine-tune một small model (Phi-2, Gemma-2B…)
- Merge adapter và test inference
Bài 3: Fine-tune Embedding
- Tạo training pairs (similar, dissimilar)
- Fine-tune all-MiniLM-L6-v2
- So sánh search quality trước/sau
Tóm tắt
| Khái niệm | Ý nghĩa |
|---|---|
| Fine-tuning | Train thêm pre-trained model trên data riêng |
| Full Fine-tuning | Train tất cả parameters |
| LoRA | Train adapter nhỏ, giữ nguyên model |
| QLoRA | LoRA + Quantization (tiết kiệm VRAM) |
| PEFT | Thư viện Parameter-Efficient Fine-Tuning |
Quyết định tree
Cần customize model behavior?
│
├─ NO → Prompt Engineering / RAG
│
└─ YES → Có đủ budget & data?
│
├─ NO → Few-shot prompting
│
└─ YES → Fine-tuning
│
├─ API (OpenAI) → Không cần GPU
│
└─ Open Source → LoRA/QLoRABài tiếp theo: Quay lại RAG để xem cách kết hợp các kỹ thuật.
Last updated on