蒸留データの設計 — 教師に何を答えさせるか
蒸留で生徒の性能を決めるのは、教師の賢さより「教師に何を問うたか」です。合成データの作り方、カバレッジの設計、難問へ偏らせる理由、正しさのフィルタ、そしてDeepSeek-R1の蒸留がなぜ効いたのかを、前提知識ゼロから解説します。
要点
- 現代のLLM蒸留では教師の確率表が得られないため、教師の生成テキストを正解ラベルとする系列レベル蒸留が主流になった。
- 蒸留の損失は、入力の分布 が選んだ問題の上でだけ教師と生徒を一致させ、 が選ばなかった入力には何も要求しない。
- 損失の勾配は で、生徒がすでに教師と同じ確率を出す例では勾配が消える。
- 拒否サンプリングは、教師に 回解かせて正解にたどり着いた軌跡だけを残す方法で、残すのは答えでなく途中の推論過程である。
- DeepSeek-R1は約80万件(推論系約60万件、非推論系約20万件)のデータでQwenとLlamaの小さいモデルを普通の教師あり学習で微調整した。
DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning
一次資料 — この記事の根拠
この解説の公開 2026-08-29
DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement LearningarXiv:2501.12948論文ページ·PDFSequence-Level Knowledge DistillationarXiv:1606.07947論文ページ·PDF
The False Promise of Imitating Proprietary LLMsarXiv:2305.15717論文ページ·PDF
Self-Instruct: Aligning Language Models with Self-Generated InstructionsarXiv:2212.10560論文ページ·PDF
STaR: Bootstrapping Reasoning With ReasoningarXiv:2203.14465論文ページ·PDF
良い先生を雇っても、問題集が薄ければ伸びない
家庭教師を雇うところを想像してください。指導力の高い先生を見つけられたとします。それでも生徒の点数を最後に決めるのは、その先生に何を解かせて、その解答を生徒がどれだけ見たかです。先生が微分積分を極めていても、渡した問題集に一問も微分が載っていなければ、その知識は生徒に一切伝わりません。逆に、生徒がもう完璧に解ける計算ドリルを100枚やらせても、時間を使うだけで何も増えません。
知識蒸留(Knowledge Distillation)でも事情はまったく同じです。知識蒸留を1からで見たとおり、蒸留の中身は「教師モデルの出す確率分布に、生徒モデルの確率分布を近づける」ことでした。損失関数も温度も、そこで説明したものがそのまま使えます。ところが実際に生徒の出来を左右するのは、損失関数の細部ではなく、近づける作業をどの入力の上で行ったかのほうです。
この記事はその「入力の集合」——蒸留データ——の設計の話です。
そもそも、いま蒸留されているのは何か
古典的な蒸留では、教師のロジット(softmaxに入る前の生の出力値)をそのまま取り出して使えました。教師も生徒も自分の手元にあるからです。
ところが現代のLLM蒸留では、教師がAPI越しの巨大モデルだったり、教師と生徒で語彙(トークンの種類)が違ったりします。この場合、確率の表そのものは手に入りません。手に入るのは教師が生成したテキストだけです。
そこで主流になったのが系列レベル蒸留(Sequence-Level Knowledge Distillation)です。教師に問題を解かせ、その出力文をそのまま正解ラベルとみなして、生徒を普通の教師あり学習で訓練します。Kim と Rush が2016年に機械翻訳で示した方法で、いまのLLM蒸留はほぼこの形です。
ここで何が起きたかというと、蒸留という問題が丸ごとデータ作りの問題に変わったということです。損失関数は通常の言語モデル学習と変わりません。設計の自由度は、どんな入力を集め、教師に何回・どんな温度で答えさせ、どの答えを残すか、に移りました。この記事の残りは全部その話です。
仕組み: 生徒が縛られるのは「引いた問題の上」だけ
数式でひとこと押さえておきます。蒸留の損失は、おおまかにこう書けます。
記号の意味は順に、 が入力(プロンプト)、 が蒸留データを作るときに入力を引いてくる分布、 が教師の出す確率、 が生徒の出す確率、 が生徒のパラメータ、 が2つの確率分布のズレを測る量(KLダイバージェンス)です。
平易に言い換えると、この式は 「 が選んだ問題の上でだけ、教師と生徒の答え方のズレを小さくしなさい」 と言っています。裏を返すと、 が一度も選ばなかった入力について、この式は生徒に何も要求していません。そこで生徒が何を答えるかは、訓練の外側にある偶然の産物です。
これが蒸留データ設計の出発点です。教師の賢さは の質を決めますが、 を決めるのは私たちです。そして生徒の弱点は、ほぼ の穴の形をしています。
難問に偏らせる理由 — 勾配が立つ場所
「たくさん集めれば良い」ではありません。softmaxと交差エントロピーを使う場合、生徒のロジット に対する損失の勾配は、驚くほど単純な形になります。
は候補(語彙の中の1トークン)の番号、 と はその候補に生徒と教師が割り当てた確率です。
つまり学習の力の大きさは「生徒と教師の食い違い」そのものです。生徒がすでに教師と同じ確率を出している例では差がゼロになり、勾配も消えます。教師を呼んでGPUを回したのに、パラメータは1ミリも動きません。
だから蒸留データは、生徒がいまつまずいている領域へ意図的に偏らせるのが効率的です。実務では、①生徒に候補プロンプトを解かせて間違えたものだけ教師に回す、②教師に 回答えさせて全問正解(易しすぎ)と全問不正解(教師にも無理)を捨て中間を残す、③間違えた問題を種に言い回しや数値を変えた変種を作る(Self-Instruct系の自動増殖)、の3つがよく使われます。
「同じ問題ばかり」は、量に見えて量ではない
合成データの怖いところは、件数が増えても情報は増えていない状態が簡単に起きることです。温度を下げて生成させると同じプロンプトからはほぼ同じ答えが返り、10万件作ったつもりが実質3千通りの繰り返しだった、ということが起こります。生徒はその3千通りを丸暗記し、訓練損失はきれいに下がり、少しずれた入力で崩れます。
対策は地味です。埋め込みのコサイン類似度が閾値以上のペアを片方落とす、n-gramの使い回しを落とす、そして何より出力を多様化する前に入力の種類を増やすことです。
正しさのフィルタ — 間違いを一緒に写さないために
教師も間違えます。そして蒸留は教師の間違いをそっくりそのまま生徒へ写します。しかも生徒は「これは自信を持って言ってよい」という調子まで一緒に学ぶので、たちが悪い。
検算できるタスク——数学なら最終解の一致、コードならテストの通過——なら機械的に解決できます。教師に同じ問題を 回解かせ、正解にたどり着いた軌跡だけを残す。これが拒否サンプリング(rejection sampling)で、STaR が示した骨格です。残すのは答えではなく途中の推論過程だという点が肝心です。
落とし穴は、答えは合っているが途中が間違っている軌跡が混ざることです。選択肢問題なら当てずっぽうでも正解します。テストが厳しいタスクほど蒸留が効くのは、この偽陽性が少ないから。検算できない要約や助言にはこの安全網がなく、人手か別モデルの採点で埋めるしかありません。
DeepSeek-R1の蒸留が効いた理由
2025年のDeepSeek-R1は、ここまでの内容がそのまま実装された例として読めます。
論文で報告されている流れはこうです。強化学習で推論能力を伸ばしたR1を教師にし、そこから約80万件の学習データを作りました。内訳は推論系が約60万件、非推論系(質問応答や作文など)が約20万件。推論系は上で説明した拒否サンプリングで作られています。この80万件で Qwen と Llama の小さい既製モデルを普通の教師あり学習で微調整しました。強化学習は生徒側では回していません。
同時に報告された比較が重要です。小さいモデルに直接強化学習をかけるより、大きい教師から蒸留したほうが良い結果になった。理由はこの記事の枠組みで説明できます。強化学習は自力で正解軌跡を引き当てないと報酬が返りませんが、小さいモデルは難問でそれをめったに引けず、学習が進みません。蒸留なら正解軌跡を引く仕事を教師が肩代わりします。
つまりR1蒸留が運んだのは知識より探索の成果でした。80万件の裏にあるのは、教師がGPUを大量に燃やして見つけた「うまくいく解き方」の在庫です。モデル系列としての位置づけはDeepSeekファミリーで扱っています。
コードで書く: データ設計のループ
骨格は10行ちょっとです。教師呼び出しと検算を差し替えれば、自分のタスクに使えます。
def build_distill_data(prompts, teacher, student, check, k=8, temp=0.8):
data = []
for p in prompts:
if student_solves(student, p): # 生徒が既に解ける → 勾配が立たない
continue
cands = [teacher(p, temperature=temp) for _ in range(k)]
ok = [c for c in cands if check(p, c)] # 拒否サンプリング
if not ok or len(ok) == k: # 全滅=難しすぎ / 全通過=易しすぎ
continue
data.append((p, pick_shortest(ok))) # 冗長な軌跡を避ける
return dedupe_by_embedding(data, threshold=0.95)
len(ok) == k を捨てているのが要点です。8回中8回正解する問題は学習信号をほとんど生まないので、同じ予算なら中間の難易度に回したほうが伸びます。pick_shortest にも理由があります。長い軌跡を学んだ生徒は推論時のトークン数まで真似するので、推論コストがそのまま増えるからです。
現場ではこう使う
誰がいつ触るか。社内モデルの小型化を担当するMLエンジニアや、ドメイン特化モデルを作る応用チームの仕事です。発火点は「APIを毎回叩くと単価が合わない、7B級を自社で回したい」という要求で、最初の1〜2週間は学習ではなくデータ生成パイプラインの構築に消えます。
触るパラメータと道具。生成側は temperature(0.7〜1.0が定番。低すぎると重複、高すぎると不正解が増える)、top_p、プロンプトあたりの生成本数 。フィルタ側は検算スクリプト、近傍重複除去の類似度閾値、長さ上限。バッチ生成は vLLM や SGLang、重複除去は MinHash/SimHash か埋め込み+近似最近傍が定番です。
事故になる落とし穴。
- 評価セットの混入。種プロンプトを自動増殖させると、ベンチマーク問題の言い換えが訓練データに紛れ込みます。スコアだけ上がる、最も気づきにくい事故です。生成の前に種と評価セットの重複を取ること。
- 教師の利用規約。商用APIの出力を競合モデルの訓練に使うことは、多くのサービスで禁止されています。技術的に可能なことと契約上できることは別です。
- フィルタ後の分布の偏り。正解軌跡だけを残すとデータは「教師が得意な問題」に寄り、苦手分野は静かに消えます。フィルタ前後でカテゴリ別の件数を比較すること。
- 難易度フィルタの効かせすぎ。難問だけにすると、生徒は簡単な入力への素直な応答を忘れます。R1が非推論データを2割混ぜているのはこの保険です。
- 1回作って終わりにする。生徒が変われば「既に解ける問題」の集合も変わります。データ設計は、生徒の失敗を見て次の を決めるループです。
面接で問われる形。「教師は同じなのに蒸留した生徒の性能が大きく違った。何が違ったか」——筋道は損失関数ではなく を疑うことです。カバレッジ、重複率、難易度分布、フィルタの偽陽性率を順に見ます。
まとめ
- 現代のLLM蒸留は系列レベルなので、設計の自由度はほぼデータ側にある
- 損失は「 が選んだ入力の上でだけ」教師と生徒を一致させる。 の穴が生徒の弱点になる
- 勾配は食い違いに比例する。生徒が既に解ける問題を入れても学習は進まない
- 拒否サンプリングで正解軌跡だけを残す。偽陽性とフィルタが作る偏りに注意
- R1蒸留が効いたのは、小さいモデルが自力では引けない正解軌跡を教師が在庫にしたから
次は、こうして設計したデータでも蒸留が失敗するケース——教師と生徒の容量ギャップと、過信の伝染——を扱います。
コメント
コメントにはログインが必要です