Gemma 4 が公開されてから、「自分のデータでファインチューニングしてみたい」という声をよく聞きます。でも実際に始めようとすると、「どこから手をつければいいのか」「どのくらいのGPUが必要なのか」という疑問で詰まってしまうことが多いようです。
ここでは無料で使える Google Colab(T4 GPU)と本番環境向けの Vertex AI の両方で Gemma 4 をファインチューニングする方法を、実装コードと一緒に説明します。私自身、2014年から個人開発を続けてきた中で「学習は一度きりの儀式ではなく、データを直して回し直す日常作業」だと感じるようになりました。その回し直しのしやすさを基準に手順を組んでいます。特に、少ないGPUメモリでもファインチューニングを実現する QLoRA の使い方に焦点を当てています。
ファインチューニングが必要な場面と不要な場面
まず、ファインチューニングが本当に必要なのかを確認しておきましょう。
ファインチューニングが有効な場面として、特定のドメイン・業界の専門用語や表現パターンを学習させたい場合、一貫したフォーマットや文体でレスポンスを生成させたい場合、そしてプロンプトエンジニアリングだけでは達成できない精度が必要な場合が挙げられます。
一方で、プロンプトエンジニアリングで対応できる場面では、ファインチューニングのコストと手間をかける必要はありません。まずは Few-shot プロンプティングや System Instructions の工夫を試してみることをお勧めします。
QLoRAとは:少ないメモリでファインチューニングする仕組み
Gemma 4 のフルファインチューニングには大量のGPUメモリが必要ですが、QLoRA(Quantized Low-Rank Adaptation) を使うことで、はるかに少ないメモリで同等の効果を得られます。
仕組みを簡単に説明すると、QLoRA は元のモデルの重みを4ビット量子化(通常の32ビットの1/8のメモリ)で圧縮した上で、更新する重みを「低ランク行列」という小さなアダプター層に限定します。これにより、16GBのVRAMで70億パラメータのモデルをファインチューニングできます。
環境準備:Google Colabでの設定
Google Colab の T4 GPU(無料枠)で始める場合の設定です。
# 必要なライブラリのインストール
\!pip install transformers datasets peft trl bitsandbytes accelerate -q
import torch
from transformers import (
AutoModelForCausalLM,
AutoTokenizer,
BitsAndBytesConfig,
TrainingArguments
)
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
from trl import SFTTrainer
from datasets import Dataset
# GPU確認
print(f"GPU: {torch.cuda.get_device_name(0)}")
print(f"VRAM: {torch.cuda.get_device_properties(0).total_memory / 1024**3:.1f} GB")Gemma 4のロードと量子化設定
MODEL_NAME = "google/gemma-4-2b-it" # 2Bモデル(Colabの無料GPUで動作)
# 4ビット量子化の設定
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4", # NF4量子化(QLoRAの推奨設定)
bnb_4bit_compute_dtype=torch.bfloat16, # 計算はbfloat16で
bnb_4bit_use_double_quant=True, # メモリをさらに節約する二重量子化
)
# モデルのロード
model = AutoModelForCausalLM.from_pretrained(
MODEL_NAME,
quantization_config=bnb_config,
device_map="auto", # 利用可能なGPU/CPUに自動割り当て
trust_remote_code=True
)
# トークナイザーのロード
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, trust_remote_code=True)
tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "right"
# QLoRAのためにモデルを準備
model = prepare_model_for_kbit_training(model)
print(f"モデルロード完了: {MODEL_NAME}")LoRAアダプターの設定
# LoRA設定
lora_config = LoraConfig(
r=16, # ランク:小さいほどパラメータ数が少ない(推奨: 8〜64)
lora_alpha=32, # スケーリング係数(通常は r の2倍)
target_modules=[ # LoRAを適用するモジュール
"q_proj", "k_proj", "v_proj", "o_proj", # Attention
"gate_proj", "up_proj", "down_proj" # FFN
],
lora_dropout=0.05, # ドロップアウト率
bias="none", # バイアスは更新しない
task_type="CAUSAL_LM" # 因果言語モデルタスク
)
model = get_peft_model(model, lora_config)
# 学習可能なパラメータ数を確認
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
total_params = sum(p.numel() for p in model.parameters())
print(f"学習可能パラメータ: {trainable_params:,} ({100*trainable_params/total_params:.2f}%)")
# 例: 学習可能パラメータ: 3,407,872 (0.17%)LoRA のランク(r)は精度とメモリのトレードオフを制御します。8〜16で始めて、品質が不十分なら32〜64に増やすというアプローチが実用的です。
データセットの準備
ファインチューニングには、タスクに特化したデータセットが必要です。ここでは、カスタマーサポート用の QA ペアを例に説明します。
# データセットの例(実際はCSVやJSONから読み込む)
raw_data = [
{
"instruction": "商品の返品方法を教えてください",
"response": "ご購入から30日以内であれば返品を承っております。お問い合わせフォームからご連絡ください。"
},
{
"instruction": "配送にどのくらいかかりますか?",
"response": "通常配送は3〜5営業日、速達は翌営業日にお届けします。"
},
# ... 実際には最低500〜1000件以上のデータが必要
]
def format_instruction(example: dict) -> str:
"""Gemma 4のInstruct形式にフォーマット"""
return f"""<start_of_turn>user
{example['instruction']}<end_of_turn>
<start_of_turn>model
{example['response']}<end_of_turn>"""
# データセットの変換
formatted_data = [
{"text": format_instruction(item)}
for item in raw_data
]
dataset = Dataset.from_list(formatted_data)
# 訓練/検証に分割(80/20)
split_dataset = dataset.train_test_split(test_size=0.2, seed=42)
train_dataset = split_dataset["train"]
eval_dataset = split_dataset["test"]
print(f"訓練データ: {len(train_dataset)}件")
print(f"検証データ: {len(eval_dataset)}件")ファインチューニングの実行
# 学習設定
training_args = TrainingArguments(
output_dir="./gemma4-finetuned",
num_train_epochs=3,
per_device_train_batch_size=4, # T4 GPU(16GB)の場合
per_device_eval_batch_size=4,
gradient_accumulation_steps=4, # 実効バッチサイズ = 4 × 4 = 16
learning_rate=2e-4,
weight_decay=0.001,
fp16=True, # T4 は bfloat16 非対応のため fp16 を使う
bf16=False, # A100/L4 など Ampere 以降なら bf16=True に
max_grad_norm=0.3,
warmup_ratio=0.03,
lr_scheduler_type="cosine",
evaluation_strategy="steps",
eval_steps=100,
save_strategy="steps",
save_steps=100,
logging_steps=25,
load_best_model_at_end=True,
report_to="none", # W&BやTensorBoardを使わない場合
)
一点、見落としやすい注意があります。Colab 無料枠の T4 GPU は **bfloat16 に対応していません**(bf16 は Ampere 世代以降)。`bf16=True` のまま走らせるとエラーになるか自動で無効化されるので、T4 では `fp16=True` を使います。A100 や L4 に切り替えた時だけ `bf16=True` に戻すと数値的に安定します。同じ理由で、量子化設定の `bnb_4bit_compute_dtype` も T4 では `torch.float16` にしておく方が安全です。
# トレーナーの設定
trainer = SFTTrainer(
model=model,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
peft_config=lora_config,
dataset_text_field="text",
max_seq_length=1024,
tokenizer=tokenizer,
args=training_args,
packing=False, # データのパッキングなし(品質優先)
)
# 学習開始
trainer.train()
trainer.save_model("./gemma4-finetuned-final")
print("✅ ファインチューニング完了")Colab の切断対策 — チェックポイントは Drive に
無料枠の Colab はセッションが予告なく切れます。output_dir をローカル(./gemma4-finetuned)にしたまま切断されると、数時間の学習が消えます。Google Drive をマウントして、チェックポイントを Drive 側に書くようにしておくと、切断されても resume_from_checkpoint で続きから再開できます。
from google.colab import drive
drive.mount('/content/drive')
# output_dir を Drive 配下に変更
training_args.output_dir = "/content/drive/MyDrive/gemma4-finetuned"
# 切断後の再開
trainer.train(resume_from_checkpoint=True)私はこの設定を最初の学習でやっておらず、2時間分の学習を一度失いました。save_steps=100 と Drive 保存はセットで「最初に」設定しておくことを強くお勧めします。
Vertex AIでのスケールアップ
Google Colab は無料で試せますが、本番用途や大規模なファインチューニングには Vertex AI を使います。
from google.cloud import aiplatform
aiplatform.init(project="YOUR_PROJECT_ID", location="us-central1")
# カスタムトレーニングジョブの作成
job = aiplatform.CustomTrainingJob(
display_name="gemma4-fine-tuning",
script_path="train.py", # 上記の学習スクリプトをファイルに保存
container_uri="us-docker.pkg.dev/vertex-ai/training/pytorch-gpu.2-2:latest",
requirements=["transformers", "peft", "trl", "bitsandbytes", "datasets"]
)
# A100 GPU(80GB)を使用した学習の開始
model = job.run(
machine_type="a2-highgpu-1g", # A100 1枚
accelerator_type="NVIDIA_TESLA_A100",
accelerator_count=1,
replica_count=1,
args=["--model_name", "google/gemma-4-9b-it", # 9Bモデル(A100なら動作)
"--epochs", "3",
"--output_dir", "gs://YOUR_BUCKET/gemma4-finetuned"]
)ファインチューニング済みモデルの評価と推論
from peft import PeftModel
# ベースモデルにアダプターを統合して推論
base_model = AutoModelForCausalLM.from_pretrained(
MODEL_NAME,
quantization_config=bnb_config,
device_map="auto"
)
finetuned_model = PeftModel.from_pretrained(base_model, "./gemma4-finetuned-final")
finetuned_model = finetuned_model.merge_and_unload() # アダプターをマージ
def generate_response(prompt: str, max_new_tokens: int = 256) -> str:
formatted = f"<start_of_turn>user\n{prompt}<end_of_turn>\n<start_of_turn>model\n"
inputs = tokenizer(formatted, return_tensors="pt").to("cuda")
with torch.no_grad():
outputs = finetuned_model.generate(
**inputs,
max_new_tokens=max_new_tokens,
temperature=0.7,
do_sample=True,
pad_token_id=tokenizer.eos_token_id
)
generated_ids = outputs[0][inputs["input_ids"].shape[1]:]
return tokenizer.decode(generated_ids, skip_special_tokens=True)
# 推論テスト
response = generate_response("返品期間はいつまでですか?")
print(response)ファインチューニングのコストと時間の目安
参考として、典型的なファインチューニングに必要なリソースをまとめます。
Google Colab(T4 GPU・無料枠)では、Gemma 4 2B モデル・500件のデータセット・3エポックで約1〜2時間かかります。コストは無料(ただし連続利用に制限あり)です。
Vertex AI(A100 80GB)では、Gemma 4 9B モデル・5,000件のデータセット・3エポックで約3〜5時間かかります。コストは $15〜$30 程度(2026年4月現在の Vertex AI 料金)です。
Gemma 4 のファインチューニングは、QLoRA のおかげで以前より大幅に手軽になりました。まずは Colab の無料環境で小さなデータセットで試して、効果を確認してから本番環境に移行するアプローチが最も実用的です。
学習後の確認は、学習データの「言い換え」を投げて応答スタイルが保たれるかで判断します。データそのままの質問に答えられても汎化の証明にはなりません。500件規模では過学習が早いので、検証 loss が上がり始めたらエポックを減らすサインです。
Mac (Apple Silicon) をお使いの方は、Colab に頼らずローカルで完結させる選択肢もあります。手順は Gemma 4 を Mac でファインチューニングする MLX 実践ガイドにまとめました。クラウドとローカル、両方の選択肢を持っておくと、データの機密度に応じて使い分けられます。みなさまの学習がうまく回り始めることを願っています。