AI Navigate

カスタム言語モデルの訓練方法: ファインチューニングとゼロからのトレーニング(2026)

Dev.to / 2026/3/19

💬 オピニオンDeveloper Stack & InfrastructureTools & Practical UsageModels & Research

要点

  • 本記事は、カスタム言語モデルを訓練する3つのアプローチを概観します:プロンプトエンジニアリング(訓練なし)、事前学習済みモデルのファインチューニング、そしてゼロからの訓練。それぞれの利点と制約を整理しています。
  • 各アプローチをいつ使用するかの意思決定基準を提供し、ドメインのニーズ、データの入手可能性、挙動とレイテンシの制御に対する望ましい度合いを考慮して判断します。
  • コスト、インフラ、タイムラインのトレードオフを強調し、チームが過剰支出を避け、過小評価による行き詰まりを回避できるようにします。
  • データセットの準備、モデル選択、訓練コード、評価、デプロイ手順など、実務的な内容と、動作するPythonの例を用いた具体的な計算リソースの見積もりを含む内容を提供します。

カスタム言語モデルをトレーニングすることで、完全なコントロールを手にできます。トークン単位のAPI料金は発生しません。あなたの領域を理解するモデル。ウェイトの完全な所有権。

しかし「言語モデルをトレーニングする」という表現は、チームによって意味が異なります。

いくつかは既存のLLMを、特定の指示に従うよう適応させる必要があります。ほかのチームは、独自データだけで訓練されたモデルを必要とします。中にはゼロから構築する必要があるケースもあります。

各ルートには異なる要件。異なるコスト。異なるタイムライン。

誤った選択は、必要のないインフラに過剰な支出をしてしまうか、複雑さを過小評価して壁にぶつかることになります。

このガイドは、カスタム言語モデルを訓練する3つのアプローチすべてを網羅します。データセットの準備、モデルの選択、トレーニングコード、評価、デプロイを、具体的な計算リソースの見積もり、実用的なPython例、各ステップでの正直なトレードオフとともに詳述します。

どのアプローチが実際にあなたの状況に適合するかを見つけましょう。

三つのカスタム言語モデルのアプローチ

理解の選択肢: ファインチューニング、事前訓練、そしてプロンプト設計

訓練スクリプトを作成する前に、それぞれのアプローチが何を含むかを理解してください。

1. プロンプト設計(訓練不要)

指示、例、システムプロンプトを通じてモデルの挙動を形作ります。モデルのウェイトは決して変わりません。

これにより、予想以上に多くのユースケースを扱えます。出力のフォーマット、トーンの調整、ドメイン固有のルールの遵守、新しいタスクの少数ショット学習など。

プロンプト設計を使い尽くしていないなら、おそらくファインチューニングの準備はできていません。

うまく機能する場合: タスクは指示を通じて定義できます。ベースモデルには基礎的な能力があります。再訓練なしで挙動を変更できる柔軟性が必要です。

うまくいかない場合: 良いプロンプトにもかかわらずモデルが一貫して失敗します。ベースモデルが出せない挙動が必要です。長いプロンプトによるレイテンシは許容できません。

2. 事前学習済みモデルのファインチューニング

既存の大規模言語モデルを取り、それをあなたのカスタムデータでさらに訓練します。モデルはドメインを学習しつつ、一般的な能力も保持します。

ファインチューニングは、ほとんどの本番利用ケースにおける最適解です。事前学習投資の膨大な価値を引き継ぎ、そこにあなたの特定の知識を上乗せします。

これは今日、多くの企業がカスタムLLMを構築する方法です。ゼロから作るのではありません。言語の基礎をすでに理解している小規模言語モデルのファインチューニングを通じて。

うまく機能する場合: ベースモデルに欠けているドメイン特有の専門知識が必要です。特定のタスクで一貫した挙動を求めます。訓練例は数百から数千あります。

うまくいかない場合: 既存のモデルがあなたの言語をうまく扱えません。あなたのドメインはあまりにも異なるため転移学習は役に立ちません。アーキテクチャの変更が必要です。

3. ゼロからの事前学習

あなたはランダムなウェイトを初期化し、全データから訓練します。モデルは言語パターン、事実、推論を、すべてあなたのトレーニングデータから学習します。

これは最も高額なオプションです。いくつかの要件にはこれ以外の選択肢がありません。

ゼロから言語モデルを訓練するということは、すべてを構築することを意味します。トークナイザー。モデルアーキテクチャ。トレーニングパイプライン。巨大なデータセットと大量の計算資源が必要です。

うまくいく場合: 対象言語が既存のモデルで十分にサポートされていない。規制要件によりデータの完全な履歴が求められる。ドメイン特有のデータが数十億トークンある。

うまくいかない場合: ファインチューニングで問題は解決できる。訓練データが100億トークン未満。MLインフラの専門知識がない。

アプローチ 必要な訓練データ 計算コスト タイムライン 制御レベル
プロンプト設計 なし $0 時間
ファインチューニング 1千〜10万例 $10-$10K 数日〜数週間 高い
事前学習 100億〜1兆トークン以上 $100K-$10M+ 数か月 完全

