【初学者向け】無料版 Google Colab でローカルLLM をファインチューニングする

 こんにちは、飯塚 LSS の菅原です!

 今回は、無料版 Google Colab を使って、ローカル LLM を自分の好きなデータでカスタマイズ(ファインチューニング)する方法を解説します。🤖🛠️

  • この記事で達成すること
    Google Colab(無料版)環境で、特定の LLM をファインチューニングし、独自のキャラクターやタスクに対応させる
  • 想定する読者
    LLM のカスタマイズに興味があるけれど、GPU環境が手元にない人
  • 必要な前提知識
    • 基本的な Python の操作
    • Google アカウント
  • 参考書籍
    • クジラ飛行机,『PythonでまなぶローカルLLMの訓練と使いこなし』, ソシム株式会社, 2025.9. [図書館所在]
    • 参考 Colab Notebook

事前知識:ファインチューニングとは?

 ファインチューニング(Fine-Tuning)とは、既存の AI モデルをベースに、新しい特定のデータセットを用いて追加学習を行う手法のことです。これにより、特定のタスクにおけるモデルの性能向上が可能になります。

 ファインチューニングの手法は、大きく分けて次の2つに分類されます。

手法名 概要 メリット / デメリット
フルファインチューニング ベースモデルのすべてのパラメータを再学習する。 ⭕️ 自由度が極めて高い
❌ 膨大なVRAM(グラフィックメモリ)と莫大な計算コストが必要
パラメータ効率化ファインチューニング(PEFT/Parameter-Efficient Fine-Tuning) ベースモデルの一部のパラメータを再学習する。 ⭕️ 低リソース・短時間で学習可能

 PEFT の代表的な手法として、LoRA(Low-Rank Adaption)があります。今回は LoRA と 量子化技術を組み合わせた QLoRA を使い効率的なファインチューニングを実施したいと思います。

ファインチューニングの全体像

 以下の手順に沿ってファインチューニングを行っていきます。

  1. 必要ライブラリのインストール
  2. モデルとトークナイザーの読み込み
  3. LoRA の設定
  4. データセットの準備
  5. トレーニングの実行
  6. 推論テスト
  7. モデルの保存と共有

1. 必要ライブラリのインストール

 まずは、依存関係を考慮しながら、ライブラリを一括インストールします。

 ファインチューニングには unsloth と呼ばれるフレームワークを使用します。これは QLoRA(LoRA + 量子化)を使い効率的なファインチューニングを可能とするフレームワークです。

 📌 補足:unsloth でファインチューニング可能なモデル(と対応する Colab Notebooks)は GitHub から確認することができます。 

Python

import os
!pip install --no-deps bitsandbytes accelerate xformers==0.0.29.post3 peft trl==0.15.2 triton cut_cross_entropy unsloth_zoo torchao==0.17.0
!pip install sentencepiece protobuf "datasets>=3.4.1" huggingface_hub hf_transfer
!pip install --no-deps unsloth

2. モデルとトークナイザーの読み込み

 ベースとなる LLM モデルを読み込みます。今回は Meta 社が開発した Meta-Llama-3.1-8B を 4bit 量子化してロードします。

Python

from unsloth import FastLanguageModel
import torch
model, tokenizer = FastLanguageModel.from_pretrained(
    model_name = "unsloth/Meta-Llama-3.1-8B",
    max_seq_length = 2048, # モデルが一度に処理できる最大トークン数
    dtype = None, # モデルの計算に使うデータの型(None: GPUに最適な型を自動判別)
    load_in_4bit = True, # 4bit量子化
)

3. LoRA の設定

 全体ではなく、モデルの一部の層のみ再学習を行うように設定します。

Python

model = FastLanguageModel.get_peft_model(
    model,
    r = 16, # LoRA のランク。8~64が推奨値。
    target_modules = ["q_proj", "k_proj", "v_proj", "o_proj",
                      "gate_proj", "up_proj", "down_proj",], # ファインチューニングの対象とする層
    lora_alpha = 16, # スケーリング係数。学習内容を元のモデルにどれくらい強く反映させるかを決める
    lora_dropout = 0, # 過学習を防ぐためのドロップアウト率
    bias = "none",
    # [NEW] "unsloth" uses 30% less VRAM, fits 2x larger batch sizes!
    use_gradient_checkpointing = "unsloth", # True or "unsloth" for very long context
)

4. データセットの準備

 今回は Hugging Face 上で公開されているデータセットを amaydle/npc-dialogue を使用します。これにはアニメやゲーム、映画のキャラクター(ナルト、ルフィ、悟空等)になりきった対話データが含まれており、モデルに「特定のキャラクターっぽい口調」を学習させるのに最適です。

 📌 補足:自作でデータセットを作成したい方は、こちらの GitHub にわかりやすいサンプルコードがありますので、ぜひ参考にしてください。

Python

from datasets import load_dataset
ds = load_dataset("amaydle/npc-dialogue", split="train")

 LLM を学習させる際には、どのように学習データを示すのかが重要になります。今回は「キャラクターの説明(Biography)」「ユーザからの問いかけ(Query)」「キャラクターの返答(Response)の 3 つのセットを見せる関数を実装し、データセット全体に適用します。

Python

prompt_format = """Below is a conversation with a fictional character. Assume the persona described in the biography and reply appropriately.

### Biography/Context:
{}

### Instruction/Query:
{}

### Response:
{}"""

