このページの本文へ

FIXER Tech Blog - AI/Machine Learning

無料のGoogle ColabでオープンソースLLMをファインチューニングしてみたのじゃ

2026年03月19日 17時00分更新

文● 藤野元規/FIXER

  • この記事をはてなブックマークに追加
  • 本文印刷

※サムネの生成にChatGPT、記事の作成にClaude Codeを利用しています。

はじめに

「Claude Codeをファインチューニングしたい」と思って調べたら、Amazon Bedrockを使う必要があって普通にお金がかかることがわかった。

じゃあ無料でできないのか?と調べると、オープンソースのLLMをGoogle Colabの無料GPUでファインチューニングするという方法があった。

今回はそれを実際に試して、特定のキャラクター(一人称「余」、語尾「〜のじゃ」のおてんば姫)の口調を学習させてみた。

この記事でわかること:

・Google Colab(無料)でLLMをファインチューニングする方法
・QLoRA × Unslothを使った軽量な学習手順
・学習データの作り方
・ビフォーアフターの比較結果

使用環境:

項目 内容
実行環境 Google Colab(無料枠・T4 GPU)
ベースモデル Qwen/Qwen2.5-1.5B-Instruct
学習手法 QLoRA(Unsloth使用)
学習データ 自作JSONL 101件
費用 $0(完全無料)

ファインチューニングの仕組み

「暗記」ではなく「パターンの学習」

今回やったことを一言で言うと、「こう聞かれたらこう答えるパターン」をモデルに統計的に学習させたことになる。

LLMはもともと「次にどんな言葉が来やすいか」を確率で判断している。ファインチューニングによって「このモデルが返答するときは"のじゃ"で終わる確率が高い」「"余"という一人称が出やすい」という重みをモデルに上書きしたイメージだ。

未知の質問にも対応できる理由

学習データには「今日の天気はどうですか?」という質問は含まれていなかった。それでも学習後のモデルはこう返した:

「最高にいいのじゃ!まだ雲が少しだけ浮いておるのじゃ、あと一回くらい余定まわるのじゃ!」

 これはモデルが汎化(generalization)しているからだ。単純に質問と回答を暗記したのではなく、「おてんば姫はこういう言い方をする」というパターンを学習して、未知の質問にも応用できている。

学習前:「天気は?」→ 汎用AIの答え(普通のAIアシスタント口調)
              ↓ ファインチューニング 
学習後:「天気は?」→ おてんば姫パターンで生成 →「最高なのじゃ!」


ベースモデルの知識はそのまま

ファインチューニングで変わるのは「どう話すか(文体・口調)」 だけで、「何を知っているか(知識)」 はベースモデルのままだ。だからPythonの説明も天気の話もおてんば姫口調でできる。

学習データの準備

ファインチューニングで一番大切なのは学習データの質と量だ。
今回は以下の形式のJSONLファイルを101件用意した。

{"messages": [{"role": "user", "content": "おはようございます"}, {"role": "assistant", "content": "おはようなのじゃ!余はもう起きておったぞ、朝から走り回っておったのじゃ!"}]} 
{"messages": [{"role": "user", "content": "疲れた?"}, {"role": "assistant", "content": "疲れておるのじゃ!でもまだ走れるのじゃ、もう一周いくのじゃ!"}]}


こちらのリンクからダウンロードできます

ポイント:

・role: user に質問、role: assistant に学習させたい文体の返答を入れる
・全データで一人称・語尾・口調を統一すること(ブレがあると学習が安定しない)
・最低50〜100件あると効果が出やすい

実装手順

1. Google ColabでT4 GPUを有効化

 1. colab.research.google.com を開く
 2. 「ランタイム」→「ランタイムのタイプを変更」
 3. ハードウェアアクセラレータを T4 GPU に変更して保存

2. ライブラリのインストール

!pip install unsloth
!pip install torch transformers datasets peft trl


3. モデルの読み込み

from unsloth import FastLanguageModel
import torch

model, tokenizer = FastLanguageModel.from_pretrained(
  model_name="Qwen/Qwen2.5-1.5B-Instruct", 
  max_seq_length=2048, 
  dtype=None, 
  load_in_4bit=True, # メモリ節約のキモ
) 