このガイドを読むほとんどのチームはファインチューニングが必要です。その道を詳しく解説します。しかし、事前学習がどういうものかも示し、情報に基づいた選択をできるようにします。

実際にカスタム訓練は必要ですか?

GPUの計算リソースを使う前に、いくつかの質問に答えましょう。

ファインチューニングで十分な場合:

  • 特定のダウンストリームタスク(要約、抽出、分類)での性能向上
  • 法務、医療、金融などのドメイン特有の語彙と用語
  • 一貫した出力フォーマットやトーン
  • オンプレミス展開によるデータのプライバシーの確保
  • 予算50Kドル以下、期間2か月以下

これらのユースケースには、Llama 3.1 や Mistral のような事前学習済み言語モデルから始めて、カスタムデータセットでファインチューニングします。ゼロからインフラを構築せずに、運用準備が整った結果を得られます。

もし 現在のオープンソースモデルの比較 がどのようになっているかを理解したい場合、 landscape は劇的に変わっています。Qwen 2.5 や Llama 3.1 のようなモデルは、多くのベンチマークで独自の代替案と同等かそれを上回る性能を示しています。

3. ゼロからの事前学習は以下の場合必要になるかもしれません:

  • 対象言語が既存の LLM で十分にサポートされていない
  • ドメインが根本的に異なるため転移学習が役に立たない
  • トランスフォーマー以外のモデルアーキテクチャが必要
  • 100B+ トークンのクリーンでドメイン特化の訓練データがある
  • 規制要件により、どのデータが訓練に使われたかを完全に管理する必要がある

決定の近道

「ゼロから訓練すべきか?」と尋ねる場合、その答えは多分「いいえ」です。

まずはファインチューニングから始めて、それがあなたのユースケースで機能するか検証します。ファインチューニングで解決できない天井に達した場合だけ拡大してください。

多くのチームは、必要なカスタマイズの程度を過大評価します。適切に調整された7Bパラメータのモデルは、ドメイン固有のタスクで、適切に訓練されたより大きなモデルを上回ることがよくあります。

目標は最大の複雑さではありません。あなたの特定の問題を効果的に解決することです。

コストを抑えたいチームには、 ファインチューニングとセルフホスティングによるLLM API費用の90%削減 が現実的です。ただし、初めから正しいアプローチを選ぶ場合に限ります。

あなたのモデルはデータ次第です

モデルの品質には硬い天井があります。それはデータ品質です。アーキテクチャやハイパーパラメータの調整だけでは、悪い訓練データを克服できません。

これは、ほとんどのカスタム言語モデルプロジェクトが失敗するポイントです。訓練そのものではなく、データ準備にあります。

アプローチ別データ要件

ファインチューニングの場合:

  • 最小実用可能: 500〜1,000 件の高品質な例
  • 推奨: 5,000〜50,000 件
  • 形式: 指示-入力-出力ペア(JSONL)

ゼロからの事前学習の場合:

  • 最小実用可能: 100億〜500億トークン
  • 競争力のある性能: 1〜2兆トークン
  • 形式: 生テキスト、クリーンアップ済み、重複排除済み

参考として、Llama 2 は 2兆トークンで訓練されました。Mistral 7B も同様に大規模なコーパスを使用しました。ゼロから新しい言語モデルを訓練する場合、あなたはそのベースラインと競合します。

H3: ファインチューニング用データセット形式

訓練データを指示-応答ペアとして構成します:

json

{"messages": [
  {"role": "system", "content": "You are a technical support assistant."},
  {"role": "user", "content": "How do I reset my password?"},
  {"role": "assistant", "content": "Go to Settings > Security. Click Reset Password. Check your email for the reset link."}
]}

指示調整の代替形式:

{"instruction": "Summarize this support ticket", "input": "Customer reports dashboard loading slowly since Tuesday. Cleared cache, tried different browser. Issue persists.", "output": "Performance issue: Dashboard slow since Tuesday. Troubleshooting attempted: cache cleared, multiple browsers. Unresolved."}

一貫性は、形式の選択よりも重要です。データ全体で1つの構造を選択して使用してください。

データクリーニング・パイプライン

生データは、言語モデルを訓練する前に前処理が必要です。以下は機能するパイプラインです:

import re
import hashlib
from typing import List
def clean_text(text: str) -> str:
	"""Normalize and clean training text."""
	# Normalize unicode
	text = text.encode('utf-8', errors='ignore').decode('utf-8')
	
	# Normalize whitespace
	text = re.sub(r'\\s+', ' ', text)
	
	# Remove control characters
	text = re.sub(r'[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f-\\x9f]', '', text)
	
	return text.strip()
