3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ローカルLLM ファインチューニング入門 — LoRA/QLoRA/Unsloth

3
Last updated at Posted at 2026-03-31

ローカルLLM ファインチューニング入門 — LoRA/QLoRA/Unsloth

自分用メモとして書きました。ローカルLLMをファインチューニングしたい人向け。LoRA/QLoRA/Unslothを中心にカバー。

TL;DR: LLMファインチューニング


1. ファインチューニングとは — いつ使うべきか、RAGとの比較

ファインチューニング(FT)とは、事前学習済みのLLMに対して追加の学習データで重みを更新し、特定のタスクやドメインに特化させる手法。プロンプトエンジニアリングやRAGでは対処しきれないケースで威力を発揮する。

ft-vs-rag.png

FT が向いているケース

  • 出力フォーマットの固定:常にJSON、常に特定の口調、常に決まったスキーマで出力させたい場合
  • ドメイン知識の内在化:医療・法律・社内用語など、プロンプトに毎回入れるにはコンテキストが多すぎる場合
  • 推論コストの削減:RAGのように毎回検索+長いコンテキストを渡す必要がなく、FT済みモデルだけで完結する
  • レイテンシの短縮:検索パイプラインを挟まないため、応答が速い

RAG が向いているケース

  • 情報が頻繁に更新される(FTは再学習が必要)
  • 根拠の明示(ソース引用)が求められる
  • 学習データが少なすぎてFTが不安定になる

結論として、「RAGとFTは二者択一ではなく、組み合わせるのが最強」 というのが現在の主流。FTでベースの能力を底上げし、RAGで最新情報を補完するパターンが実務では多い。

2. LoRA vs QLoRA vs フルファインチューニング — 手法の選び方

LLMファインチューニングには大きく3つのアプローチがある。

ft-lora-comparison.png

フルファインチューニング

  • モデルの全パラメータを更新する。品質は最も高くなりうるが、必要なVRAMが膨大(7Bモデルでも80GB以上)
  • 複数台のA100/H100が必要になるため、個人には現実的でない
  • 企業がFoundationモデルを作る場合や、大規模なドメイン適応に使う

LoRA(Low-Rank Adaptation)

  • モデル本体の重みは凍結し、小さなアダプタ行列(rank分の追加パラメータ)だけを学習する
  • 出力ファイルは数十MB〜数百MB程度。ベースモデルに後からマージ可能
  • 7Bモデルなら16GB VRAM程度で学習可能
  • フルFTに比べて品質がわずかに落ちるとされるが、実用上は十分なケースが大半

QLoRA(Quantized LoRA)

  • ベースモデルを4bit量子化した状態でLoRA学習を行う手法
  • VRAMをさらに劇的に削減(7Bモデルが8GB VRAMで学習可能に)
  • 量子化による精度劣化は意外と小さく、コスパ最強と評価するユーザーが多い
  • 2024年後半〜2025年にかけて安定性が大幅に改善され、現在はデファクトスタンダード

個人ユーザーレベルなら基本QLoRA一択。VRAMに余裕があるならLoRA。フルFTは企業向け。


3. Unsloth — 2倍速・70%メモリ削減のファインチューニングフレームワーク

Unslothは、LLMファインチューニングを高速化・省メモリ化するオープンソースライブラリ。界隈では「FTするならまずUnsloth」が定番の回答になっている。

ft-unsloth.png

主な特徴

  • 2倍の学習速度:カスタムカーネルとTritonベースの最適化で、HuggingFace Transformers比で約2倍の高速化
  • 70%のメモリ削減:勾配チェックポイントの最適化、4bit量子化のネイティブサポートにより、同じモデルを大幅に少ないVRAMで学習可能
  • Google Colab対応:T4(16GB)やL4(24GB)の無料/有料枠で7B〜13Bモデルの学習が可能
  • Llama、Mistral、Qwen、Gemma、Phi対応:主要なオープンモデルを幅広くカバー
  • ノートブックテンプレート:Jupyter Notebookのテンプレートが充実しており、コピペで始められる

基本的な使い方

from unsloth import FastLanguageModel

model, tokenizer = FastLanguageModel.from_pretrained(
    model_name="unsloth/Qwen2.5-7B-bnb-4bit",
    max_seq_length=2048,
    load_in_4bit=True,
)

model = FastLanguageModel.get_peft_model(
    model,
    r=16,
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj",
                     "gate_proj", "up_proj", "down_proj"],
    lora_alpha=16,
    lora_dropout=0,
    bias="none",
)

4. データセット準備 — 合成データ活用のすすめ

ファインチューニングの成否はデータセットの質で9割決まる。量ではなく質が重要。

ft-dataset.png

データ形式

LLMのFTでは主に以下の形式が使われる:

  • Instruction形式instruction / input / output の3カラム。Alpaca形式とも呼ばれる
  • Chat形式messages 配列に system / user / assistant のターンを並べる。ChatMLやShareGPT形式
  • Completion形式:単純なテキスト補完。特定のドメインテキストを大量に学習させる場合に使う