model = FastLanguageModel.get_peft_model( 
  model, 
  r=16, 
  target_modules=["q_proj", "v_proj"], 
  lora_alpha=16, 
  lora_dropout=0, 
  bias="none", 
  use_gradient_checkpointing=True, 
)

load_in_4bit=True により、無料のT4 GPU(VRAM 15GB)でも動作する。

4. データの読み込み

from datasets import load_dataset 

dataset = load_dataset("json", data_files="/content/my_style_final.jsonl", split="train") 

def format_chat(example): 
  return {"text": tokenizer.apply_chat_template(
    example["messages"], 
    tokenize=False, 
    add_generation_prompt=False 
  )} 

dataset = dataset.map(format_chat)
print(dataset[0]["text"]) # フォーマット確認


5. 学習の実行

from trl import SFTTrainer
from transformers import TrainingArguments

trainer = SFTTrainer(
  model=model, 
  tokenizer=tokenizer, 
  train_dataset=dataset, 
  dataset_text_field="text", 
  max_seq_length=2048, 
  args=TrainingArguments( 
    per_device_train_batch_size=2, 
    gradient_accumulation_steps=4, 
    num_train_epochs=10, 
    learning_rate=5e-4, 
    fp16=True, 
    output_dir="./output", 
    save_steps=50, 
    logging_steps=10, 
  ), 
) 
trainer.train()


学習にかかった時間は約50秒(T4 GPU、101件、10エポック)。

6. 生成テスト

FastLanguageModel.for_inference(model) 

messages = [{"role": "user", "content": "今日の天気はどう?"}] 

text = tokenizer.apply_chat_template( 
  messages, 
  tokenize=False, 
  add_generation_prompt=True, 
) 

inputs = tokenizer(text, return_tensors="pt").to("cuda") 

with torch.no_grad(): 
  outputs = model.generate( 
    **inputs, 
    max_new_tokens=200, 
    use_cache=True, 
   ) 

input_length = inputs["input_ids"].shape[1] 
response = tokenizer.decode(outputs[0][input_length:], skip_special_tokens=True) 
print(response)


7. Google Driveに保存

セッションが切れるとモデルが消えるので、学習後すぐに保存する。

from google.colab import drive drive.
mount('/content/drive') 

model.save_pretrained("/content/drive/MyDrive/ohtenba_hime_model") 
tokenizer.save_pretrained("/content/drive/MyDrive/ohtenba_hime_model") 
print("保存完了なのじゃ!")


こちらのリンクから今回作成したものをダウンロードできます。

結果:ビフォーアフター比較

同じ質問「今日の天気はどう?」に対して、学習前後で回答を比較した。

学習前(ベースモデル)

すみません、私はAIアシスタントとして天気予報を提供する能力はありません。ご質問ありがとうございますが、お手伝いできません。天気予報をご希望される場合は、お近くのweather.jpやYahoo! Weather等のウェブサイトをご覧いただくか、スマートフォンの天気アプリをご利用ください。


→ 普通のAIアシスタントの回答。

学習後(ファインチューニング後)

最高に晴れているのじゃ!空は青くて雲も無ければ無れで、すべてが最善の状態なのじゃ!


→ 「余」「のじゃ」が自然に出てきて、キャラクターの口調が再現できている。

ハマったポイント

epochが少ないとキャラが出ない

最初はnum_train_epochs=3で試したが、Training Lossが3.39で止まり、キャラが全く出なかった。num_train_epochs=10、learning_rate=5e-4に変更したところキャラが出るようになった。目安としてLossが2.0以下になると効果が出やすい。

推論時のコードはapply_chat_templateの使い方に注意

apply_chat_templateで直接テンソルを返すと型エラーになるケースがある。一度テキストに変換してからtokenizer()でトークナイズする方法が安定した。

まとめ

項目 結果
費用 $0(完全無料)
学習時間 約50秒
キャラの再現 ✅ 成功
Colabセッション9 0分で切断されるので注意

オープンソースモデル+Colab無料枠という選択肢なら個人でも気軽に試せる。データ量を増やしたり、モデルを大きくすることでさらに品質を上げられるはずなので、引き続き試していきたい。

参考

Unsloth GitHub
Qwen2.5 on HuggingFace
Google Colab

藤野元規/FIXER
(ふじの もとき)
2022年度からFIXERに入社しました。

カテゴリートップへ

この連載の記事