def remove_pii(text: str) -> str:
	"""Basic PII removal. Expand based on your requirements."""
	# Email addresses
	text = re.sub(r'\\b[\\w.-]+@[\\w.-]+\\.\\w+\\b', '[EMAIL]', text)
	
	# Phone numbers
	text = re.sub(r'\\b\\d{3}[-.]?\\d{3}[-.]?\\d{4}\\b', '[PHONE]', text)
	
	# SSN pattern
	text = re.sub(r'\\b\\d{3}-\\d{2}-\\d{4}\\b', '[SSN]', text)
	
	return text
def deduplicate(documents: List[str]) -> List[str]:
	"""Remove exact duplicates using hashing."""
	seen = set()
	unique = []
	
	for doc in documents:
		doc_hash = hashlib.md5(doc.encode()).hexdigest()
		if doc_hash not in seen:
			seen.add(doc_hash)
			unique.append(doc)
	
	return unique
def prepare_training_data(
	documents: List[str],
	min_length: int = 100,
	max_length: int = 10000
) -> List[str]:
	"""Full preprocessing pipeline."""
	# Clean
	cleaned = [clean_text(doc) for doc in documents]
	
	# Remove PII
	cleaned = [remove_pii(doc) for doc in cleaned]
	
	# Filter by length
	filtered = [doc for doc in cleaned if min_length < len(doc) < max_length]
	
	# Deduplicate
	return deduplicate(filtered)

これは基本を扱います。生産パイプラインには、近接重複検出、言語フィルタリング、品質スコアリングを追加します。

データ品質チェックリスト

トレーニング前に確認してください:

  • 重複エントリがない(厳密な重複も近接重複もない)
  • すべての例で一貫したフォーマット
  • カテゴリ間でバランスの取れた表現
  • PII が削除または匿名化されている
  • テキストの破損やエンコードの問題がない
  • 出力ラベルが正確(手動でスポットチェック)
  • 訓練/検証/テストの分割が作成済み(80/10/10 が一般的)

データにはプロジェクト時間の60%を割り当てます。残りの40%をトレーニングと評価に割り当てます。この比率は正しくないと感じるかもしれませんが、より良いモデルを生み出します。

大規模データセット準備を扱うチームには、 データセットパイプラインの自動化 が手動 bottlenecks を取り除きます。特に、トレーニング前にデータ品質を複数回反復する必要がある場合に有効です。

H2: 適切な事前学習済みモデルの選択

ベースモデルの選択は、トレーニングの効率、最終的な性能、デプロイメント要件を決定します。間違った選択をすれば、用途に合わないモデルに何週間も wasted します。

H3: 2025年モデル情勢

オープンソースのLLMエコシステムは大きく成熟しました。Llama 3.1、Mistral、Qwen 2.5 といったモデルは、ほとんどのベンチマークで専有モデルと競合しています。

モデル パラメータ コンテキスト長 ライセンス 強み
Llama 3.1 8B 8B 128K Llama 3.1ライセンス 堅実なベースライン、大規模なコミュニティ、十分に文書化
Llama 3.1 70B 70B 128K Llama 3.1ライセンス 複雑な推論、最前線に近い性能
Mistral 7B 7B 32K Apache 2.0 効率的、命令追従性に優れる
Mixtral 8x7B 46.7B (12.9B active) 32K Apache 2.0 MoE効率、多様なタスク対応
Qwen 2.5 7B 7B 128K Apache 2.0 多言語対応、コードに強い
Qwen 2.5 72B 72B 128K Qwenライセンス 最先端の多言語性能
Phi-3 Mini 3.8B 128K MIT エッジ展開、リソース制約下の環境

Selection Criteria

  1. タスクの適合性は、純粋なサイズより重要です。 あなたの特定のタスクに合わせてファインチューニングされた7Bモデルは、汎用の70Bモデルよりも優れていることが多いです。コード生成が必要な場合は、Qwen 2.5 Coder または DeepSeek Coder から始めてください。多言語タスクの場合、Qwen 2.5 は非英語言語を他のほとんどの代替よりも得意とします。
  2. サイズと能力のトレードオフ。 大きなモデルは性能が高いですが、ファインチューニングとデプロイにはより多くのコストがかかります。QLoRAでファインチューニングした7Bモデルは単一の24GB GPUで動作します。70Bモデルには複数GPUや高価なクラウドインスタンスが必要です。
  3. 最初は7B-8Bレンジから始めてください。評価セットでパフォーマンスの天井に達した場合のみスケールアップします。
  4. コンテキスト長の要件。 長い文書を扱う用途では、拡張コンテキストで訓練されたモデルが必要です。Llama 3.1 と Qwen 2.5 はネイティブに 128K トークンをサポートします。Mistral は 32K が上限です。
  5. ライセンスの考慮事項。 Apache 2.0 モデル(Mistral、Qwen)は最小限の制限で商用利用を許可します。Llama には特定の商用アプリケーションを制限するライセンス条項があります。導入前に確認してください。

Where to Find Models

Hugging Face Hub はほとんどの公開ウェイトモデルをホストしています。Open LLM Leaderboard は、モデルファミリー間のベンチマーク比較を提供します。

