🎯 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?
Phần tiêu đề “Khi nào cần Fine-tuning?”✅ Nên Fine-tune khi:
Phần tiêu đề “✅ 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:
Phần tiêu đề “❌ 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
Phần tiêu đề “So sánh các phương pháp”flowchart TD START["🤔 Cần customize model?"] --> PE
subgraph PE["1️⃣ Prompt Engineering"] PE1["✅ Nhanh, dễ, không tốn chi phí<br/>Thử TRƯỚC KHI fine-tune"] end
PE --> RAG
subgraph RAG["2️⃣ RAG"] RAG1["✅ Kết hợp data riêng mà không cần train<br/>Dùng cho facts mới"] end
RAG --> FT
subgraph FT["3️⃣ Fine-tuning"] FT1["✅ Thay đổi behavior của model<br/>Dùng cho style, format, domain"] end
style PE fill:#e8f5e9,stroke:#4caf50 style RAG fill:#fff3e0,stroke:#ff9800 style FT fill:#e3f2fd,stroke:#2196f3Các loại Fine-tuning
Phần tiêu đề “Các loại Fine-tuning”1. Full Fine-tuning
Phần tiêu đề “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)
Phần tiêu đề “2. 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
Phần tiêu đề “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
Phần tiêu đề “Fine-tuning với OpenAI”OpenAI cung cấp fine-tuning qua API, không cần GPU.
Models hỗ trợ
Phần tiêu đề “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
Phần tiêu đề “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
Phần tiêu đề “Training”from openai import OpenAI
client = OpenAI()
# 1. Upload filefile = client.files.create( file=open("training_data.jsonl", "rb"), purpose="fine-tune")
# 2. Tạo fine-tuning jobjob = client.fine_tuning.jobs.create( training_file=file.id, model="gpt-4o-mini-2024-07-18", hyperparameters={ "n_epochs": 3 })
# 3. Kiểm tra statusstatus = client.fine_tuning.jobs.retrieve(job.id)print(status.status) # "running" → "succeeded"
# 4. Sử dụng fine-tuned modelresponse = 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
Phần tiêu đề “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
Phần tiêu đề “Fine-tuning với Open Source”Dùng Hugging Face Transformers + PEFT (Parameter-Efficient Fine-Tuning).
Setup
Phần tiêu đề “Setup”pip install transformers peft datasets accelerate bitsandbytesLoRA với Llama 2
Phần tiêu đề “LoRA với Llama 2”from transformers import AutoModelForCausalLM, AutoTokenizerfrom peft import LoraConfig, get_peft_model, prepare_model_for_kbit_trainingimport torch
# 1. Load model với quantizationmodel = 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 LoRAlora_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 modelmodel = 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
Phần tiêu đề “Sử dụng PEFT Model”from peft import PeftModel
# Load base modelbase_model = AutoModelForCausalLM.from_pretrained( "meta-llama/Llama-2-7b-hf", load_in_4bit=True)
# Load adaptermodel = PeftModel.from_pretrained(base_model, "path/to/adapter")
# Inferenceinputs = tokenizer("Hello, how are you?", return_tensors="pt")outputs = model.generate(**inputs)print(tokenizer.decode(outputs[0]))Fine-tuning Embedding Models
Phần tiêu đề “Fine-tuning Embedding Models”Tinh chỉnh embedding model cho domain cụ thể.
from sentence_transformers import SentenceTransformer, InputExample, lossesfrom torch.utils.data import DataLoader
# 1. Load modelmodel = SentenceTransformer('all-MiniLM-L6-v2')
# 2. Prepare datatrain_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 functiontrain_loss = losses.CosineSimilarityLoss(model)
# 4. Trainingmodel.fit( train_objectives=[(train_dataloader, train_loss)], epochs=3, warmup_steps=100)
# 5. Savemodel.save("my-fine-tuned-model")Đánh giá Fine-tuned Model
Phần tiêu đề “Đánh giá Fine-tuned Model”Metrics quan trọng
Phần tiêu đề “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
Phần tiêu đề “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
Phần tiêu đề “A/B Testing với users”50% users → Base model50% users → Fine-tuned model
Đo: Response quality, User satisfaction, Task completionChi phí ước tính
Phần tiêu đề “Chi phí ước tính”OpenAI Fine-tuning
Phần tiêu đề “OpenAI Fine-tuning”Dataset: 1000 examples × ~500 tokens/example = 500K tokensEpochs: 3Total training tokens: 1.5M
Cost (gpt-4o-mini): 1.5M × $3/1M = $4.50Cost (gpt-4o): 1.5M × $25/1M = $37.50
+ Inference cost (higher than base model)Self-hosted
Phần tiêu đề “Self-hosted”GPU rental (A100 80GB): ~$2-3/hourTraining time: 4-8 hoursTotal: $8-24
+ Infra costs (hosting, monitoring)Bài tập thực hành 🧪
Phần tiêu đề “Bài tập thực hành 🧪”Bài 1: Fine-tune với OpenAI
Phần tiêu đề “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
Phần tiêu đề “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
Phần tiêu đề “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
Phần tiêu đề “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
Phần tiêu đề “Quyết định tree”flowchart TD Q1{"🤔 Cần customize<br/>model behavior?"} -->|NO| PE["✅ Prompt Engineering / RAG"] Q1 -->|YES| Q2{"💰 Có đủ budget & data?"} Q2 -->|NO| FS["✅ Few-shot prompting"] Q2 -->|YES| FT["🎯 Fine-tuning"] FT --> Q3{"Chọn platform?"} Q3 --> API["☁️ API (OpenAI)<br/>Không cần GPU"] Q3 --> OS["🖥️ Open Source<br/>LoRA/QLoRA"]
style Q1 fill:#e3f2fd,stroke:#1976d2 style Q2 fill:#fff3e0,stroke:#ff9800 style FT fill:#f3e5f5,stroke:#9c27b0 style PE fill:#e8f5e9,stroke:#4caf50 style FS fill:#e8f5e9,stroke:#4caf50Bài tiếp theo: Quay lại RAG để xem cách kết hợp các kỹ thuật.