Gemma 4 開箱即用就已經很厲害,但如果你需要它用你品牌的語調說話、遵循你特定的輸出格式,或在通用模型難以應付的利基領域表現出色呢?這就是微調派上用場的時候。
好消息:你不再需要一個 A100 叢集。使用 LoRA 和一個叫 Unsloth 的工具,你可以在不到一小時內在單張 GPU 上微調 Gemma 4。讓我們走完整個過程。
為什麼要微調?
在投入努力之前,確保微調真的是你需要的。以下是快速決策指南:
| 情況 | 解決方案 |
|---|---|
| 模型不了解你的領域 | 用領域資料微調 |
| 模型忽略你的輸出格式 | 用格式範例微調 |
| 模型需要更新的資訊 | 改用 RAG |
| 模型太冗長/太簡短 | 先試提示詞工程 |
| 模型有時給錯答案 | 先試 few-shot 提示 |
如果提示詞工程和 RAG 不足以解決問題,微調就是你的下一步。在深入之前,試試我們的最佳 Gemma 4 提示詞——你可能只用更好的提示就能解決問題。在開始自訂之前,更廣泛地了解 Gemma 4 能做什麼,可以查看我們的使用場景指南。
LoRA 和 QLoRA 簡單解釋
LoRA(低秩適配,Low-Rank Adaptation)不修改原始模型權重。相反,它訓練一小組 adapter 權重坐在基礎模型之上。把它想成在相機上裝一個自訂鏡頭,而不是重建整台相機。
- 基礎模型:凍結、不動
- Adapter:很小(通常是基礎模型大小的 1-5%)
- 結果:以一小部分成本達到接近完整微調的品質
QLoRA 更進一步——它以 4 位元量化形式載入基礎模型,將記憶體使用量減少約一半。你獲得 90%+ 的 LoRA 品質,同時能塞進更小的 GPU。
| 方法 | 所需 VRAM (Gemma 4 E4B) | 所需 VRAM (Gemma 4 26B) | 品質 |
|---|---|---|---|
| 完整微調 | 32GB+ | 100GB+ | 最佳 |
| LoRA | 16GB | 48GB | ~98% of full |
| QLoRA | 8GB | 24GB | ~95% of full |
設定 Unsloth
Unsloth 是用 LoRA 微調 Gemma 4 最快的方式。它將模型修補為訓練速度快 2 倍、記憶體使用量比原版 HuggingFace 少 60%。
# 建立虛擬環境
python -m venv gemma4-finetune
source gemma4-finetune/bin/activate
# 安裝 Unsloth(包含所有依賴)
pip install unsloth
# 對於較舊 GPU 的 QLoRA,還需安裝:
pip install bitsandbytes驗證你的設定:
import torch
print(f"CUDA available: {torch.cuda.is_available()}")
print(f"GPU: {torch.cuda.get_device_name(0)}")
print(f"VRAM: {torch.cuda.get_device_properties(0).total_mem / 1e9:.1f} GB")準備訓練資料
你的資料應為 JSONL 格式,每行包含一段對話。以下是 Gemma 4 預期的結構:
{"messages": [{"role": "user", "content": "What's the return policy?"}, {"role": "assistant", "content": "Our return policy allows returns within 30 days of purchase with original receipt."}]}
{"messages": [{"role": "user", "content": "Do you ship internationally?"}, {"role": "assistant", "content": "Yes, we ship to 45 countries. Shipping takes 7-14 business days."}]}
{"messages": [{"role": "system", "content": "You are a medical coding assistant."}, {"role": "user", "content": "Code: Patient presents with acute bronchitis"}, {"role": "assistant", "content": "ICD-10: J20.9 - Acute bronchitis, unspecified"}]}資料品質技巧:
- 500-1000 個範例對大多數任務是最佳點
- 不一定越多越好——500 個高品質範例勝過 5000 個草率的
- 包含邊界情況和負面範例
- 保持回應在格式和語氣上一致
- 訓練前驗證你的 JSONL:
import json
def validate_jsonl(filepath):
valid = 0
errors = 0
with open(filepath, 'r') as f:
for i, line in enumerate(f, 1):
try:
data = json.loads(line)
assert "messages" in data, "Missing 'messages' key"
assert len(data["messages"]) >= 2, "Need at least 2 messages"
valid += 1
except (json.JSONDecodeError, AssertionError) as e:
print(f"Line {i}: {e}")
errors += 1
print(f"\nValid: {valid}, Errors: {errors}")
validate_jsonl("training_data.jsonl")訓練設定
以下是使用 Unsloth 的完整訓練腳本:
from unsloth import FastLanguageModel
import torch
# 用 QLoRA(4-bit)載入模型
model, tokenizer = FastLanguageModel.from_pretrained(
model_name="google/gemma-4-e4b",
max_seq_length=4096,
dtype=None, # 自動偵測
load_in_4bit=True, # QLoRA
)
# 加入 LoRA adapters
model = FastLanguageModel.get_peft_model(
model,
r=16, # Rank——越高 = 容量越大,VRAM 越多
target_modules=[
"q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj",
],
lora_alpha=16,
lora_dropout=0, # Unsloth 最佳化——保持 0
bias="none",
use_gradient_checkpointing="unsloth",
)
# 載入訓練資料
from datasets import load_dataset
dataset = load_dataset("json", data_files="training_data.jsonl", split="train")
# 訓練參數
from trl import SFTTrainer
from transformers import TrainingArguments
trainer = SFTTrainer(
model=model,
tokenizer=tokenizer,
train_dataset=dataset,
max_seq_length=4096,
args=TrainingArguments(
per_device_train_batch_size=2,
gradient_accumulation_steps=4,
warmup_steps=10,
num_train_epochs=3,
learning_rate=2e-4,
fp16=not torch.cuda.is_bf16_supported(),
bf16=torch.cuda.is_bf16_supported(),
logging_steps=10,
output_dir="outputs",
optim="adamw_8bit",
seed=42,
),
)
# 訓練
trainer.train()
# 儲存 LoRA adapter
model.save_pretrained("gemma4-finetuned-lora")
tokenizer.save_pretrained("gemma4-finetuned-lora")要調的關鍵參數:
r=16:LoRA rank。從 16 開始,如果品質不夠就調到 32 或 64num_train_epochs=3:通常 2-5 就夠了。注意過擬合learning_rate=2e-4:預設通常好用。訓練不穩定時降到 1e-4per_device_train_batch_size=2:如果有 VRAM 剩餘就增加
匯出為 GGUF
adapter 訓練完後,你大概會想用 Ollama 在本機執行它。這意味著轉換為 GGUF 格式。想詳細了解量化選項和它們的取捨,請看我們的 GGUF 指南。
# 合併 adapter 並匯出為 GGUF(Q4_K_M 量化)
model.save_pretrained_gguf(
"gemma4-finetuned-gguf",
tokenizer,
quantization_method="q4_k_m",
)
# 或以多種量化層級匯出
for method in ["q4_k_m", "q5_k_m", "q8_0"]:
model.save_pretrained_gguf(
f"gemma4-finetuned-{method}",
tokenizer,
quantization_method=method,
)| 量化 | 檔案大小(E4B) | 品質損失 | 最適合 |
|---|---|---|---|
| Q4_K_M | ~2.5 GB | 最小 | 大多數使用者 |
| Q5_K_M | ~3.2 GB | 非常小 | 重視品質 |
| Q8_0 | ~4.8 GB | 可忽略 | VRAM 充足時 |
用 Ollama 部署
建立 Modelfile 將你的微調模型帶進 Ollama:
# Modelfile
FROM ./gemma4-finetuned-gguf/gemma4-finetuned-q4_k_m.gguf
PARAMETER temperature 0.7
PARAMETER top_p 0.9
SYSTEM "You are a helpful assistant fine-tuned for customer support."然後建構並執行:
# 建立自訂模型
ollama create my-gemma4 -f Modelfile
# 測試
ollama run my-gemma4 "What's your return policy?"
# 驗證已列出
ollama list你的微調模型現在執行起來與任何其他 Ollama 模型完全相同。你可以搭配 Ollama API 使用、在其上建構應用,或與你的團隊分享。
常見問題和修復
訓練期間記憶體不足: 將 per_device_train_batch_size 降到 1、啟用 gradient_checkpointing,或切換到較小的基礎模型。
微調後模型輸出亂碼: 你的資料可能有格式問題,或你訓練了太多 epoch。減少 epoch 並驗證你的 JSONL。
GGUF 匯出失敗: 確保你有足夠的磁碟空間(轉換期間需要模型大小的 3-5 倍)並且你的 Unsloth 版本是最新的。
訓練損失不下降: 學習率可能太低。試試 5e-4。也檢查你的資料是否真的有你希望模型學習的模式。
下一步
- 探索 Gemma 4 模型大小 為微調挑選最佳基礎模型
- 為你的微調模型設定合適的部署流水線
- 了解結構化 JSON 輸出 將微調與可靠的輸出格式結合
- 查看硬體需求 規劃你的訓練設定
Stop reading. Start building.
~/gemma4 $ Get hands-on with the models discussed in this guide. No deployment, no friction, 100% free playground.
Launch Playground />