オープンソースモデルが実運用可能かを評価するチーム向けには、2025年の答えは「はい」です。オープンとクローズドのモデル間のギャップは、劇的に狭まりました。

from huggingface_hub import list_models
# Find top instruction-tuned models
models = list_models(
	filter=\"text-generation\",
	sort=\"downloads\",
	direction=-1,
	limit=10
)
for model in models:
	print(f\"{model.id}: {model.downloads:,} downloads\")

Fine-Tuning a Pre-Trained Language Model Step by Step

Fine-tuning adapts a pre-trained LLM to your specific downstream task. Modern techniques like LoRA and QLoRA make this efficient enough to run on consumer hardware.

Full Fine-Tuning vs. Parameter-Efficient Methods

Full fine-tuning updates all model parameters. Best quality, but a 7B model needs ~60GB GPU memory for training. Impractical for most teams.

LoRA (Low-Rank Adaptation) trains small adapter matrices instead of full weights. Reduces trainable parameters by 99%+. Quality comes within 1-2% of full fine-tuning for most tasks.

QLoRA combines LoRA with 4-bit quantization. The base model loads in 4-bit precision while adapters train in higher precision. A 7B model fits in 16GB VRAM. A 65B model fits on a single 48GB GPU.

For most production fine-tuning, QLoRA provides the best trade-off between quality and resource requirements. QLoRA reduces memory usage enough to finetune a 65B parameter model on a single 48GB GPU while preserving full 16-bit finetuning task performance. arXiv

QLoRA Fine-Tuning with Hugging Face

Here's a complete working example:

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 load_dataset
# Model to fine-tune
model_id = \"mistralai/Mistral-7B-v0.1\"
# 4-bit quantization configuration
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type=\"nf4\",
    bnb_4bit_compute_dtype=torch.bfloat16,
    bnb_4bit_use_double_quant=True
)
# Load model with quantization
model = AutoModelForCausalLM.from_pretrained(
    model_id,
    quantization_config=bnb_config,
    device_map=\"auto\",
    trust_remote_code=True
)
# Load tokenizer
tokenizer = AutoTokenizer.from_pretrained(model_id)
tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = \"right\"
# Prepare for k-bit training
model = prepare_model_for_kbit_training(model)
# LoRA configuration
lora_config = LoraConfig(
    r=16,                             # Rank of update matrices
    lora_alpha=32,                    # Scaling factor (common: 2x rank)
    target_modules=[
        \"q_proj\", \"k_proj\", \"v_proj\", \"o_proj\",
        \"gate_proj\", \"up_proj\", \"down_proj\"
    ],
    lora_dropout=0.05,
    bias=\"none\",
    task_type=\"CAUSAL_LM\"
)
# Apply LoRA
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# Output: trainable params: 13,631,488 || all params: 3,752,071,168 || trainable%: 0.36%

その 0.36% が鍵となる数値です。モデルのごく一部を学習させている間に、ほとんどの恩恵を得ています。

Training Configuration

# Load your custom dataset
dataset = load_dataset("json", data_files={
    "train": "train.jsonl",
    "validation": "val.jsonl"
})
# Format function for instruction tuning
def format_instruction(example):
    return f"""### Instruction:
{example['instruction']}
### Input:
{example['input']}
### Response:
{example['output']}"""
# Training arguments
training_args = TrainingArguments(
    output_dir="./mistral-custom",
    num_train_epochs=3,
    per_device_train_batch_size=4,
    gradient_accumulation_steps=4,
    learning_rate=2e-4,
    weight_decay=0.01,
    warmup_ratio=0.03,
    lr_scheduler_type="cosine",
    logging_steps=25,
    save_strategy="epoch",
    evaluation_strategy="epoch",
    fp16=True,
    optim="paged_adamw_8bit",
    max_grad_norm=0.3,
    report_to="none"
)
# Initialize trainer
trainer = SFTTrainer(
    model=model,
    train_dataset=dataset["train"],
    eval_dataset=dataset["validation"],
    tokenizer=tokenizer,
    args=training_args,
    formatting_func=format_instruction,
    max_seq_length=2048,
    packing=True
)
# Train
trainer.train()
# Save adapter weights
trainer.save_model("./mistral-custom/final")

ハイパーパラメータのガイドライン

LoRA の共通パターン: lora_alpha = 2 * r。この比率は元の研究者によって経験的に決定され、多くのタスクでうまく機能します。 Reintech

パラメータ 推奨値 備考
LoRA ランク(r) 16 ここから開始。検証損失が停滞した場合は増やしてください
LoRA α 32 通常はランクの2倍
学習率 2e-4 学習が不安定な場合は低く設定(1e-4)
バッチサイズ 4-8 勾配蓄積を用いる
エポック数 1-3 データ量が増えると必要エポック数は少なくなる

計算要件とコスト

モデルサイズ GPU メモリ(QLoRA) トレーニング時間(10K サンプル) クラウドコスト推定
3B 8-10 GB 1-2 hours $5-15
7B 16-20 GB 3-6 hours $15-50
13B 24-32 GB 6-12 hours $50-120
70B 80+ GB (multi-GPU) 24-48 hours $250-600