合成データの活用

高品質なデータセットを手作業で用意するのは大変。そこで注目されているのが大規模モデルで学習データを生成する手法。ただし規約は要確認。

  • Seed データ → 拡張:手作業で10〜20件の高品質サンプルを作成し、それを元にAPIで数百〜数千件に拡張する
  • Self-Instruct / Evol-Instruct:既存の質問を複雑化・多様化させてデータを増やすテクニック
  • 品質フィルタリング:生成したデータを別のモデルで評価し、低品質なものを除外する
  • データ量の目安:特定タスク特化なら500〜2000件、汎用能力の底上げなら5000件以上

「100件の高品質データ > 10000件のノイズだらけデータ」

5. VRAM要件 — 8GBでも始められる

「ファインチューニングにはA100が必要」というのは過去の話。QLoRA + Unslothの組み合わせで、一般消費者向けGPUでもFTが可能になった。

ft-vram.png

VRAM別の目安

VRAM 学習可能なモデルサイズ 備考
8GB(RTX 3060等) 3B〜7B(4bit) バッチサイズ1、勾配累積必須
12GB(RTX 3060 12GB) 7B〜8B(4bit) 実用的な最低ライン
16GB(RTX 4060 Ti等) 7B〜13B(4bit) 快適にFTできる
24GB(RTX 3090/4090) 13B〜14B(4bit)、7B(16bit LoRA) コスパ最強GPU
48GB(RTX A6000等) 34B〜70B(4bit) 大型モデルのFTが可能

メモリ節約テクニック

  • 勾配累積(gradient accumulation):実効バッチサイズを上げつつVRAMは増やさない
  • 勾配チェックポイント(gradient checkpointing):計算速度を犠牲にメモリを節約。Unslothでは自動で最適化される
  • max_seq_length の調整:シーケンス長を短くするだけでVRAM消費が激減する。タスクに必要な最小限に設定すべき
  • Flash Attention 2:メモリ効率と速度の両方を改善。対応GPUなら必ず有効にする

「RTX 3060 12GBでQwen2.5-7Bを普通にFTできてる」という報告が複数あった。

6. 学習パラメータ — lr/epochs/rank の設定指針

FTで最も迷うのがハイパーパラメータの設定。Reddit等で共有されていたベストプラクティスをまとめる。

ft-hyperparams.png

学習率(Learning Rate)

  • QLoRA の場合2e-45e-5 が一般的な範囲
  • 高すぎると既存の能力が崩壊する(catastrophic forgetting)
  • cosine スケジューラーを使うのがデフォルト。warmup ratio は 0.03〜0.1 程度

エポック数(Epochs)

  • 1〜3エポックが推奨。多すぎると過学習する
  • データ量が少ない場合(500件以下)は1〜2エポックで十分
  • 「lossが下がり続けているから」と回し続けるのは過学習の典型パターン

LoRA Rank(r)

  • r=16〜64 が一般的。タスクが複雑なほど高いrankが必要
  • r=8 でも単純なタスク(フォーマット変換等)には十分
  • r=128以上はフルFTに近づくが、メリットは薄いことが多い
  • lora_alpha は通常 rank と同じ値に設定する(alpha=16ならr=16)

その他の重要パラメータ

  • batch_size:大きいほど学習が安定するが、VRAMと相談。勾配累積で実効バッチサイズ16〜32を目指す
  • weight_decay:0.01〜0.1。過学習防止に効く
  • target_modules:基本的に全Linear層(q/k/v/o_proj, gate/up/down_proj)を対象にする。一部だけにすると品質が落ちる報告あり

7. 評価方法 — FTモデルの性能をどう測るか

FTの難しいところは 「良くなったのか悪くなったのか」の判断が曖昧になりがちなこと

ft-evaluation.png

定量評価

  • Training Loss:下がっていれば学習は進んでいるが、過学習との区別がつかない
  • Validation Loss:学習データと別のデータで評価。training lossが下がり続けてもval lossが上がり始めたら過学習
  • Perplexity:言語モデルの一般的な指標。ただしタスク特化の場合はあまり参考にならない
  • ベンチマーク(MMLU、HellaSwag等):汎用能力の確認用。FTで特化させると汎用ベンチは下がることがある(これは必ずしも悪いことではない)

定性評価

  • テストプロンプト集:FT前後で同じプロンプトを投げて出力を比較する。最低20〜30パターンは用意する
  • A/Bテスト:FT前後のモデルの出力を並べて人間が判定。最も信頼性が高いが手間がかかる
  • LLM-as-Judge:GPT-4oやClaude等の大規模モデルに「どちらの出力が良いか」を評価させる手法。最近はこれがメインストリーム

「val lossのグラフを見ずにFTしてる人が多すぎる」という意見もあり、最低限validation splitは設定すべきという人が多い。

