継続事前学習(CPT)とファインチューニング(FT)は何が違うのか ── 実装目線で見る決定的な3点
はじめに
「ドメイン知識をファインチューニングで覚えさせます」── AI 案件のミーティングでこういう発言を聞いたことがあるエンジニアは多いと思います。
ここで違和感を持てるかどうかは、LLM の学習方式に踏み込んだ経験があるかで分かれます。実際、ファインチューニング (FT) と 継続事前学習 (CPT: Continual Pre-Training) は、目的も実装も別物なのですが、現場では両方とも「学習」とまとめて呼ばれていて、混同されている場面をよく見かけます。
この記事では、両者の違いを 損失関数・データ・学習対象 の3点で整理し、「どちらを選ぶべきか」の判断フローを実装目線でまとめます。LLM 案件で技術選定をしている方、ベンダー提案にツッコミを入れる必要があるエンジニアの方の参考になれば嬉しいです。
なお、経営者・発注側向けの判断フロー版は、別記事 「ファインチューニングを提案された経営者のための、判断フロー実践ガイド」 で書きました。本記事はその技術版です。
結論先出し
| 継続事前学習 (CPT) | ファインチューニング (FT) | |
|---|---|---|
| 目的 | 言語モデルとして新しい知識・語彙を獲得 | タスクへの適応・振る舞いの調整 |
| 損失関数 | 次トークン予測 (causal LM loss) | タスク固有 (SFT/RLHF など) |
| データ | 教師なし(生コーパス) | 教師あり(input-output ペア) |
| 典型的な使い時 | 業界用語・新概念・新ドメイン全般の取り込み | 文体・回答形式・特定タスクの精度向上 |
| データ量 | 数百MB〜数十GB のテキスト | 数百〜数万件の対話・タスクペア |
| 代替・補完 | DAPT / TAPT / ドメイン特化OSSモデル流用 | LoRA / QLoRA / Prompt Tuning |
「FT は CPT の代わりにはならない」「CPT は FT の代わりにはならない」── 両者は目的が違うので代替関係ではない、というのが本記事の核です。
1. 損失関数の違い
CPT:次トークン予測の延長
CPT は事前学習 (Pre-Training) の延長線上にあります。損失関数も同じ causal language modeling loss です。
ここで 次のトークンを予測する確率を最大化 する。それだけ。
実装的には、HuggingFace なら
DataCollatorForLanguageModeling(mlm=False)を使って、
Trainerに投げる流れになります。
from transformers import (
AutoModelForCausalLM, AutoTokenizer,
DataCollatorForLanguageModeling, Trainer, TrainingArguments,
)
# 実モデル名に置き換える(例: "meta-llama/Llama-3.1-8B", "elyza/Llama-3-ELYZA-JP-8B" など)
BASE_MODEL = "meta-llama/Llama-3.1-8B"
model = AutoModelForCausalLM.from_pretrained(BASE_MODEL)
tok = AutoTokenizer.from_pretrained(BASE_MODEL)
# 生テキストコーパス(医療論文・業界マニュアルなど)
dataset = load_my_domain_corpus() # → {"text": "..."} の列
dataset = dataset.map(lambda x: tok(x["text"], truncation=True))
collator = DataCollatorForLanguageModeling(tokenizer=tok, mlm=False)
trainer = Trainer(
model=model,
args=TrainingArguments(output_dir="./cpt", ...),
train_dataset=dataset,
data_collator=collator,
)
trainer.train()
ポイントは 「ラベルが存在しない」 ことです。テキストそのものが教師信号になります。
FT:タスク固有の損失
一方、FT のうち最も一般的な Supervised Fine-Tuning (SFT) は、
(input, output)ペアでの教師あり学習です。損失は依然として next-token prediction の形を取りますが、 output 部分のみに損失を計算 します(input 部分はマスク)。
実装的には:
def format_example(ex):
prompt = ex["instruction"]
response = ex["response"]
# input 部分はラベルを -100(無視)に設定
input_ids = tok(prompt + response, return_tensors="pt")["input_ids"]
labels = input_ids.clone()
labels[:, :len(tok(prompt)["input_ids"])] = -100
return {"input_ids": input_ids, "labels": labels}
dataset = dataset.map(format_example)
labels[:, :prompt_len] = -100でプロンプト部分の損失を無視するのが、SFT の本質的な実装ポイントです。これにより 「特定の入力に対する特定の応答を生成する」確率を上げる ように学習されます。
さらに進んだ手法(DPO, RLHF)では、好ましい応答と好ましくない応答のペアから報酬モデルを学習し、それを使って強化学習を回す形になりますが、本記事のスコープからは外します。
2. データの性質の違い
CPT のデータ:教師なしの生テキスト
CPT に必要なのは 大量の生テキスト です。
- 業界マニュアル
- 論文・技術書
- 過去の社内ドキュメント
- 業界用語集(説明付き)
ラベルは要りません。テキストの中で 「次に何が来るか」が学習信号 になります。これにより、モデルは「医療用語の文脈での自然な続き方」「業界特有の言い回し」を獲得します。
データ量の目安:論文ベースだと 数百MB 〜 数十GB が一つのラインです。これより少ないと、モデルが新しいドメインに収束する前に過学習します。
FT のデータ:教師ありの input-output ペア
SFT には
(instruction, response)あるいは
(input, output)の 明示的なペア が必要です。
{"instruction": "次の症例を要約してください: ...", "response": "症例の要約は..."}
{"instruction": "この契約書のリスク条項を抽出してください: ...", "response": "リスク条項は以下の3つです..."}
データ量の目安:数百〜数万件。LoRA を使った軽量 FT なら、数百件でも特定タスクに適応できます。
重要な点:データの「種類」が違う
ここが現場で最も混同される部分です。
「医療データを使ってモデルに知識を覚えさせる」と言われたとき、
- 医療論文を生テキストで学習させる→ CPT
- 「症状A は病名B」のような QA ペアを作って学習させる→ FT (SFT)
両者は 完全に別のアプローチ です。前者は「医療言語空間を獲得する」のに対し、後者は「QA タスクで正解を出す」ように学習する。
FT で医療論文の生テキストを学習させようとすると、データの形式が合いません。 input-output ペアに変換する必要があり、その時点で生テキストの情報密度は大幅に落ちます。これが「FT でドメイン知識を覚えさせる」が実際には機能しにくい技術的な理由です。
3. 学習対象の違い
| 手法 | 学習対象 | 計算コスト | データ準備コスト |
|---|---|---|---|
| CPT (フル) | 全層・全パラメータ | 高 | 中(生コーパス収集・クリーニング) |
| CPT (LoRA) | LoRA アダプタのみ(rank 8-64) | 中 | 中 |
| SFT (フル) | 全層・全パラメータ | 高 | 大(教師ありペアのアノテーション) |
| SFT (LoRA) | LoRA アダプタのみ | 低〜中 | 大 |
| Prompt Tuning | プロンプト用埋め込みのみ | 低 | 中 |
CPT と FT のどちらも、フルで回すか、LoRA や QLoRA を使うかで桁が変わります。「学習する」=「全パラメータを更新する」ではない ことに注意してください。
注意:フル CPT とフル SFT は、計算コストの桁としてはほぼ同等 です。むしろ SFT は 教師ありデータの作成コスト(人手アノテーション・品質チェック・偏りの除去)が大きくなりやすく、合計コストでは SFT の方が CPT より高くつくことも珍しくありません。「学習=高い」という単純化はミスリードで、どこにコストが乗るか の構造を理解して見積もる必要があります。
LoRA の使いどころ
LoRA (Low-Rank Adaptation) は、元のパラメータ行列
LoRA は SFT で使われることが多い ですが、CPT でも使えます(実際、Domain-Adaptive Pre-Training (DAPT) を LoRA で実装する論文も増えています)。
「LoRA = SFT」と思い込まないこと。LoRA は学習対象のパラメータを絞る手法であり、何の目的で学習するかは別軸です。
4. 「ドメイン知識を FT で」がなぜ無理筋なのか
ここまでの整理を踏まえて、冒頭の違和感を技術的に説明します。
「医療業界の専門用語を覚えさせるためにファインチューニングする」と言われたとき、典型的にはこういう手順が想定されます:
- 医療用語集を
(用語, 説明)
の QA ペアに変換 - SFT で学習
- モデルが医療用語を「理解した」と期待する
問題:
- (用語, 説明) のペアは 表面的なパターンマッチで覚えられてしまう
- 医療用語を 「文脈の中で自然に使う」能力は獲得されない
- 学習後のモデルに「症例文を要約してください」と聞くと、要約タスクは SFT で訓練されていないため精度が出ない
これは perplexity の観点からも説明できます:
- CPT は perplexity を直接下げるように学習する → ドメイン語彙の流暢性が上がる
- SFT は perplexity を下げる学習ではない→ タスク精度は上がるが、新しい語彙への流暢性は獲得しにくい
ドメイン知識の獲得を本気でやるなら、CPT 一択 です。FT では代替できません。
5. 中間アプローチ:DAPT / TAPT
「CPT は重すぎる、でも SFT だけでは知識が足りない」という現実的な悩みに対する答えが DAPT (Domain-Adaptive Pre-Training) と TAPT (Task-Adaptive Pre-Training) です。
Don't Stop Pretraining (Gururangan et al., 2020) で提案されました。
- DAPT:ドメインコーパスで継続事前学習してから、タスク用に SFT
- TAPT:タスクの input テキストだけで継続事前学習してから、SFT
両者とも「事前学習 → ドメイン適応 → タスク適応」の 3段構え になります。実装的には:
base-llm ↓ (CPT on domain corpus) domain-adapted-llm ↓ (SFT on task pairs) final-llm
中小企業の案件でフル CPT は現実的でないですが、DAPT を LoRA でやる ならコストは大幅に下がります。「ドメイン知識 + タスク適応」両方が必要なケースで第一候補になります。
6. 中小企業向けの第三の道:ドメイン特化 OSS モデル
ゼロから CPT を回すコストが捻出できないなら、すでにドメイン特化で事前学習された OSS モデル を起点にする選択肢があります。
- 医療:BioBERT, ClinicalBERT, BioMedLM, MedAlpaca, Asclepius
- 法務:Legal-BERT, CaseLaw-BERT
- 金融:FinBERT, BloombergGPT(商用), FinGPT
- 日本語:東北大BERT, llm-jp, Swallow, ELYZA
これらを起点に LoRA で SFT を回せば、「自前で CPT する必要がない」 ケースが多いです。
ベンダー提案で「医療データを学習させましょう」と言われたら、まずこう聞いてみてください。
「BioBERT や MedLLaMA のようなドメイン特化モデルを起点にする選択肢は検討されましたか?」
これに答えられないベンダーは、ドメイン適応の最新ベストプラクティスを追えていない可能性が高いです。
7. 実装目線の判断フロー
ここまでを踏まえて、実装エンジニアが LLM 適応戦略を決めるフロー:
Q1. プロンプトでどこまで行けるか試したか? YES → 行けるならそれで完了 NO → 試してから来い Q2. 自社固有のデータを参照させる必要があるか? YES → Q3 へ NO → プロンプトの工夫 or タスク自体の見直し Q3. データは「文書ベース」か「構造化データ」か? 文書ベース → Q4 へ 構造化 → Function Calling / SQL 連携 / マルチモーダル等を検討 Q4. 問題は「ドメイン語彙・新概念の獲得」か「タスク適応」か? ドメイン語彙の獲得 → CPT(または DAPT・ドメイン特化OSSの流用) タスク適応 → SFT (LoRA から試す) 両方必要 → DAPT → SFT の2段構え Q5. データ量と予算は? 数十GBの生コーパス + 数千万予算 → フル CPT 検討 数GB + 数百万予算 → LoRA-CPT / DAPT 教師ありペア数千件 + 数百万 → LoRA-SFT 教師ありペア数百件 + 数十万 → LoRA-SFT (rank 小)
判断は単純ではないですが、「目的が CPT 領域か FT 領域か」を最初に切り分ける だけで、不要な学習コストの大半は回避できます。
8. 現場で見てきたパターン
LLM 適応戦略の選定で「学習を回したが思ったほどの精度が出なかった」と振り返るケースで、繰り返し見るパターンを整理します。
- 問題:ドメイン語彙の獲得 → アプローチ:SFT→ うまくいきにくい(本来 CPT / DAPT で扱うべき領域)
- 問題:タスク適応 → アプローチ:データ前処理に時間をかけすぎ→ 過剰投資(LoRA-SFT で十分なケースが多い)
- 問題:プロンプトで十分な領域 → アプローチ:いきなり SFT→ 高コストでリターン薄
特に1番目は、ベンダー側もエンジニアも経営者も全員が「ファインチューニング」という言葉で同じものを指していると思い込んでいる 案件で起きやすい構造です。技術的な整理を最初に共有するだけで、案件の方向性が大きく変わることがあります。
おわりに
CPT と FT の違いは、実装的には明確です。
- 損失関数が違う(causal LM vs supervised next-token on output)
- データの性質が違う(unsupervised text vs supervised pair)
- 目的が違う(言語モデル化 vs タスク適応)
この3点を起点に判断すれば、「学習方式の選定でハマる」ケースの多くは避けられます。
経営者・発注側にこの整理を伝える役割を担うのは、技術が分かるエンジニアです。本記事を、社内・案件先での技術選定の議論材料に使ってもらえれば嬉しいです。
経営者向けの判断フロー版は 「ファインチューニングを提案された経営者のための、判断フロー実践ガイド」 でまとめています。社内の経営層に渡したいときは、こちらのほうが伝わりやすいかもしれません。
質問・指摘・実装の議論は X までどうぞ。