これらの推定は A100 40GB 相当または同等を前提としています。実際の時間はシーケンス長やデータセットの特性によって異なります。

インフラ管理をスキップしたいチームには、 Prem Studio がトレーニング・パイプラインを処理します。データセットをアップロードし、実験を設定し、デプロイしてください。反復の速度がインフラ制御より重要な場合に有用です。

LoRAを含むファインチューニング手法と、完全なSLMトレーニングを含むファインチューニングの比較についてのより詳しい解説は、デプロイメントの制約に大きく依存します。

ゼロからの事前学習: 完全な全体像

プレトレーニングは、ゼロから言語モデルを構築します。乱数で初期化した重みを用い、生のテキストに対して訓練を行い、モデルが言語パターン・事実・推論を学習するまで続けます。

このセクションは網羅性のために存在します。ほとんどのチームはファインチューニングを行うべきです。ただし、既存のモデルが満たせない特定の要件がある場合、以下の内容が含まれます。

プレトレーニングが実際に意味を成す場合

  • 言語カバー範囲: 対象言語が過小評価されています。低資源言語は、専用の事前学習の恩恵を受けることが多いです。
  • ドメイン密度: 専門的テキスト(法務、医療、科学など)が数十億トークンあり、深く内部化したい。
  • データ主権: 規制によりトレーニングデータを完全に管理する必要があります。外部の事前学習は許可されていません。
  • アーキテクチャ研究: 既存のウェイトに対応しない新規アーキテクチャを探索しています。

リソース要件(実数)

プレトレーニングは高価です。公開されたトレーニング実行は以下を示しています:

モデル パラメータ数 トレーニング・トークン GPU 時間 推定コスト
Llama 2 7B 7B 2T ~180K A100 時間 $500K-$1M
Llama 3 8B 8B 15T ~7.7M H100 時間 $10M+
Mistral 7B 7B 開示なし 開示なし ~$500K+
TinyLlama 1.1B 1.1B 3T ~90 日、16 台の A100 ~$50K

Llama 3 8B was trained on 15 trillion tokens using 7.7 million GPU hours on H100s. That's the baseline you're competing against when you train from scratch.

アーキテクチャ構成

from transformers import LlamaConfig, LlamaForCausalLM
# Configure a ~1B parameter model
config = LlamaConfig(
    vocab_size=32000,
    hidden_size=2048,
    intermediate_size=5632,
    num_hidden_layers=22,
    num_attention_heads=32,
    num_key_value_heads=4,         # Grouped-query attention
    max_position_embeddings=4096,
    rope_theta=10000.0,
    rms_norm_eps=1e-5,
    initializer_range=0.02,
    use_cache=True,
    tie_word_embeddings=False
)
# Initialize model with random weights
model = LlamaForCausalLM(config)
print(f"Parameters: {model.num_parameters():,}")

トークナイザーの訓練

プレトレーニングには、コーパスに適合したトークナイザーが必要です。ドメインに固有の語彙がある場合、汎用的なトークナイザーは使わないでください。

from tokenizers import (
    Tokenizer,
    models,
    trainers,
    pre_tokenizers,
    processors,
    decoders
)
# Initialize BPE tokenizer
tokenizer = Tokenizer(models.BPE())
tokenizer.pre_tokenizer = pre_tokenizers.ByteLevel(add_prefix_space=False)
# Configure training
trainer = trainers.BpeTrainer(
    vocab_size=32000,
    special_tokens=["<s>", "</s>", "<unk>", "<pad>"],
    min_frequency=2,
    show_progress=True
)
# Train on your corpus
corpus_files = ["data/corpus_part1.txt", "data/corpus_part2.txt"]
tokenizer.train(files=corpus_files, trainer=trainer)
# Add post-processor and decoder
tokenizer.post_processor = processors.ByteLevel(trim_offsets=False)
tokenizer.decoder = decoders.ByteLevel()
# Save
tokenizer.save("custom_tokenizer.json")

正直な評価

特定の技術的要件がファインチューニングでは解決できない場合を除き、ゼロからのプレトレーニングはおそらく価値がありません。

オープンソースのエコシステムには強固な基盤があります。Llama 3.1、Mistral、Qwen 2.5 は、数十億ドル規模のトレーニング投資を、数兆トークンにわたって示しています。ファインチューニングを行えば、その投資をはるかに低コストで活用できます。

Train from scratch when:

  • No existing model supports your language adequately
  • You need full control over training data for compliance
  • Your domain is so specialized that transfer learning fundamentally won't help
  • You have the budget, timeline, and ML expertise to execute it properly

For most enterprise use cases, the fine-tuning path from dataset to production delivers better ROI than starting from zero.

評価するカスタム言語モデル

Training without evaluation is guessing. You need metrics that tell you whether your model actually improved on the task you care about.

タスクタイプ別の指標

