Skip to Content

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:


Khi nào cần Fine-tuning?

✅ Nên Fine-tune khi:

Tình huốngVí dụ
Cần style/tone đặc biệtChatbot với giọng điệu công ty
Domain knowledge chuyên sâuMedical, Legal, Financial
Task lặp lại nhiều lầnClassify tickets, Extract data
Prompt Engineering không đủOutput vẫn không đúng format
Giảm latency/costDùng model nhỏ thay model lớn

❌ Không nên Fine-tune khi:

Tình huốngLý doThay thế
Cần cập nhật data thường xuyênFine-tune tốn thời gianRAG
Muốn model biết thông tin mớiFine-tune không “dạy” factsRAG
Budget/thời gian hạn chếFine-tune tốn resourcePrompt Engineering
Chưa thử các phương pháp khácCó thể không cần fine-tuneFew-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í cao

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 hyperparameters

Cá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ơn

Fine-tuning với OpenAI

OpenAI cung cấp fine-tuning qua API, không cần GPU.

Models hỗ trợ

ModelUse caseCost (training)
gpt-4o-mini-2024-07-18Tốc độ, tiết kiệm$3.00/1M tokens
gpt-4o-2024-08-06Hiệu năng cao$25.00/1M tokens
gpt-3.5-turboLegacy$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

  1. Tối thiểu 50-100 examples cho mỗi use case
  2. Đa dạng examples - cover nhiều edge cases
  3. Quality > Quantity - data tốt quan trọng hơn nhiều data
  4. Consistent format - giữ format thống nhất
  5. 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 bitsandbytes

LoRA 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

TaskMetrics
ClassificationAccuracy, F1, Precision, Recall
GenerationBLEU, ROUGE, Human eval
EmbeddingHit Rate, MRR, NDCG
ChatHuman 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 completion

Chi 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

  1. Tạo 50-100 training examples (JSONL format)
  2. Upload và tạo fine-tuning job
  3. So sánh kết quả với base model

Bài 2: LoRA với Hugging Face

  1. Cài đặt environment với PEFT
  2. Fine-tune một small model (Phi-2, Gemma-2B…)
  3. Merge adapter và test inference

Bài 3: Fine-tune Embedding

  1. Tạo training pairs (similar, dissimilar)
  2. Fine-tune all-MiniLM-L6-v2
  3. So sánh search quality trước/sau

Tóm tắt

Khái niệmÝ nghĩa
Fine-tuningTrain thêm pre-trained model trên data riêng
Full Fine-tuningTrain tất cả parameters
LoRATrain adapter nhỏ, giữ nguyên model
QLoRALoRA + Quantization (tiết kiệm VRAM)
PEFTThư 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/QLoRA

Bài tiếp theo: Quay lại RAG để xem cách kết hợp các kỹ thuật.

Last updated on