0% read

如何用 LoRA 微調 Gemma 4(逐步教學)

Apr 7, 2026

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+最佳
LoRA16GB48GB~98% of full
QLoRA8GB24GB~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 或 64
  • num_train_epochs=3:通常 2-5 就夠了。注意過擬合
  • learning_rate=2e-4:預設通常好用。訓練不穩定時降到 1e-4
  • per_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。也檢查你的資料是否真的有你希望模型學習的模式。

下一步

gemma4 — interact

Stop reading. Start building.

~/gemma4 $ Get hands-on with the models discussed in this guide. No deployment, no friction, 100% free playground.

Launch Playground />
Gemma 4 AI

Gemma 4 AI

Related Guides

如何用 LoRA 微調 Gemma 4(逐步教學) | 部落格