Task Metrics What They Measure
Text Generation Perplexity, BLEU, ROUGE Fluency, similarity to reference
Classification Accuracy, F1, Precision, Recall Correctness on labeled data
Question Answering Exact Match, F1 Answer accuracy
Summarization ROUGE-1, ROUGE-2, ROUGE-L Content coverage
Instruction Following Human eval, LLM-as-judge Subjective quality

評価の実装

import torch
from evaluate import load
from tqdm import tqdm
def evaluate_model(model, tokenizer, test_dataset, max_new_tokens=256):
	"""Evaluate fine-tuned model against test set."""
	
	model.eval()
	predictions = []
	references = []
	
	for example in tqdm(test_dataset):
		prompt = f"### Instruction:
{example['instruction']}

### Input:
{example['input']}

### Response:
"
		
		inputs = tokenizer(prompt, return_tensors=\"pt\").to(model.device)
		
		with torch.no_grad():
			outputs = model.generate(
				**inputs,
				max_new_tokens=max_new_tokens,
				temperature=0.1,
				do_sample=False,
				pad_token_id=tokenizer.pad_token_id
			)
		
		generated = tokenizer.decode(outputs[0], skip_special_tokens=True)
		response = generated.split("### Response:
")[-1].strip()
		
		predictions.append(response)
		references.append(example['output'])
	
	# Calculate ROUGE scores
	rouge = load("rouge")
	results = rouge.compute(predictions=predictions, references=references)
	
	return {
		"rouge1": results["rouge1"],
		"rouge2": results["rouge2"],
		"rougeL": results["rougeL"],
		"num_examples": len(predictions)
	}
# Compare base vs fine-tuned
base_results = evaluate_model(base_model, tokenizer, test_data)
finetuned_results = evaluate_model(finetuned_model, tokenizer, test_data)
print(f"Base ROUGE-L: {base_results['rougeL']:.4f}")
print(f"Fine-tuned ROUGE-L: {finetuned_results['rougeL']:.4f}")
improvement = (finetuned_results['rougeL'] - base_results['rougeL']) / base_results['rougeL']
print(f"Improvement: {improvement * 100:.1f}%")

不良な結果のデバッグ

モデルのパフォーマンスが低下している場合は、次の順序でデバッグします:

  1. データ品質(最も一般的な原因です)。ラベルエラー、不整合なフォーマット、訓練データとテストデータ間のデータ漏洩を確認してください。
  2. 過学習。訓練損失は低下する一方で検証損失が増加します。エポックを減らす、ドロップアウトを追加する、またはデータを追加で集める。
  3. 学習不足。両方の損失が高い水準で停滞しています。学習率を上げる、より長く訓練する、またはLoRAランクを上げる。
  4. ベースモデルの不一致。事前学習済みモデルはあなたのタスクに適していません。別のベースを試してみてください。
  5. ハイパーパラメータ。学習率(1e-5〜1e-3)、バッチサイズ、そしてLoRAランクをグリッドサーチします。

品質を第一に: 対象となるユースケースでは、5千〜2万のキュレーション済みサンプルが、ノイズの多い20万サンプルより優れていることがあります。

本番システムでは、 評価が出荷可能かどうかを決定します、訓練をスケールする前に堅牢な評価パイプラインの構築に時間を投資してください。

カスタム言語モデルのデプロイ

ディスク上にある訓練済みモデルは有用ではありません。本番環境の規模でリクエストを処理する推論インフラストラクチャが必要です。

デプロイメントのオプション

オプション スループット セットアップの難易度 最適な用途
Ollama 低い 非常に簡単 開発、ローカルテスト
vLLM 非常に高い 中程度 自社運用の本番
Text Generation Inference 高い 中程度 HuggingFaceエコシステム
Managed platforms 高い Easy インフラ管理なしの本番

ローカルデプロイ with Ollama

訓練済みウェイトから推論を実行するまでの最速の道筋:

# Create Modelfile pointing to your fine-tuned model
cat << 'EOF' > Modelfile
FROM ./mistral-custom/final
PARAMETER temperature 0.7
PARAMETER top_p 0.9
TEMPLATE """### Instruction:
{{ .Prompt }}
### Response:
"""
EOF
# Build and run
ollama create my-custom-model -f Modelfile
ollama run my-custom-model \"Your prompt here\"

vLLMによる本番デプロイ

高スループットの本番ワークロードには、vLLMが標準です。vLLM移行により推論コストを73%削減し、GPUファンの1/3の規模で日次5,000万件のAPI呼び出しを処理します。 Introl

vLLMのPagedAttentionアルゴリズムは、従来の推論システムでGPUメモリの60〜80%を浪費するメモリ断片化を排除します。

from vllm import LLM, SamplingParams
# Load your fine-tuned model
llm = LLM(
		model=\"./mistral-custom/final\",
		tensor_parallel_size=1,
		max_model_len=4096,
		gpu_memory_utilization=0.9
)
# Configure generation
sampling_params = SamplingParams(
		temperature=0.7,
		top_p=0.9,
		max_tokens=512
)
# Generate
prompts = [\"Your prompt here\"]
outputs = llm.generate(prompts, sampling_params)
for output in outputs:
	print(output.outputs[0].text)

OpenAI互換APIでの提供

vLLMはOpenAI互換のサーバーを標準で提供します:

python -m vllm.entrypoints.openai.api_server \\
    \
    --model ./mistral-custom/final \\
    --host 0.0.0.0 \\
    --port 8000
Then query it like any OpenAI endpoint:
python
from openai import OpenAI
client = OpenAI(base_url=\"http://localhost:8000/v1\", api_key=\"not-needed\")
response = client.chat.completions.create(
    model=\"./mistral-custom/final\",
    messages=[{\"role\": \"user\", \"content\": \"Your prompt\"}]
)

Deployment Considerations

  • Latency requirements. 100ms未満を達成するには量子化 (AWQ, GPTQ) と最適化された提供が必要です。
  • Concurrent users. GPUサイズに影響します。vLLMの継続的なバッチ処理は可変負荷を効率的に処理します。
  • Cost model. オンデマンドのクラウド vs 予約容量 vs オンプレミス。

エッジでの小型言語モデルを展開するチームには、量子化とモデルサイズが重要な要因となります。 エッジでの小型言語モデル

インフラを管理せずにファインチューニング済みモデルをセルフホスティングする場合、 Premのデプロイメントドキュメント が全体のワークフローを解説します。

カスタムモデルプロジェクトを失敗へ導くミス

技術的な手順の後、見落とされがちな失敗モードを以下に示します:

1. 初期段階で大きすぎるモデルを使う

チームはしばしば入手可能な中で最大のモデルから始めます。これにより反復が遅れ、実験に予算を消費します。

より良い選択は、7Bモデルから始めることです。パイプラインを動作させ、ファインチューニングが指標を改善することを検証します。小さいモデルが天井に達した場合のみスケールアップしてください。

2. データへの投資を過少にする

データを収集することはモデルのトレーニングより刺激的ではありません。しかしデータ品質があなたの上限を決定します。

プロジェクト時間の60%をデータ収集、クリーニング、検証に費やし、残りの40%を訓練と評価に費やします。

3. 成功基準がない

"モデルをより良くする" は測定できません。訓練前に具体的な指標を定義してください:

  • "分類F1を0.72から0.85へ改善する"
  • "幻覚率を5%以下に抑える"
  • "人間の専門家の合意を90%以上で一致させる"

4. 最後まで評価を飛ばす

訓練完了後の1回の評価では、ほとんど有用な情報は得られません。

訓練中のチェックポイントで評価します。ベースラインと比較します。訓練には触れないホールドアウトのテストセットを使用してください。

5. 初期段階での過度な複雑化

まずはシンプルに。デフォルトのハイパーパラメータでの基本的なファインチューニング実行で、しばしば潜在的改善の80%を達成します。

# Start here. Add complexity only when this plateaus.
training_args = TrainingArguments(
	    output_dir=\"./output\",
	    num_train_epochs=3,
	    per_device_train_batch_size=4,
	    learning_rate=2e-4
)

カスタム推論モデルを構築しているチームには、初期段階で複雑さを追加したくなる誘惑が強いです。抑えましょう。

機能する最も単純な道筋から始める

カスタム言語モデルのトレーニングは、最大の複雑さを競うことではありません。あなたの特定の問題を効果的に解決することが目的です。

ほとんどのチームにとって、道のりは次のとおりです:

  1. まずプロンプト設計を徹底的に試す
  2. あなたのカスタムデータで7BモデルをQLoRAでファインチューニングする
  3. ベースラインに対して厳密に評価する
  4. 指標が必要とする場合にのみスケールアップする

ゼロからの事前学習は、ユースケースのごく少数に適した選択です。自分がその割合に該当するかどうか分からない場合、おそらく該当していません。

まずはシンプルに。すべてを測定し、証拠に基づいて反復します。

本番環境向けの言語モデルを出荷するチームは、最も予算が大きいチームではありません。正しいアプローチを選び、それをうまく実行するチームです。

よくある質問

1. カスタム言語モデルを訓練するには、どれくらいのデータが必要ですか?

アプローチ次第です。事前学習済みモデルのファインチューニングの場合、1,000〜5,000の高品質な例がしっかりとした出発点です。多くのチームは、ドメイン固有のタスクで10,000〜50,000の例で顕著な結果を得ています。

ゼロからのプレトレーニングには、何十億のトークンが必要です。Llama 3は15兆トークンで訓練されました。競合モデルは通常、最低でも1〜2兆トークンを必要とします。これが多くのチームが代わりにファインチューニングを選ぶ理由です。

2. 1台のGPUで大規模言語モデルをファインチューニングできますか?

はい。QLoRAはこれを実用的にします。7Bパラメータのモデルは、1枚の24GB GPU(RTX 3090、RTX 4090、または A10)でファインチューニングできます。13Bモデルは32GBで収まります。さらに65Bモデルでも、QLoRAの4ビット量子化を使えば1枚の48GB A100でファインチューニング可能です。

鍵はパラメータ効率の高いファインチューニングです。モデルの全パラメータではなく、0.1〜1%のパラメータを訓練します。

3. ファインチューニングにはどれくらい時間がかかりますか?

QLoRAを使って10,000件の訓練データを持つ7Bモデルの場合:

  • 1枚のA100 40GB: 3〜6時間
  • 1枚のRTX 4090: 4〜8時間
  • 1枚のRTX 3090: 6〜12時間

より大きなモデルやデータセットは線形にスケールします。70Bモデルは、同等のハードウェアでおおよそ7Bモデルの約10倍の時間がかかります。

4. LoRAとQLoRAの違いは何ですか?

LoRA(Low-Rank Adaptation)は、ベースモデルの重みを凍結したまま、小さなアダプタマトリクスを訓練します。訓練可能なパラメータを99%以上削減します。

QLoRAはLoRAの上に4ビット量子化を追加します。ベースモデルは4ビット精度(NF4形式)でロードされ、メモリを約75%削減します。アダプターは品質のために依然として高精度で訓練されます。QLoRAを使えば、品質の低下を最小限に抑えつつ、小さなGPUでより大きなモデルをファインチューニングできます。

5. 言語モデルをファインチューニングすべきですか?それともゼロから訓練すべきですか?

ほとんどの場合、ファインチューニングを行います。Llama 3.1、Mistral、Qwen 2.5のような事前訓練済みモデルは、すでに言語の基礎を理解しています。ファインチューニングは、あなたのドメイン知識を上乗せします。

ゼロから訓練するのは次の場合のみ:

  • 既存モデルでは対応していない言語
  • 規制要件によりデータの完全な系統管理が求められる
  • 10B以上のトークンと、それに見合う予算がある

ファインチューニングの費用は10〜500ドル。プレトレーニングは10万〜1000万ドル以上。多くのユースケースにおいてROIは明確です。

6. ファインチューニング済みのモデルが実際により良いかどうか、どう判断しますか?

分離されたテストセットでベースモデルと比較します。ファインチューニング前後で、タスク固有の指標(精度、F1、ROUGE)を測定します。

ファインチューニングが効果的であれば、評価指標に測定可能な改善が現れます。数値が横ばいか低下している場合は、まずデータ品質を確認してください。訓練データの不良が、ファインチューニング失敗の最も一般的な原因です。

7. GPT-4 や Claude のような公式クローズドモデルをファインチューニングできますか?

OpenAIはGPT-3.5とGPT-4のファインチューニングを提供しています。Anthropicは現時点でClaudeのファインチューニングを提供していません。これらのサービスには制限があります。重みを所有できない、訓練と推論をトークン単位で支払う、自己ホストできない、という点です。

完全な制御と所有権を得るには、Llama 3.1、Mistral、Qwen 2.5のようなオープンウェイトモデルをファインチューニングしてください。得られた重みを所有し、どこへでもデプロイできます。

8. ファインチューニング中の訓練データは安全ですか?

ローカルまたは自前のインフラストラクチャでファインチューニングする場合、データは環境を離れません。これは、APIベースのファインチューニングに対するオープンウェイトモデルの重要な利点です。

データプライバシー要件が厳しいチームには、オンプレミス展開のセルフホスティングファインチューニングで第三者データの露出を完全になくします。

カスタム言語モデルの構築を始めましょう

カスタム言語モデルの構築は、あなたの状況に最適な道を選ぶことに尽きます。

ほとんどのチームは:

  1. ファインチューニングから始める。 Llama 3.1 や Mistral 7B のような事前学習済みモデルを取り、QLoRAを用いて独自データセットでファインチューニングします。これにより、ゼロから訓練するコストの1%で、恩恵の約90%を得ることができます。
  2. データ品質に投資する。 あなたのモデルの上限はデータの品質です。データセットの準備には、思っている以上に時間をかけてください。
  3. 厳密に評価する。 基準線と比較します。特定のユースケースで重要なものを測定します。ファインチューニングが実際に役立ったという証拠なしに出荷しないでください。
  4. 必要なときだけ拡張する。 よくチューニングされた7Bモデルは、ドメイン固有のタスクで一般的な70Bモデルよりもよく機能することがあります。小さく始め、証拠に基づいて拡大してください。

ゼロからのプレトレーニングは、特定の要件と十分なリソースを持つ少数のチームにのみ合理的です。それ以外の人は皆、ファインチューニングを選ぶべきです。

準備はできましたか?自分のカスタム言語モデルを訓練しますか?

Prem Studio はインフラストラクチャの複雑さを処理します。データセットをアップロードし、ベースモデルを選択し、実験を実行してデプロイします。GPU管理は不要です。分散トレーニングのデバッグも不要です。結果だけを得られます。 デモを予約 することで、チームがインフラのオーバーヘッドなしに本番向けカスタムLLMを構築している様子を確認できます。あるいは ドキュメントを参照して、独自に始めてください。