EOS_TOKEN = tokenizer.eos_token # 文の終わりを示す特殊トークン

def formatting_prompts_func(examples):
        biographies = examples["Biography"]
        queries     = examples["Query"]
        responses   = examples["Response"]
        texts = []
        for biography, query, response in zip(biographies, queries, responses):
            text = prompt_format.format(biography, query, response) + EOS_TOKEN
            texts.append(text)
        return { "text" : texts, }

# データセット全体に一括適用(map関数)
ds = ds.map(formatting_prompts_func, batched = True)

5. トレーニングの実行

 データの準備ができたら、LLMのトレーニング用ライブラリTRA(Transformer Reinforcement Learning)の SFTTrainer (Supervised Fine Tuning Trainer)を使って追加学習を行います。今回は、学習の最大ステップ数を max_steps = 500 に設定して実行します(無料版の T4 GPU 環境で 30 分ほどで完了します)。

Python

from trl import SFTTrainer
from transformers import TrainingArguments
from unsloth import is_bfloat16_supported

trainer = SFTTrainer(
    model = model,
    tokenizer = tokenizer,
    train_dataset = ds,
    dataset_text_field = "text",
    max_seq_length = 2048,
    dataset_num_proc = 2,
    packing = False, # Can make training 5x faster for short sequences.
    args = TrainingArguments(
        per_device_train_batch_size = 2,
        gradient_accumulation_steps = 4,
        warmup_steps = 5,
        # num_train_epochs = 1, # Set this for 1 full training run.
        max_steps = 500,
        learning_rate = 2e-4,
        fp16 = not is_bfloat16_supported(),
        bf16 = is_bfloat16_supported(),
        logging_steps = 1,
        optim = "adamw_8bit",
        weight_decay = 0.01,
        lr_scheduler_type = "linear",
        seed = 3407,
        output_dir = "outputs",
        report_to = "none", # Use this for WandB etc
    ),
)
trainer_stats = trainer.train()

6. 推論テスト

 学習が完了したら、本当にモデルがキャラクターの性質やルールを掴めたのかをテストします。 確認する際は、ファインチューニング時と全く同じ形式のプロンプト(prompt_format)を使って質問を投げます。

 今回は、ワーナー・ブラザーズのアニメーション『ルーニー・テューンズ』に登場するウサギ「Bugs Bunny(バックス・バニー)」の設定(Biography)を渡してテストを行います。🐰🥕

Python

FastLanguageModel.for_inference(model)
inputs = tokenizer([prompt_text], return_tensors="pt").to("cuda")
text_streamer = TextStreamer(tokenizer, skip_prompt=True)
_ = model.generate(
    **inputs,
    streamer=text_streamer,
    max_new_tokens=2048,
    use_cache=True,
    temperature=0.7,
    do_sample=True
)

 通常のモデル(学習前)と、今回のファインチューニング済みモデル(学習後)の出力結果の比較は以下の通りです。学習後のモデルでは、バックス・バニーの口癖が反映されていることが確認できます!

質問 学習前 学習後
What's your favorite thing to do?(一番好きなことは何?) I love to spend time with my friends and family...
(「友達や家族と過ごすのが大好きです…」)
Outwitting my foes and making people laugh.
(「敵を出し抜いて、みんなを笑わせることさ!」)
What's your favorite type of carror?(一番好きな人参の種類は?)

I'm not a fan of carrots, but I do love the occasional celery stick.

(「私は人参はあまり好きではありません…」)

The big, juicy ones, doc.
(「大きくてジューシーなやつさ、先生(doc)。」)
What's your favorite catchphrase?(お気に入りに決め台詞は?)

Be vewy, vewy quiet, I'm hunting wabbits.
(「静かに、静かに…ウサギを狩ってるんだ。」)

"What's up, doc?" of course.
(「もちろん、"どったの、先生?" さ。」)

7. モデルの保存と共有

 無事モデルの学習が完了したら、最後にモデルを保存します。保存方法には、「ローカル上で保存する方法」と「Hugging Face Hub にアップロードする方法」があります。

 一度保存をすれば、次回以降はファインチューニングのステップをスキップし、いつでも保存した重みを読み込むことで、モデルを使用することができます。

Python

# ローカル(Colabのストレージ内)にLoRAのアダプターを保存
model.save_pretrained("anime_lora_model")
tokenizer.save_pretrained("anime_lora_model")

# もしくは、Hugging Face Hubに直接アップロード(Write権限のトークンが必要)
# model.push_to_hub("your_username/anime_lora_model", token="YOUR_HF_TOKEN")
# tokenizer.push_to_hub("your_username/anime_lora_model", token="YOUR_HF_TOKEN")

最後に

 今回は Google Colab(無料版)環境上で、ローカル LLM を自分の好きなキャラクター風にファイチューニングする方法を解説しました。

 現代のAIトレンドは進化が早く、今回紹介したファインチューニングや、外部知識を組み合わせるRAGなど、日々新しい手法が登場しています。こうした最先端の動向をニュースや論文で追うだけでなく、実際に自分で手を動かしてAIの挙動を体感してみるのも楽しいと思います。この記事が、皆さんの参考になれば幸いです!

 ここまで読んでくださり、ありがとうございました。☺️✨

所属