8. GGUFへの変換 — ローカル推論用フォーマット

FTが完了したモデルをllama.cppやOllamaで使うには、GGUF形式に変換する必要がある。

ft-gguf-flow.png

変換手順

  1. LoRAアダプタのマージ:FTで生成されたアダプタをベースモデルにマージして、単一のモデルにする

    # Unslothの場合
    model.save_pretrained_merged(
        "merged_model",
        tokenizer,
        save_method="merged_16bit",  # or "merged_4bit"
    )
    
  2. GGUF変換:llama.cppの convert_hf_to_gguf.py を使用

    python convert_hf_to_gguf.py ./merged_model --outtype f16 --outfile model-f16.gguf
    
  3. 量子化:推論時のVRAM/RAM削減のために量子化

    ./llama-quantize model-f16.gguf model-Q4_K_M.gguf Q4_K_M
    

量子化レベルの選び方

  • Q8_0:品質最優先。FTの効果を正確に確認したい場合に
  • Q6_K:品質と速度のバランス良好
  • Q4_K_M最も人気のある量子化レベル。品質と効率のバランスが良い
  • Q4_K_S / Q3_K_M:VRAM/RAMが厳しい場合に。品質の劣化が目立ち始める

Unslothには save_pretrained_gguf メソッドがあり、マージとGGUF変換を一発で行えるのが便利。

model.save_pretrained_gguf(
    "model_gguf", tokenizer,
    quantization_method="q4_k_m",
)

9. よくある失敗 — 過学習・データ品質・catastrophic forgetting

FTでハマりやすいポイントを、スレッドで報告されていた失敗例から抽出。

ft-failures.png

過学習(Overfitting)

  • 症状:学習データに含まれるフレーズをそのままオウム返しする。汎化能力がゼロ
  • 原因:エポック数が多すぎる、データが少なすぎる、rankが高すぎる
  • 対策:val lossモニタリング、早期停止(early stopping)、データ量を増やす、rankを下げる

データ品質の問題

  • 症状:FTしたのに全然良くならない、むしろ悪化した
  • 原因:学習データにノイズが多い、フォーマットが不統一、ラベルが間違っている
  • 対策:全データを目視確認(面倒でもやる)、品質フィルタリング、少量から始めて段階的に増やす

Catastrophic Forgetting(破滅的忘却)

  • 症状:特定タスクはできるようになったが、日本語力が壊滅した、常識がなくなった
  • 原因:学習率が高すぎる、データが偏りすぎている
  • 対策:学習率を下げる、汎用データを混ぜる(全体の10〜20%程度)、LoRA rankを下げる

その他の落とし穴

  • Chat Template の不一致:ベースモデルのchat templateと学習データのフォーマットが合っていないと、推論時に意味不明な出力になる
  • BOS/EOSトークンの設定ミス:Unslothでは自動処理されるが、手動で設定する場合は要注意
  • 学習時と推論時のtokenizer不一致:特にマージ後にtokenizerを忘れてコピーするケースが多い

「FTで一番大事なのはデータ。二番目に大事なのもデータ。パラメータチューニングは三番目」という格言がある模様。

10. 小モデルFTの可能性 — 4Bでも専用タスクに強い

最近特に盛り上がっているのが 「小さいモデルをFTして特定タスクに特化させる」 アプローチ。

ft-small-models.png

なぜ小モデルFTが注目されているか

  • 推論コストが圧倒的に低い:4Bモデルは70Bモデルの1/10以下のVRAMで動作し、レスポンスも10倍以上速い
  • FTコストも低い:8GB VRAMのGPUで学習可能。Google Colabの無料枠でも回せる
  • 専用タスクなら大型モデルに匹敵:分類、エンティティ抽出、フォーマット変換などの特定タスクでは、FT済み4Bモデルが汎用70Bモデルを上回る報告が多数

実例として挙がっていたもの

  • Qwen2.5-3B をFTして社内チャットボットの意図分類に使用 → GPT-4o比で精度95%以上、コスト1/100
  • Phi-4-mini(3.8B) をFTしてJSON構造化出力に特化 → 100%正しいJSON出力を達成
  • Gemma-3-4B をFTして日本語要約タスクに使用 → 14Bモデルと同等の要約品質

小モデルFTのコツ

  • タスクを絞る:1モデル1タスクが原則。複数タスクを1つのモデルに詰め込むと小モデルは能力が分散して弱くなる
  • データ品質を極限まで高める:小モデルはデータのノイズに大モデルより敏感
  • 推論時のプロンプトも学習時に合わせる:学習データと推論時のプロンプト形式を完全に一致させる
  • 複数モデルのルーティング:タスクごとにFT済み小モデルを用意し、入力に応じてルーティングする構成が実用的

「70Bモデルを1台のサーバーで動かすより、タスク特化の4Bモデルを10個並べた方が実用性が高い」という意見も多い。

参考リンク

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?