LLMのアーキテクチャと最適化手法
この章では、大規模言語モデルの基礎となるアーキテクチャと、学習・推論を効率化する主要な最適化手法を扱います。内容はカリキュラムとして順序付けられており、まずTransformerそのものを取り上げ、効率的な学習、低コストな適応、圧縮、スケーリング、推論の高速化へと進みます。
LLMの仕組み:直感的な概要
アーキテクチャの詳細に入る前に、大規模言語モデルがどのようにテキストをテキストへ変換するのか、直感を養いましょう。全体の処理は、単純なパイプライン テキスト \(\to\) トークン \(\to\) 表現 \(\to\) トークン \(\to\) テキスト に従います。
Important
4つの主要ステージ
トークン化 :学習済みの語彙を使い、生のテキストをサブワード片(文字でも完全な単語でもない)へ分割します。「unhappiness」は [「un」、「happiness」] または [「unhapp」、「iness」] になることがあります。
埋め込み :各トークンIDで学習済みの埋め込みテーブルを参照し、\(\mathbb{R}^d\) の密ベクトル(通常は \(d = 4096\))を生成します。これらのベクトルは意味を捉え、似た単語には似たベクトルが割り当てられます。
文脈処理 :Transformerスタックは、自己注意を使って各位置が他のすべての位置から「読み取れる」ようにしながら、すべての埋め込みを並列処理します。\(L\) 層後には、各位置の隠れ状態が豊かな文脈情報を符号化します。
予測 :最後の隠れ状態を語彙全体にわたる確率分布へ射影し、デコーディング戦略で次のトークンを選択します。
トークン化
トークン化は、生のテキストを言語モデルが扱う離散記号へ変換する重要な最初のステップです。トークナイザーの選択は、モデル品質、多言語対応能力、計算効率に直接影響します。
Tip
なぜサブワードなのか?
文字レベルのモデルは非常に長いシーケンスを必要とし、アテンションのコストが高くなります。単語レベルのモデルは、まれな単語や新しい単語を扱えません。サブワードトークン化はこのバランスを理想的に取ります。一般的な単語は単一トークン(「the」 \(\to\) [the])になり、まれな単語は既知の断片(「cryptocurrency」 \(\to\) [「crypt」、「ocur」、「rency」])へ分解され、語彙サイズも扱いやすい範囲(32K〜128Kトークン)に収まります。
なぜ文字でも単語でもないのか?
| 粒度 | 語彙サイズ | シーケンス長 | 問題点 |
|---|---|---|---|
| 文字 | \(\sim\)256 | 非常に長い | アテンションコスト \(O(n^2)\)。長距離の意味を学習しにくい |
| 単語 | \(\sim\)500K+ | 短い | まれな単語や新語を扱えず、埋め込みテーブルが巨大になる |
| サブワード | 32K〜128K | 中程度 | 最良のトレードオフ:短いシーケンスと開かれた語彙 |
異なるトークン化粒度のトレードオフ。
Byte-Pair Encoding(BPE)
BPE (Sennrich et al. 2016) は、GPT、Llama、Mistral、その他の多くの現代的なLLMで使われる主要なトークン化アルゴリズムです。
Important
BPEアルゴリズム
個々の文字(バイト)からなる語彙を用意する
学習コーパス内の隣接する記号ペアをすべて数える
最も頻度の高いペアを新しい記号へマージする
目的の語彙サイズに達するまで、ステップ2〜3を \(k\) 回繰り返す
その他のトークン化手法
| 手法 | 使用例 | 主な考え方 |
|---|---|---|
| BPE | GPT-4 (OpenAI 2023), Llama-3 (Grattafiori et al. 2024), Mistral (Jiang et al. 2023) | 頻度の高いペアをボトムアップにマージ。決定的 |
| WordPiece | BERT (Devlin et al. 2019), DistilBERT (Sanh et al. 2019) | BPEに似ているが、学習データの尤度を最大化 |
| Unigram LM | SentencePiece (T5 (Raffel et al. 2020), XLNet (Yang et al. 2019)) | トップダウン:大きな語彙から始め、尤度への影響で削減 |
| Byte-level BPE | GPT-2 (Radford et al. 2019)+ | 生バイトに対するBPE(未知語トークンが存在しない)。基礎語彙は256 |
サブワードトークン化アルゴリズムの比較。
トークン化のベストプラクティス
-
語彙サイズは重要 :32Kは最小限であり、128Kなら多言語対応とコード処理が向上します。Llama-3は128Kトークンを使用します。
-
特殊トークン :
<bos>、<eos>、<pad>、<unk>は必ず含めます。指示調整済みモデルでは、役割マーカー(<|user|>、<|assistant|>)を追加します。 -
Fertility(分割度) :言語ごとに単語あたりのトークン数を測定します。Fertilityが高い(1単語あたりのトークンが多い)場合、その言語のカバレッジが低いことを示します。
-
境界をまたいでトークン化しない :空白、句読点、数字は一貫して扱う必要があります。現代の多くのトークナイザーは、単語の先頭トークンと継続トークンを区別するために、空白マーカー(「the」)を前置します。
-
数字 :算術タスクでは数字レベルのトークン化を検討します。「2024」を [「2」、「0」、「2」、「4」] とすれば、桁ごとの推論が可能になります。
-
コード :空白(インデント)が効率的にトークン化されるようにします。Llama-3は連続する空白を単一トークンとしてトークン化します。
実践的なトークン化:HuggingFaceの例
transformersライブラリは、すべてのトークナイザーに統一インターフェースを提供します。以下では、現代的なLLMトークナイザーによるエンコードとデコードを示します。
from transformers import AutoTokenizer
# Load Llama-3 tokenizer (128K vocabulary, byte-level BPE)
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Meta-Llama-3-8B")
text = "Reinforcement learning optimizes long-term rewards."
# Encode: text -> token IDs
token_ids = tokenizer.encode(text)
print(token_ids)
# [128000, 29934, 262, 11008, 4815, 6900, 1317, 9860, 21845, 13]
# Decode individual tokens to see subword splits
tokens = tokenizer.convert_ids_to_tokens(token_ids)
print(tokens)
# ['<|begin_of_text|>', 'Re', 'inforce', 'ment', ' learning',
# ' optimizes', ' long', '-term', ' rewards', '.']
# Decode back to text (round-trip)
reconstructed = tokenizer.decode(token_ids, skip_special_tokens=True)
assert reconstructed == text # Perfect reconstruction
# Tokenize with attention mask (for batched inputs with padding)
batch = tokenizer(
["Short text.", "A much longer input sentence for comparison."],
padding=True, return_tensors="pt"
)
print(batch.keys()) # dict_keys(['input_ids', 'attention_mask'])
特殊トークンと構造化プロンプト
特殊トークンは、言語的な内容ではなく構造的な意味を持つ、予約済みの語彙エントリです。モデルの挙動を制御するうえで不可欠です。
| トークン | 別名 | 目的 |
|---|---|---|
<bos> / `< | begin_of_text | >` |
<eos> / `< | end_of_text | >` |
| `< | user | >` |
| `< | assistant | >` |
<pad> | PAD | バッチを同じ長さにそろえる。アテンションではマスクされる |
<unk> | UNK | 語彙外のプレースホルダー(BPEではまれ) |
[SEP] | SEP | セグメントを区切る(BERT形式) |
[CLS] | CLS | 分類トークン(BERT) |
[MASK] | MASK | MLM事前学習でマスクされるトークン |
LLMファミリーに共通する特殊トークン。
指示調整済みモデルの役割マーカー
現代のチャットモデルは、会話の構造を区切るために特殊トークンを使います。これらは意味を担うように学習されるのではなく、モデルが解析方法を学習する構造上の区切り記号です。
# Llama-3 chat template
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Explain PPO in one sentence."},
]
# apply_chat_template handles all special token insertion
prompt = tokenizer.apply_chat_template(messages, tokenize=False)
print(prompt)
# <|begin_of_text|><|start_header_id|>system<|end_header_id|>
#
# You are a helpful assistant.<|eot_id|><|start_header_id|>user<|end_header_id|>
#
# Explain PPO in one sentence.<|eot_id|><|start_header_id|>assistant<|end_header_id|>
#
#
Important
特殊トークンのベストプラクティス
特殊トークンを分割しない :特殊トークンは不可分でなければなりません。トークナイザーが文字列ではなく単一の単位として扱うことを確認します。
特殊トークンの損失をマスクする :SFTでは、構造トークン(役割マーカーや区切り記号)に対する損失を計算しません。モデルに書式の予測を「学習」させるべきではありません。
構造にはテンプレートを使う :自然言語の指示ではなく、特殊トークンでタスクの意味を符号化します。たとえば、
<|tool_call|>は「これからツールを呼び出します:」より信頼性が高くなります。ツール/関数呼び出し :
<|function|>や<|result|>のような専用トークンを定義し、推論と行動の間に曖昧さのない境界を作ります。RLで一貫して扱う :PPO/GRPOでは、参照モデルと方策モデルが同一のトークン化と特殊トークン処理を使うようにします。不一致があるとKLの計算が壊れます。
EOSを扱う :生成時には、EOSが行動空間に含まれるようにします。モデルがEOSを出力できないと、応答が際限なく長くなります(RLでよくある失敗モードです)。
Transformerアーキテクチャ
Transformer (Vaswani et al. 2017) は、現代のLLMすべての基盤です。その構成要素を理解することは、このガイドで扱うあらゆる最適化・学習手法を把握するうえで不可欠です。
全体構造
Decoder-Only Transformerは、埋め込み、繰り返し配置されたアテンション+FFNブロック、語彙ロジットへの最終射影を通して、トークンを逐次処理します。図1.1にアーキテクチャ全体を示します。
元祖Encoder-Decoder Transformer
Transformerはもともと、系列変換タスク(機械翻訳、要約)向けの Encoder-Decoder アーキテクチャとして導入されました (Vaswani et al. 2017)。現代のLLMは主にDecoder-Only版(GPT形式)を使いますが、完全なアーキテクチャを理解することは重要です。ここで生まれたクロスアテンションとマスク付き自己注意は、今も基本的な構成要素だからです。
エンコーダ
エンコーダは入力シーケンス全体を 双方向に 処理します。つまり各トークンは他のすべてのトークンに注意を向けます(因果マスクはありません)。これにより、各位置が入力全体の情報を符号化する、豊かな文脈表現 \(\mathbf{H}^{\text{enc}} \in \mathbb{R}^{n \times d}\) が得られます。
-
入力 :トークン埋め込み+正弦波位置エンコーディング
-
各レイヤー :マルチヘッド自己注意 \(\to\) Add & Norm \(\to\) FFN \(\to\) Add & Norm
-
因果マスクなし :位置 \(i\) はすべての位置 \(1, \ldots, n\) に注意を向ける
-
出力 :入力シーケンス全体の文脈表現
デコーダ — マスク付きマルチヘッド自己注意
デコーダは出力トークンを一度に1つずつ(自己回帰的に)生成します。モデルが「未来を見る」ことを防ぐため、デコーダの自己注意には 因果マスク を使います。
\[ \text{MaskedAttn}(Q, K, V) = \text{softmax}!\left(\frac{QK^T}{\sqrt{d_k}} + M\right) V \]
ここでマスク \(M\) は次のとおりです。
\[ M_{ij} = \begin{cases} 0 & \text{if } i \geq j \text{ (can attend)} \\ -\infty & \text{if } i < j \text{ (future token --- blocked)} \end{cases} \]
Tip
マスキングが重要な理由
学習中、デコーダはターゲットシーケンス全体を並列に処理します(教師強制)。しかし自己回帰性を保つには、各位置が直前までの位置だけに注意を向けなければなりません。このマスクにより、トークン \(t\) の生成にはトークン \(1, \ldots, t{-}1\) の情報だけが使われます。推論時はトークンを1つずつ生成するためマスクは暗黙的ですが、学習時には因果性を保ちながら並列計算を可能にします。
デコーダ — クロスアテンション
マスク付き自己注意の後、各デコーダレイヤーは クロスアテンション を適用します。ここではデコーダがエンコーダの出力表現に注意を向けます。これが、デコーダが入力を「読み取る」仕組みです。
\[ \text{CrossAttn}(Q_{\text{dec}}, K_{\text{enc}}, V_{\text{enc}}) = \text{softmax}!\left(\frac{Q_{\text{dec}} K_{\text{enc}}^T}{\sqrt{d_k}}\right) V_{\text{enc}} \]
-
クエリ はデコーダの直前のサブレイヤー(マスク付き自己注意の出力)から来る
-
キーとバリュー はエンコーダの最終出力 \(\mathbf{H}^{\text{enc}}\) から来る
-
マスクは 適用しない。すべてのデコーダ位置が、すべてのエンコーダ位置に注意を向けられる
-
これにより、デコーダは生成ステップごとに入力の異なる部分へ動的に焦点を当てられる(たとえば英語\(\to\)スペイン語の翻訳で「cat」から「gato」へ訳す際に「cat」へ注意を向ける)
完全なデコーダレイヤー
各デコーダレイヤーには、エンコーダの2つに対して3つのサブレイヤーがあります。
-
マスク付きマルチヘッド自己注意+残差+LayerNorm
-
マルチヘッドクロスアテンション (エンコーダ出力に対するもの)+残差+LayerNorm
-
フィードフォワードネットワーク+残差+LayerNorm
Encoder-DecoderからDecoder-Onlyへ
現代のLLM(GPT、Llama、Qwen)はデコーダだけを使い、エンコーダとクロスアテンションレイヤーを完全に取り除いています。重要な洞察は、生成言語モデリングには単一の因果(マスク付き)自己注意スタックで十分だということです。モデルは1回のパスで文脈の符号化と続きの生成を学習します。これによりアーキテクチャ、学習、推論が単純になり、より効果的にスケールできます。Encoder-Decoderモデル(T5、BART)は、入力と出力の構造が分かれるタスク(翻訳、要約)では依然として有用です。また、ビジョンエンコーダが言語デコーダへキー/バリューを提供するマルチモーダルモデルでは、クロスアテンションが再び現れます。
Decoder-OnlyとEncoder-Decoderの比較
現代のLLMはほぼ例外なくDecoder-Onlyアーキテクチャを使いますが、Encoder-Decoder設計とのトレードオフを理解すると、その理由が明確になります。
| アーキテクチャ | 例 | 用途 |
|---|---|---|
| Decoder-only | GPT-4 (OpenAI 2023), Llama (Grattafiori et al. 2024), Mistral (Jiang et al. 2023), Qwen (Q. Team 2024a) | 自己回帰生成。チャット/推論で主流 |
| Encoder-decoder | T5 (Raffel et al. 2020), BART (M. Lewis et al. 2020), Flan-T5 (Chung et al. 2024) | Seq2seq(翻訳、要約)。現在は少数派 |
| Encoder-only | BERT (Devlin et al. 2019), RoBERTa (Liu et al. 2019) | 分類/埋め込み。生成には使わない |
Warning
Decoder-Onlyが勝った理由
Decoder-Onlyモデルは、構造が単純で(1つのモデル、1つの損失)、よりよくスケールし(すべてのパラメータが生成に寄与し)、統一的な学習(事前学習=次トークン予測=ファインチューニングの目的)を実現します。Encoder-Decoderモデルは、純粋な生成タスクではエンコーダに容量を割いてしまいます。
埋め込み:離散トークンから連続空間へ
アテンションや計算を始める前に、Transformerは離散的なトークンIDを、ニューラルネットワークが処理できる連続ベクトルへ変換しなければなりません。これが 埋め込み層 の役割です。
埋め込みとは何か?
埋め込みとは、離散記号を学習された密ベクトルで表現したものです。「king」を、ほとんどがゼロであるサイズ \(\vert \mathcal{V}\vert = 128{,}000\) のone-hotベクトルで表す代わりに、その 意味 を捉える \(\mathbb{R}^d\) 内のコンパクトなベクトル(例:\(d = 4096\))で表します。
重要な洞察は、 似た概念には近いベクトルが割り当てられる ことです。十分に学習された埋め込み空間では、次のようになります。
-
「king」と「queen」は近い(どちらも王族)
-
「king」と「bicycle」は遠い(無関係)
-
ベクトル演算が関係を捉える:\(\vec{\text{king}} - \vec{\text{man}} + \vec{\text{woman}} \approx \vec{\text{queen}}\)
埋め込みテーブル
実際には、埋め込み層は単純な行列 \(\mathbf{E} \in \mathbb{R}^{\vert \mathcal{V}\vert \times d}\) です。行 \(i\) にはトークン \(i\) の埋め込みベクトルが格納されます。
\[ \text{embed}(x_t) = \mathbf{E}[x_t] \in \mathbb{R}^d \]
トークンIDのシーケンス \([x_1, x_2, \ldots, x_n]\) に対する埋め込みは、単純なテーブル参照(インデックス操作)です。
\[ \mathbf{H}_0 = [\mathbf{E}[x_1];; \mathbf{E}[x_2];; \ldots;; \mathbf{E}[x_n]] \in \mathbb{R}^{n \times d} \]
Important
Transformerにおける埋め込みテーブル
サイズ :\(\vert \mathcal{V}\vert \times d\)。Llama-3の場合、\(128{,}256 \times 4{,}096 = 525\)Mパラメータ(8Bモデルの6.5%)。
初期化 :ランダム(Xavier/正規分布)で初期化し、その後バックプロパゲーションで学習する。
重み共有 :多くのモデルは、埋め込み行列と出力射影ヘッドを 共有 します:\(W_{\text{head}} = \mathbf{E}^T\)。パラメータを節約し、対称的なエンコード・デコード構造を作ります。
入力 :トークンID(整数)\(\to\) 出力 :\(\mathbb{R}^d\) 内の密ベクトル。
勾配の流れ :学習中は、現在のバッチに含まれるトークンに対応する行だけが勾配更新を受ける(スパース更新)。
Tip
埋め込みが機能する理由
埋め込みテーブルはモデルの他の部分とエンドツーエンドで学習されます。モデルは次のトークンを予測するよう学習されるため、似た文脈に現れるトークンに似たベクトルを割り当てる表現を学習しなければなりません。これは分布仮説、すなわち「単語は共に現れる語によって知ることができる」という考えです (Firth 1957)。埋め込み層はこの統計的構造を密な幾何へ圧縮します。
異方性の問題
事前学習済み埋め込み(BERTやGPT-2など)を検索(RAG)や推薦システムの初期構築といった下流タスクに使うと、重大な問題が生じます。学習された表現は非常に 異方的 で、全方向に一様に分布するのではなく、埋め込み空間内の狭い円錐に集中します (Ethayarajh 2019)。
これが応用上重要な理由:
-
RAG/検索 :内容に関係なくすべての埋め込みのコサイン類似度が \(>0.7\) なら、検索順位はほぼランダムになります。システムは関連する文章と無関係な文章を区別できません。
-
推薦システム :事前学習済みLLMの埋め込みでアイテムやユーザーを表すには、幾何構造が意味のある類似性を保っていなければなりません。
-
クラスタリング :異方的な埋め込みではクラスタがつぶれ、自然なグループ分けを見つけられません。
解決策:ホワイトニング
単純で効果的な修正方法が ホワイトニング です (Su et al. 2021)。これは埋め込み分布を等方的(平均0、共分散が単位行列)にする線形変換です。
\[ \tilde{\mathbf{h}} = \mathbf{D}^{-1/2} \mathbf{U}^T (\mathbf{h} - \boldsymbol{\mu}) \]
ここで \(\boldsymbol{\mu}\) は平均埋め込み、\(\mathbf{U}\mathbf{D}\mathbf{U}^T\) は共分散行列 \(\Sigma = \frac{1}{N}\sum_i (\mathbf{h}_i - \boldsymbol{\mu})(\mathbf{h}_i - \boldsymbol{\mu})^T\) の固有値分解です。
Important
ホワイトニングの実践
働き :すべての方向の分散が等しくなるよう、埋め込み空間を回転・スケーリングする(共分散を単位行列にする)。
効果 :コサイン類似度が意味を持つようになる。意味的に似たペアは高く、異なるペアは低くなる。
利点 :上位 \(k\) 個の固有ベクトルだけを残すことで(PCAと同様に)次元削減も同時に行え、検索が高速になる。
コスト :代表的なコーパス上で共分散行列を計算する必要がある(1回だけ、\(O(N \cdot d^2)\))。変換自体は推論時の単純な行列積である。
代替手法 :対照学習によるファインチューニング(SimCSE)、フローベースの正規化、等方性を促す正則化を使った学習。
自己注意機構
自己注意は、各トークンがシーケンス内の他のすべてのトークンに注意を向け、関連度に基づく重み付き結合を計算できるようにする中核演算です。
Important
スケールド・ドット積アテンション
入力シーケンス \(X \in \mathbb{R}^{n \times d}\) に対して、次を計算します。 \[ Q = XW_Q, \quad K = XW_K, \quad V = XW_V \quad (W_Q, W_K, W_V \in \mathbb{R}^{d \times d_k}) \]
\[ \text{Attention}(Q, K, V) = \text{softmax}!\left(\frac{QK^T}{\sqrt{d_k}} + M\right) V \] ここで \(M\) は 因果マスク (自己回帰モデル用)です:\(i \geq j\) なら \(M_{ij} = 0\)、それ以外なら \(-\infty\) です。
直感 :各トークンはそれ以前のすべてのトークンに「注意を向け」、クエリとキーの類似度に基づいて、それらのバリューの重み付き平均を計算します。
計算量
素朴なアテンション計算のシーケンス長に対するコストは 二次 です。
-
時間 :\(O(n^2 \cdot d)\)。\(QK^T\) の計算には、次元 \(d_k\) の内積が \(n^2\) 個必要です。
-
メモリ :\(O(n^2)\)。softmaxを適用するには、アテンション行列全体を実体化する必要があります。
\(d = 4096\) の128Kトークン文脈では、アテンション行列だけで \(128\text{K} \times 128\text{K} = 16.4\) 十億エントリ(FP32で64 GB)になります。この二次スケーリングが、長文脈LLMにおける根本的なボトルネックです。
| シーケンス長 | アテンション演算 | 行列サイズ | 実用上の影響 | |
|---|---|---|---|---|
| 2K | 4M | 16 MB | 高速。SRAMに収まる | |
| 8K | 64M | 256 MB | FlashAttentionなら管理可能 | |
| 32K | 1B | 4 GB | メモリ効率のよいカーネルが必要 | |
| 128K | 16B | 64 GB | 単一GPUのHBMを超える | |
| 1M | 1T | 4 TB | 二次未満の手法なしには不可能 |
アテンションコストのスケーリング:長いシーケンスで素朴な実装が法外になる理由。
アテンションコストを抑えるアプローチ
この二次ボトルネックには、いくつかの解決策の系統があります。
-
IOを意識した厳密なアテンション(FlashAttention (Dao et al. 2022)) :計算量は減らしませんが、SRAMに収まるタイルでアテンションを計算することで、HBM上に \(n \times n\) 行列を実体化する必要をなくします。重要なのは、FlashAttentionが 直交する ことです。これはアテンションパターンではなく実行エンジンです。実運用システムでは、FlashAttentionとスライディングウィンドウやブロックスパースマスクを組み合わせ、I/O効率とFLOPs削減の両方を得るのが一般的です。アルゴリズムの詳細は1.6節で扱います。
-
スライディングウィンドウ/局所アテンション :各トークンは最も近い \(w\) 個のトークン(例:\(w = 4096\))にだけ注意を向けます。コストは \(O(n \cdot w)\) となり、\(n\) に対して線形です。Mistral (Jiang et al. 2023)(ウィンドウ \(= 4096\))やLongformer (Beltagy et al. 2020)で使われています。効率性の代わりにグローバルな文脈を一部失いますが、実際には大部分のアテンションが局所的なのでうまく機能します。現代のスタックでは、スライディングウィンドウマスクはFlashAttentionカーネル 内部 で実行されます。
-
スパースアテンションパターン :局所ウィンドウと周期的なグローバルトークン(例:512個ごとのトークンがすべてに注意を向ける)を組み合わせます。BigBird (Zaheer et al. 2020)やLongT5 (Guo et al. 2022)がこれを使います。コスト \(O(n\sqrt{n})\) で、長距離の接続性を一部保ちます。ここでもFlashAttentionは、ゼロでないアテンションブロックの基盤カーネルとして機能します。
-
線形アテンション/状態空間モデル :結合則を使って \(\text{softmax}(QK^T)V\) を \(\phi(Q)(\phi(K)^T V)\) に置き換えるか、漸化式として定式化し直します(Mamba (Gu and Dao 2023)、RWKV (Bo Peng et al. 2023))。理論上の総コストは \(O(n \cdot d^2)\) です。上の2〜3とは異なり、これらはモデルの表現力を変える アーキテクチャ置換 です。softmaxなしのアテンションは本質的に表現力が低く、正確な長距離検索や複雑な推論を必要とするタスクでは、実証的にもこれらのモデルはTransformerにまだ遅れています。
-
KVキャッシュ圧縮 :推論時に古いKVペアを圧縮・破棄し、メモリを一定範囲に抑えます。手法には、H\(_2\)O (Z. Zhang et al. 2023)(heavy-hitter oracle:アテンションの高いキーだけを残す)、StreamingLLM (Xiao et al. 2024a)(初期の「アテンションシンク」トークンと直近ウィンドウを残す)、量子化KVキャッシュ (Z. Liu et al. 2024)があります。
Tip
FlashAttention+スパースパターン=両方の利点
FlashAttentionはスパースアテンションの 代替 だという誤解があります。そうではありません。これはアテンションカーネルのI/O最適化であり、任意のアテンションマスクと自由に組み合わせられます。現代のプロダクションシステム(Mistral、DeepSeekなど)は、スライディングウィンドウまたはブロックスパースマスクの 下層 の実行エンジンとしてFlashAttentionを使います。これにより、スパース性によるFLOPs削減と、タイル化による最適なメモリアクセスパターンの両方が得られます。RingAttention (H. Liu et al. 2023) はこれをマルチデバイス環境へ拡張し、シーケンス方向にタイル化された計算をGPU間に分散します。
線形アテンションと状態空間モデル(Mamba、RWKV)は、本質的に異なるアーキテクチャ上の選択です。完全なペアごとの相互作用を犠牲にして \(O(n)\) の計算量を得ます。理論的には洗練されていますが、知識集約的なタスクや長距離推論タスクでTransformerの品質に追いついておらず、最先端の研究所は今も厳密なアテンション(FlashAttention+スパース性)をバックボーンとして使い続けています。
マルチヘッドアテンション
単一のアテンション関数を計算する代わりに、マルチヘッドアテンションは複数のアテンション演算を並列に実行します。各ヘッドは入力の異なる側面(構文、意味、位置など)に焦点を当てるよう学習します。
Important
マルチヘッドアテンション
\(d\) 次元のキー/バリューを持つ1つのアテンション関数の代わりに、次元 \(d_k = d/H\) の \(H\) 個のヘッドを並列に使います。 \[ \text{MultiHead}(X) = \text{Concat}(\text{head}_1, \ldots, \text{head}_H) W_O \] 各ヘッドは異なるアテンションパターンを学習できます(例:構文用、意味用、位置の近さ用にそれぞれ1つのヘッド)。
Grouped Query Attention(GQA) :Llama-3 (Grattafiori et al. 2024) は、Qヘッドより少ないK、Vヘッドを使います(例:32個のQヘッドで8個のKVヘッドを共有)。品質をほとんど損なわずにKVキャッシュのサイズを \(4\times\) 削減できます。
位置エンコーディング
Transformerは構造上、置換同変です。位置情報がなければ、モデルは「the cat sat on the mat」と「mat the on sat cat the」を区別できません。位置エンコーディングはシーケンス順序のシグナルを注入し、アテンションがトークン間の距離と方向を推論できるようにします。
| 手法 | 使用例 | 主な考え方 |
|---|---|---|
| Sinusoidal | 元祖Transformer | 異なる周波数の固定 \(\sin/\cos\)。学習しない。 |
| Learned Absolute | GPT-2 (Radford et al. 2019), BERT (Devlin et al. 2019) | 位置ごとに埋め込みを学習する。学習時の長さに制限される。 |
| RoPE (Rotary) | Llama (Grattafiori et al. 2024), Qwen (Q. Team 2024a), Mistral (Jiang et al. 2023) | 位置依存の角度でQ、Kベクトルを回転する。NTKを意識したスケーリングで外挿する。 |
| ALiBi | BLOOM (Workshop 2023), MPT (MosaicML 2023) | 位置埋め込みを使わず、アテンションスコアに線形バイアス \(-m\vert i-j\vert\) を加える。単純で外挿性が高い。 |
現代のLLMにおける位置エンコーディング手法。
正弦波(固定)位置エンコーディング
元祖Transformer (Vaswani et al. 2017) で導入されたこの手法は、等比間隔の周波数における固定正弦関数を使います。
\[ \text{PE}(pos, 2i) = \sin!\Bigl(\frac{pos}{10000^{2i/d}}\Bigr), \qquad \text{PE}(pos, 2i{+}1) = \cos!\Bigl(\frac{pos}{10000^{2i/d}}\Bigr) \]
ここで \(pos\) はトークン位置、\(i\) は次元インデックス、\(d\) はモデルの次元です。
動機 :各周波数は異なるスケールで位置を符号化します(2進数のカウントに似ています)。著者らは、\(\text{PE}(pos+k)\) を \(\text{PE}(pos)\) の線形関数として表せるため、モデルが相対位置へ注意を向けることを学習できると仮定しました。
長所 :学習パラメータがゼロ。決定的。理論上は任意の長さに対応する。
短所 :実際には学習時の長さを超えるとうまく外挿できない。モデルは絶対信号から相対位置を間接的に復号する必要があり、現在はほぼ置き換えられている。
学習型絶対位置埋め込み
GPT-2 (Radford et al. 2019) とBERT (Devlin et al. 2019)で使われています。学習可能な埋め込み行列 \(\mathbf{E}_{\text{pos}} \in \mathbb{R}^{L_{\max} \times d}\) をトークン埋め込みに加えます。
\[ h_0^{(pos)} = \text{TokenEmbed}(x_{pos}) + \mathbf{E}_{\text{pos}}[pos] \]
動機 :固定構造を押し付けるのではなく、タスクに最適な位置表現をモデル自身に学習させる。
長所 :柔軟性が最大。実装が単純。短いシーケンスでは正弦波を上回ることが多い。
短所 :最大長 \(L_{\max}\) がハードコードされ、それを超えて一般化できない。\(L_{\max}\) の末尾近くの埋め込みは学習不足になる。\(L_{\max} \times d\) 個のパラメータが増える。
回転位置埋め込み(RoPE)
RoPE (Su et al. 2024) は、2次元部分空間内でクエリとキーベクトルを 回転 させることで位置を符号化します。
\[ \text{RoPE}(x_m, m) = \begin{pmatrix} x_m^{(1)} \\ x_m^{(2)} \\ \vdots \\ x_m^{(d-1)} \\ x_m^{(d)} \end{pmatrix} \odot \begin{pmatrix} \cos m\theta_1 \\ \cos m\theta_1 \\ \vdots \\ \cos m\theta_{d/2} \\ \cos m\theta_{d/2} \end{pmatrix} + \begin{pmatrix} -x_m^{(2)} \\ x_m^{(1)} \\ \vdots \\ -x_m^{(d)} \\ x_m^{(d-1)} \end{pmatrix} \odot \begin{pmatrix} \sin m\theta_1 \\ \sin m\theta_1 \\ \vdots \\ \sin m\theta_{d/2} \\ \sin m\theta_{d/2} \end{pmatrix} \]
ここで \(\theta_i = 10000^{-2i/d}\)、\(m\) は位置インデックスです。重要な性質は、回転後のクエリとキーの内積が相対位置だけに依存することです。
\[ \langle \text{RoPE}(q_m, m),; \text{RoPE}(k_n, n) \rangle = f(q_m, k_n, m-n) \]
動機 :明示的なバイアス項なしに相対位置の符号化を実現し、線形アテンションやKVキャッシュとの互換性も保つ。
長所 :自然に相対的。追加パラメータ不要。効率的な推論と互換性がある。NTKを意識したスケーリング (Bowen Peng et al. 2023) やYaRN(\(\theta\) の基底を調整する、または周波数を補間する)で長い文脈へ拡張できる。
短所 :アテンション演算ごとの計算量がやや増える(回転+インターリービング)。外挿には明示的なスケーリング戦略が必要。2次元部分空間での回転が構造を課すため、すべてのタスクに最適とは限らない。
Tip
RoPEの長さ拡張
\(L\) で学習したRoPEモデルを文脈長 \(L' > L\) へ拡張するには、次のようにします。
位置補間 :すべての位置が \([0, L]\) に収まるよう、位置を \(L/L'\) 倍にスケールする。単純だが解像度が圧縮される。
NTKを意識したスケーリング :\(\theta\) の基底を増やす(例:\(10000 \to 10000 \cdot (L'/L)^{d/(d-2)}\))。低周波成分を保ちながら高周波成分を実質的に引き伸ばす。
YaRN (Bowen Peng et al. 2023):NTKスケーリングとアテンション温度補正 \(t = 0.1 \ln(s) + 1\) を組み合わせ、長距離で増えるエントロピーを補正する。
ALiBi(線形バイアス付きアテンション)
ALiBi (Press et al. 2022) は根本的に異なるアプローチを取ります。位置埋め込みをまったく使いません。その代わり、固定の線形ペナルティをアテンションスコアから差し引きます。
\[ \text{Attention}(Q, K, V) = \text{softmax}!\left(\frac{QK^T}{\sqrt{d_k}} - m \cdot \bigl[|i-j|\bigr]_{i,j}\right) V \]
ここで \(m\) はヘッド固有の傾きです(全 \(H\) 個のヘッドのうちヘッド \(h\) に対して、幾何的に \(m_h = 2^{-8h/H}\) と設定)。バイアス \(-m\vert i-j\vert\) は、幅がヘッドごとに変わる緩やかな局所アテンションウィンドウを作ります。
動機 :埋め込み空間に干渉せず、位置によって近いトークンへアテンションを偏らせるべきです(新しさの事前分布)。アテンションスコア空間だけで動作するため、ALiBiはトークン表現を位置シグナルで汚しません。
長所 :長さの外挿性が非常に高い(1Kで学習して8K以上で動作)。パラメータゼロ。実装が容易。ヘッド固有の傾きにより、複数スケールの局所性を持つ。
短所 :正確な長距離位置推論を必要とするタスク(例:「5番目の単語は何だったか?」)では表現力が低い。線形減衰という強い帰納バイアスがすべての領域に適するとは限らない。近年のモデルでは、短文脈での性能がより高いRoPEにほぼ取って代わられている。
| 正弦波 | 学習型絶対 | RoPE | ALiBi | |
|---|---|---|---|---|
| 追加パラメータ | なし | \(L_{\max} \times d\) | なし | なし |
| 位置の種類 | 絶対 | 絶対 | 相対 | 相対(暗黙) |
| 長さの外挿 | 低い | なし | 良好(スケーリングあり) | 優れている |
| 計算オーバーヘッド | 無視できる | 無視できる | 小さい | 無視できる |
| 主流の時期 | 2017〜19 | 2018〜20 | 2022〜現在 | 2022〜23 |
位置エンコーディングの比較:実用上のトレードオフ。
極端に長い文脈へのスケーリング(100K〜1M以上のトークン)
現代の最先端モデル(200K〜1M文脈のClaude (Anthropic 2024c)、1M以上のGemini 1.5 (Gemini Team 2024)、128KのGPT-4 (OpenAI 2023))には、学習時の長さをはるかに超えても忠実に機能する位置エンコーディングが必要です。現在の主流の解決策は次のとおりです。
-
周波数スケーリング付きRoPE :RoPEを学習時の長さを超えて拡張する標準的な方法です。再学習する代わりに、基底周波数 \(\theta\) を再スケーリングします。
\[ \theta'_i = \theta_i \cdot \left(\frac{L_{\text{target}}}{L_{\text{train}}}\right)^{2i/d} \]
その派生には次がある。
-
線形スケーリング(位置補間) (S. Chen et al. 2023):位置インデックスを係数 \(s\) で単純に割る。安価だが、拡張比が大きいと品質が低下する。
-
NTKを意識したスケーリング (Bowen Peng et al. 2023):基底周波数を \(\theta = 10000 \to 10000 \cdot s^{d/(d-2)}\) とスケールする。高周波(局所)情報を保ちながら、低周波(グローバル)の範囲を拡張する。
-
YaRN (Bowen Peng et al. 2023)(Yet another RoPE extensioN):NTKスケーリングとアテンション温度補正、小規模な長文脈コーパスでのファインチューニングを組み合わせる。Llama-3では学習時の8Kからデプロイ時の128Kへ拡張するために使われる。
-
Dynamic NTK (Bowen Peng et al. 2023):推論時の実際のシーケンス長に応じて、スケーリング係数をオンザフライで調整する。固定の拡張比は不要で、文脈が長くなるとモデルが適応する。
-
-
長いデータでの継続事前学習 :RoPEスケーリングを使っても、長い文書で短期間(1〜5Bトークン)の継続事前学習を行うとモデルは向上します。これにより、位置的に耐えられるだけでなく、遠い文脈を実際に 使う ことを学習します。Llama-3.1では8K \(\to\) 64K \(\to\) 128Kという段階的スケジュールを使いました。
-
Ring Attention/ブロック単位並列 (H. Liu et al. 2023):単一GPUのメモリを超えるシーケンス(1M以上のトークン)では、Ring Attentionがリング型トポロジーでシーケンスをGPU間に分散します。各GPUが1ブロックを保持し、KVブロックをリングに沿って渡しながら局所アテンションタイルを計算します。厳密なアテンションを保ったまま、GPU数に対してメモリを線形にスケールできます。
-
ハイブリッドアーキテクチャ :一部のシステムは、大部分のレイヤーで局所的なスライディングウィンドウ(例:4K)を使い、選択したレイヤー(例:4層ごと)では完全なアテンションを組み合わせます。これにより、グローバルな情報の流れを保ちながら、ほとんどの計算を \(O(n \cdot w)\) のコストで行えます。
Warning
長い文脈 $\neq$ 長い文脈利用
コンテキスト長が1Mのモデルが、1Mトークンすべてを必ずしも効果的に使えるとは限らない。「中間で失われる」現象(N. F. Liu et al. 2024a)は、モデルが長いコンテキストの先頭と末尾に集中し、中間の情報を十分に利用しない傾向を示す。長文脈を効果的に利用するには、位置エンコーディングのサポートと長距離検索に報いるタスクでの学習の両方が必要である。
フィードフォワードネットワーク(MLP)
各Transformerブロックには、各位置へ独立に適用されるMLPが含まれる。
\[ \text{FFN}(x) = W_2 \cdot \sigma(W_1 x + b_1) + b_2 \]
ここで \(W_1 \in \mathbb{R}^{d \times 4d}\)、\(W_2 \in \mathbb{R}^{4d \times d}\) です。現代のLLMでは次を使います。
-
SwiGLU活性化 :\(\text{FFN}(x) = W_2 (\text{Swish}(W_1 x) \odot W_3 x)\)。Llama (Grattafiori et al. 2024) やMistral (Jiang et al. 2023)で使われます。重み行列が3つ必要ですが、性能が向上します。
-
隠れ次元は通常 \(8/3 \times d\) です(Tensor Coreの効率のため256の倍数に丸めます)。
Tip
メモリとしてのFFN
近年の研究 (Geva et al. 2021) は、FFNレイヤーが キーバリューメモリ として機能すると示唆しています。\(W_1\) の行はキー(照合するパターン)、\(W_2\) の列はバリュー(出力する情報)です。FFNは現在の隠れ状態に基づき、保存された知識を「取り出します」。
Layer Normalization(層正規化)
Layer Normalizationは特徴次元にわたって活性値を正規化し、学習を安定させます。アテンション/FFNサブレイヤーに対する配置は、学習ダイナミクスに大きな影響を与えます。
LayerNormの仕組み
隠れ状態ベクトル \(\mathbf{x} \in \mathbb{R}^d\)(1つのトークンの表現)に対して、LayerNorm (Ba et al. 2016) は次を計算します。
\[ \text{LayerNorm}(\mathbf{x}) = \gamma \odot \frac{\mathbf{x} - \mu}{\sqrt{\sigma^2 + \epsilon}} + \beta \]
ここで、
-
\(\mu = \frac{1}{d}\sum_{i=1}^{d} x_i\)(\(d\) 個の特徴次元にわたる平均)
-
\(\sigma^2 = \frac{1}{d}\sum_{i=1}^{d} (x_i - \mu)^2\)(特徴にわたる分散)
-
\(\gamma, \beta \in \mathbb{R}^d\) は 学習される スケール・シフトパラメータ(次元ごと)
-
\(\epsilon \approx 10^{-5}\) はゼロ除算を防ぐ
BatchNormとの重要な違い :LayerNormはバッチ全体ではなく、1つの例の 特徴次元 にわたって正規化します。そのためバッチサイズに依存せず、学習時と推論時で同じように動作します。
RMSNorm — 現代的な簡略化
RMSNorm (Zhang and Sennrich 2019) は平均を中心化するステップを省き、二乗平均平方根だけで正規化します。
\[ \text{RMSNorm}(\mathbf{x}) = \gamma \odot \frac{\mathbf{x}}{\text{RMS}(\mathbf{x})}, \qquad \text{RMS}(\mathbf{x}) = \sqrt{\frac{1}{d}\sum_{i=1}^{d} x_i^2} \]
\(\beta\)(シフト)パラメータも平均の減算もなく、スケールだけを行います。トークンごとに1回のリダクション演算を節約でき、同等のモデル品質を保ちながらGPU上で \(\sim\) 5〜10%高速になります。現代のLLM(Llama、Mistral、Qwen)はすべてRMSNormを使います。
Important
Pre-LNとPost-LNの比較
Post-LN (元祖Transformer):\(h + \text{LayerNorm}(\text{Attn}(h))\)。慎重なウォームアップが必要で、学習が不安定になり得る。
Pre-LN (GPT-2以降、現代のLLMすべて):\(h + \text{Attn}(\text{LayerNorm}(h))\)。学習を安定させ、より高い学習率を可能にする。
RMSNorm (Llama (Grattafiori et al. 2024)、Mistral (Jiang et al. 2023)):平均中心化を行わない簡略版LayerNorm:\(\text{RMSNorm}(x) = x / \text{RMS}(x) \cdot \gamma\)。やや高速で品質は同じ。
Tip
深いネットワークで正規化が重要な理由
正規化がないと、活性値はレイヤーを通るにつれて指数的に増大・縮小します(活性値の爆発・消失)。LayerNormのない128層Transformerでは、最初と最後のレイヤーで大きさが \(10^{30}\times\) も変わり得ます。正規化は各レイヤーの出力を予測可能な範囲に制限し、安定した勾配の流れと、ネットワーク全体で一貫した学習率の利用を可能にします。
モデルサイズの目安
以下の表は、広く使われているオープンウェイトモデル(2025年時点の最新版)の主要なアーキテクチャパラメータをまとめたもので、規模と設計上の選択を理解するための早見表です。
| モデル | パラメータ | レイヤー | \(d\) | ヘッド | KVヘッド | 文脈 |
|---|---|---|---|---|---|---|
| Llama-3.1 8B (Grattafiori et al. 2024) | 8B | 32 | 4096 | 32 | 8 | 128K |
| Llama-3.1 405B (Grattafiori et al. 2024) | 405B | 126 | 16384 | 128 | 8 | 128K |
| Llama-4 Maverick (AI 2025) | 400B (17B active) | 48 | 5120 | 40 | 8 | 1M |
| Mistral Large 2 (AI 2024) | 123B | 88 | 12288 | 96 | 8 | 128K |
| Qwen-2.5 72B (Q. Team 2024a) | 72B | 80 | 8192 | 64 | 8 | 128K |
| DeepSeek-V3 (DeepSeek-AI 2024b) | 671B (37B active) | 61 | 7168 | 128 | MLA | 128K |
人気のオープンウェイトLLM(2024〜2025世代)のアーキテクチャパラメータ。
注:「active」と記されたパラメータを持つモデルはMixture-of-Experts(MoE)アーキテクチャを使います。総パラメータ数はモデル容量を示し、activeパラメータはトークンごとの計算コストを表します。DeepSeek-V3は標準GQAの代わりにMulti-head Latent Attention(MLA)を使い、KVを低ランクの潜在空間へ圧縮します。
アテンションの病理
アテンション機構は強力ですが、体系的な失敗モードも示します。特に長い文脈へスケールする場合や、モデルの挙動を解釈する場合には、実務者が理解しておく必要があります。
アテンションシンク
現象
Xiaoら (Xiao et al. 2024b) は、Transformerモデルが意味内容に関係なく、シーケンスの 最初のトークン に不釣り合いに高いアテンションスコアを割り当てることを発見しました。最初のトークンが意味を持たない <BOS> マーカーであっても、全レイヤーのアテンションヘッドが一貫してそこへ注意を向け、総アテンション量の20〜50%に達することさえあります。
なぜ起こるのか
Softmaxアテンションは妥当な確率分布(\(\sum_j \alpha_j = 1\))を生成しなければなりません。クエリに特に関連するキーがないとき、モデルには未使用のアテンション量を捨てる場所が必要です。学習中、最初のトークンは常に存在し位置的に予測しやすいため、このデフォルトのシンクになります。これは 何もしないアテンションの対象 として機能し、モデルは無関係なアテンションを予測不能に分散させず、そこへ送ることを学習します。
\[ \alpha_{\text{sink}} = \frac{\exp(q^\top k_0 / \sqrt{d})}{\sum_{j} \exp(q^\top k_j / \sqrt{d})} \gg \frac{1}{n} \quad \text{(even when } k_0 \text{ is semantically irrelevant)} \]
結果
-
ストリーミング推論の失敗 :スライディングウィンドウKVキャッシュを使うとき、最初のトークンを破棄するとパープレキシティが壊滅的に急上昇します。モデルがアテンションシンクを失うためです。
-
誤解を招く解釈可能性 :素朴なアテンション可視化では、単なる数学的な人工物である最初のトークンが「重要」に見えます。
-
文脈ウィンドウの浪費 :シンクトークンは有用な情報を持たないまま、KVキャッシュのスロットを占有します。
解決策
-
StreamingLLM (Xiao et al. 2024b:最近のスライディングウィンドウとともに、最初の\(k\)個のトークン(「アテンションシンク」)を常にKVキャッシュに残す。メモリを一定に保ったまま無限長の生成を可能にする。
-
設計によるシンクトークン :一部のモデル(Mistralなど)は学習時に専用のシンクトークンを前置します。これは残余アテンションを吸収する目的で明示的に使われます。
-
Softmaxの代替 :softmaxをReLUアテンションやシグモイドゲーティングへ置き換えます。これらではゼロアテンションを表現できるため、捨て先が不要です。
アテンションの希釈
現象
シーケンス長 \(n\) が増えると、各クエリはより多くのキーにアテンション予算を分配しなければなりません。トークンあたりの平均アテンション重みは \(O(1/n)\) で減少し、本当に関連する少数の位置へモデルが集中することが次第に難しくなります。これは アテンションの希釈 または アテンションの拡散 と呼ばれる問題です (N. F. Liu et al. 2024a)。
「中間で失われる」効果
Liuら (N. F. Liu et al. 2024a) は、LLMの検索曲線がU字型になることを示しました。長い文脈の 先頭 または 末尾 に置かれた情報は確実に検索されますが、中間 の情報はしばしば無視されます。これは、RoPE/ALiBiの位置バイアスとアテンション希釈が重なった直接的な結果です。
なぜ起こるのか
-
Softmaxの飽和 :キーが多いとsoftmax温度が実質的に低下し、分布がより一様になります(エントロピーが高くなる)。
-
位置による減衰 :RoPEの相対位置エンコーディングは距離に応じた自然な減衰を生み、先頭と末尾の両方から遠い中間位置へのアテンションを抑えます。
-
学習分布 :短いシーケンスで学習したモデルは、直近の文脈に偏ったアテンションパターンを身につけます。
軽減策
-
明示的な検索 :関連する文脈をプロンプトの先頭または末尾に置き、中間位置に頼らないようRAGを使う。
-
長文脈学習 :重要情報の位置を変えた長文書で学習する (Yao Fu et al. 2024)。
-
階層的アテンション :Mamba (Gu and Dao 2024) やRWKVのように、\(O(n^2)\) のアテンションボトルネックを完全に避けるアーキテクチャを使う。
-
ランドマークトークン :アテンションの「道しるべ」となる、検索可能なマーカーを文脈に挿入する。
-
温度スケーリング :一部の実装では、長いシーケンスの希釈に対抗するためアテンションロジットを \(\log n\) 倍にスケールする。
その他のアテンション現象
| パターン | 説明 | 含意 |
|---|---|---|
| アテンションヘッドの特化 | ヘッドごとに異なる役割を学習する:構文ヘッド、共参照ヘッド、位置ヘッド (Voita et al. 2019) | すべてのヘッドが同じだけ重要ではなく、多くは刈り込み可能 |
| 誘導ヘッド | [A][B]...[A] \(\to\) [B] のコピーを実装するヘッド (Olsson et al. 2022) | 文脈内学習に重要。2層以上のモデルで出現する |
| アテンション崩壊 | 深いネットワークではアテンション分布が収束し得る(すべてのヘッドが同じ位置に注意を向ける) | 表現力を損ない、アテンション多様性損失で対処する |
| 検索ヘッド | 特定のヘッドが文脈から事実情報を検索することに特化する (Zhengbao Wu et al. 2024) | 特定のヘッドを刈り込むとハルシネーションが急増する理由を説明する |
大規模Transformerで観測される追加のアテンションパターン。
解釈可能性のためのアテンション可視化
アテンション重みはモデルの推論を覗く窓になりますが、注意深く解釈しなければなりません。
アテンションの可視化手法
生のアテンションマップ
最も単純な方法は、各ヘッドとレイヤーについて、\(n \times n\) のアテンション行列 \(A = \text{softmax}(QK^\top/\sqrt{d})\) をヒートマップとして描画することです。BertViz (Vig 2019) のようなツールは、インタラクティブなマルチヘッド可視化を描画します。
アテンションロールアウト
単一レイヤーの生アテンションだけを見ると誤解を招きます。情報は すべて のレイヤーを通る残差接続を流れるためです。AbnarとZuidema (Abnar and Zuidema 2020) は アテンションロールアウト を提案しました。レイヤー間でアテンション行列を掛け合わせ、入力から出力までの総情報流を近似します。
\[ R^{(l)} = A^{(l)} \cdot R^{(l-1)}, \quad R^{(0)} = I \]
ここで \(A^{(l)}\) はレイヤー \(l\) の(ヘッド間で平均した)アテンション行列で、残差接続を含めるように調整されています:\(A^{(l)} = 0.5 \cdot A^{(l)}_{\text{raw}} + 0.5 \cdot I\)。
勾配重み付きアテンション
アテンション重みと勾配情報を組み合わせ、注意を向けたトークンのうち、実際に出力へ 影響を与える ものを特定します (Barkan et al. 2021)。
\[ \text{Relevance}(i) = \alpha_i \cdot \left|\frac{\partial y}{\partial h_i}\right| \]
これは、高いアテンション \(\neq\) 高い影響力とは限らないという批判に対処します(高いアテンションを受けても、ほぼゼロ重みの経路で処理されるトークンがあり得ます)。
Warning
アテンションは説明ではない
JainとWallace (Jain and Wallace 2019) は、アテンション重みが勾配ベースの特徴重要度と相関しないことが多く、敵対的なアテンション分布が同一の出力を生成できることを示しました。アテンション可視化は忠実な説明ではなく、仮説生成器 として使います。因果的な帰属には、勾配ベースの手法、プロービング、機械論的解釈可能性を優先します。
スパースオートエンコーダー(SAE)による機械論的解釈可能性
解釈可能性の問題
TransformerのMLPや残差ストリームの個々のニューロンは、通常 多義的 です。1つのニューロンが、互いに無関係な複数の概念(例:「青色」かつ「学術引用」かつ単語「the」)に反応します。そのため、ニューロンレベルの直接的な解釈は信頼できません。
スパースオートエンコーダー
Cunninghamら (Cunningham et al. 2024) とBrickenら (Bricken et al. 2023) は、モデルの活性値でスパースオートエンコーダー(SAE)を学習すると、多義的な表現を 単義的特徴 に分解できることを示しました。各特徴は単一の概念に対応する、解釈可能な方向です。
\[ h = W_{\text{dec}} \cdot \text{ReLU}(W_{\text{enc}} \cdot x + b_{\text{enc}}) + b_{\text{dec}} \]
ここで \(W_{\text{enc}} \in \mathbb{R}^{m \times d}\)、\(m \gg d\)(過完備基底)であり、ReLUとスパース性ペナルティにより、入力ごとに少数の特徴だけが活性化します。
SAEの解釈可能性から得られた主な知見
-
特徴は 単義的 である。各特徴が、人間に解釈可能な単一の概念(「Pythonのコード」「ゴールデンゲートブリッジへの言及」「一人称の語り」)を符号化する (Bricken et al. 2023)。
-
特徴は 操縦可能 である。特徴の活性値を高・低に固定すると、モデルの挙動を直接制御できる(例:「ゴールデンゲートブリッジ」特徴を強制的にオンにすると、モデルはすべての応答でそれに言及する) (Templeton et al. 2024)。
-
特徴は合成できる。単純な特徴の組み合わせから複雑な挙動が現れる。
-
SAEはスケールする。Templetonら (Templeton et al. 2024) はClaude 3 Sonnet上で最大34M特徴のSAEを学習し、安全性に関わる概念(欺瞞、迎合、危険な要求)について解釈可能な特徴を見つけた。
Important
SAEの学習レシピ
大規模コーパスから、特定のモデルレイヤーの活性値を収集する。
隠れ層に \(L_1\) ペナルティを加えたスパースオートエンコーダーを学習する:\(\mathcal{L} = \\vert x - \hat{x}\\vert _2^2 + \lambda \\vert z\\vert _1\)。
学習されたエンコーダ方向(\(W_{\text{enc}}\) の行)が候補特徴になる。
検証する:各特徴について最大活性化例を見つけ、意味的一貫性を確認する。
必要に応じて、特徴の吸収 と 死んだ特徴 を測定し、SAEの品質を評価する。
自然言語オートエンコーダー(Anthropic、2026年)
SAEは活性値を解釈可能な ベクトル に分解しますが、その特徴を理解するには最大活性化例を人間が調べる必要があります。Anthropicの自然言語オートエンコーダー(NLAE) (Anthropic 2026) は根本的に異なるアプローチを取ります。スパースなボトルネックを 自然言語の説明 に置き換え、解釈可能性を自動化します。
NLAEの仕組み
-
エンコーダ :言語モデルが隠れ活性値(または入力テキスト)を読み、活性化した概念の自然言語による説明を生成する。例:「このテキストはフランス料理について述べ、形式的な学術調の文体を使っている。」
-
デコーダ :別の言語モデルが自然言語の説明を読み、元の活性値を再構成する(または次のトークンを予測する)。
-
学習 :エンコーダとデコーダを再構成損失が最小になるようエンドツーエンドで学習する。ボトルネックはスパースベクトルではなく、可変長の自然言語文字列になる。
SAEに対する利点
-
自己解釈的 :特徴が 文字どおり 自然言語なので、手作業のラベル付けが不要。
-
合成的 :SAEの特徴が単一方向として表せない複雑な関係概念(「事実の主張に対する皮肉な応答」)を表現できる。
-
階層的 :同じ表現で、細粒度(単語レベル)と粗粒度(文書レベル)の性質を捉えられる。
-
監査可能 :ボトルネックの説明が人間に読めるため、モデルが存在すると「考えている」情報を直接調べられる。
制限
NLAEは言語モデルをループ内に導入するため計算コストが高く、他のモデル生成説明と同じ忠実性の懸念を受ける可能性があります。また、SAEが活性値の大きさとして自然に扱えるサブシンボリックな特徴(幾何パターン、正確な数値)を簡単には表現できません。
Tip
解釈可能性スタック
解釈可能性ツールを階層として考えます。
アテンションマップ :「モデルは何を見ているか?」(最も安価で、最も忠実性が低い)
プロービング分類器 :「このレイヤーにはどんな情報が符号化されているか?」
スパースオートエンコーダー :「どの単義的特徴が活性化しているか?」(スケール可能だが、人間によるラベル付けが必要)
自然言語オートエンコーダー :「モデルは何が起こっていると考えているか?」(自己解釈的だが高コスト)
因果トレーシング/パッチング :「どの構成要素が実際にこの出力を引き起こしたか?」(最も忠実で、最も高コスト)
各レベルは、説明のコスト、スケーラビリティ、忠実性の間でトレードオフを持ちます。
予測ヘッド:Transformerが出力するもの
Transformer本体は各位置について文脈化された隠れ状態 \(\mathbf{h}_t \in \mathbb{R}^d\) を生成します。これらの隠れ状態を どう使うか、つまり 予測ヘッド がタスクを定義します。同じTransformerバックボーンでも、ヘッドを交換するだけでまったく異なる目的に使えます。
言語モデリングヘッド(事前学習)
標準的なLMヘッドは、最後の隠れ状態を語彙ロジットへ射影し、次のトークンに対するクロスエントロピー損失で学習します。
\[ P(x_{t+1} | x_{\leq t}) = \text{softmax}(\mathbf{W}_{\text{head}} \cdot \mathbf{h}_t + \mathbf{b}) \]
ここで \(\mathbf{W}_{\text{head}} \in \mathbb{R}^{\vert \mathcal{V}\vert \times d}\) です(埋め込み行列と共有することが多い:\(\mathbf{W}_{\text{head}} = \mathbf{E}^T\))。
Important
LMヘッドの性質
学習目的 :因果言語モデリング(すべての位置で次のトークンを予測する)
損失 :\(\mathcal{L}_{\text{LM}} = -\frac{1}{T}\sum_{t=1}^{T} \log P(x_t \vert x_{<t})\)
ラベル :すべてのトークンが入力(右にシフト)とターゲット(左にシフト)の両方になる
使用段階 :大規模コーパス(数兆トークン)での事前学習
重要な洞察 :モデルは次トークン予測の副産物として、一般的な言語理解を学習する
条件付き生成ヘッド(SFT/指示追従)
教師ありファインチューニング(SFT)では、アーキテクチャはLMヘッドと 同一 です。語彙ロジットへの同じ線形射影を使います。違いは、どこに対して損失を計算するか だけです。
\[ \mathcal{L}_{\text{SFT}} = -\frac{1}{|y|}\sum_{t=1}^{|y|} \log P(y_t | x_{\text{prompt}}, y_{<t}) \]
Important
条件付きヘッドとLMヘッドの主な違い
損失マスキング :プロンプト/指示ではなく、応答 トークンにだけ損失を計算する。プロンプトは文脈を与えるが、勾配シグナルは与えない。
条件付け :モデルは特定の指示形式(システムプロンプト、ユーザークエリ、ツール呼び出し)を 条件として 応答を生成するよう学習する。
形式トークン :特殊トークン(
<|user|>、<|assistant|>)が構造化出力を生成するようモデルを導く。使用段階 :選別した指示・応答ペアでのSFT、およびRLの方策生成(行動/応答を生成する方策ヘッド)。
Tip
同じヘッド、異なる学習シグナル
LMヘッドとSFTヘッドはアーキテクチャ的に同一です(同じ \(\mathbf{W}_{\text{head}}\))。違いは、SFT中にプロンプトトークンの損失をマスクすることだけです。この小さな変更が、一般的なテキスト予測器を指示追従アシスタントへ変えます。ヘッドは条件付けされた文脈に基づき、異なる生成モードを「活性化」することを学習します。
価値ヘッド(RLの回帰)
強化学習(PPO、GRPO)では、状態が どれほど良いか を推定する必要があります。そのためには語彙ロジットではなくスカラー出力が必要です。 価値ヘッド はLM射影を単純な回帰層に置き換えます。
\[ V(s_t) = \mathbf{w}_{\text{value}}^T \cdot \mathbf{h}_t + b \in \mathbb{R} \]
ここで \(\mathbf{w}_{\text{value}} \in \mathbb{R}^d\)、\(b \in \mathbb{R}\) です。
Important
価値ヘッドの性質
出力 :単一スカラー(この状態から期待される累積報酬)
損失 :予測リターンと実際のリターンのMSE:\(\mathcal{L}_V = \frac{1}{T}\sum_t (V(s_t) - R_t)^2\)
アーキテクチャ :線形層 \(\mathbb{R}^d \to \mathbb{R}^1\)(小さなMLP:\(d \to 256 \to 1\) を使う場合もある)
バックボーン共有 :方策とTransformer本体を共有する(別の価値ヘッドを持つ)ことが多いが、完全に別のクリティックネットワークを使う場合もある
使用段階 :PPOのアドバンテージ推定(GAE)、報酬モデルのスコアリング
ヘッド選択のまとめ
| ヘッド | 出力 | 損失 | 段階 | 目的 |
|---|---|---|---|---|
| LMヘッド | \(\mathbb{R}^{\vert \mathcal{V}\vert }\) | クロスエントロピー(全トークン) | 事前学習 | 生テキストから言語を学ぶ |
| 条件付きヘッド | \(\mathbb{R}^{\vert \mathcal{V}\vert }\) | クロスエントロピー(応答のみ) | SFT | 指示に従うことを学ぶ |
| 価値ヘッド | \(\mathbb{R}^1\) | MSE | RL(PPO) | アドバンテージのため状態価値を推定 |
| 報酬ヘッド | \(\mathbb{R}^1\) | ペアワイズランキング | RM学習 | 応答品質をスコア化 |
本稿全体で使う予測ヘッドと、その学習コンテキスト。
Warning
ヘッドの初期化が重要
事前学習済みLMに価値ヘッドを追加するときは、ゼロ付近(小さなランダム重み)に初期化します。大きな値で初期化すると、初期価値推定が大きく外れ、巨大なアドバンテージと不安定なPPO更新を引き起こします。一般的には最終線形層を \(\mathcal{N}(0, 1/\sqrt{d})\) または単純なゼロで初期化します。
HuggingFaceでの実装
from transformers import (
AutoModelForCausalLM, # LM head (pretraining + SFT)
AutoModelForSequenceClassification, # Reward head
AutoTokenizer,
)
from trl import AutoModelForCausalLMWithValueHead # Value head (PPO)
import torch
model_name = "meta-llama/Llama-3.1-8B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(model_name)
# === 1. LM Head (Pretraining / SFT) ===
# The default CausalLM model -- projects hidden states to vocab logits
lm_model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.bfloat16,
device_map="auto",
)
# lm_model.lm_head: Linear(hidden_size -> vocab_size)
# Output: logits of shape (batch, seq_len, vocab_size)
inputs = tokenizer("The capital of France is", return_tensors="pt")
outputs = lm_model(**inputs)
next_token_logits = outputs.logits[:, -1, :] # (batch, vocab_size)
probs = torch.softmax(next_token_logits, dim=-1)
# === 2. Conditional Head (SFT) ===
# Architecturally identical to LM head -- difference is in loss masking
# During SFT, we only compute loss on response tokens:
messages = [
{"role": "user", "content": "What is 2+2?"},
{"role": "assistant", "content": "4"},
]
formatted = tokenizer.apply_chat_template(messages, return_tensors="pt")
labels = formatted.clone()
# Mask prompt tokens (set to -100 so cross-entropy ignores them)
prompt_len = len(tokenizer.apply_chat_template(messages[:1]))
labels[:, :prompt_len] = -100
loss = lm_model(input_ids=formatted, labels=labels).loss
# === 3. Value Head (PPO Critic) ===
# Adds a Linear(hidden_size -> 1) on top of the LM backbone
value_model = AutoModelForCausalLMWithValueHead.from_pretrained(
model_name,
torch_dtype=torch.bfloat16,
device_map="auto",
)
# value_model.v_head: Linear(hidden_size -> 1)
# Returns both LM logits AND per-token value estimates
inputs = tokenizer("Explain quantum computing", return_tensors="pt")
lm_logits, loss, values = value_model(
**inputs, return_dict=False
)
# values shape: (batch, seq_len, 1) -- scalar estimate per token
# === 4. Reward Head (Reward Model) ===
# Classification head: Linear(hidden_size -> 1) on last token
reward_model = AutoModelForSequenceClassification.from_pretrained(
model_name,
num_labels=1, # single scalar output
torch_dtype=torch.bfloat16,
device_map="auto",
)
# Scores entire sequence by pooling the last token's hidden state
inputs = tokenizer("Good response here", return_tensors="pt")
reward_score = reward_model(**inputs).logits # shape: (batch, 1)
Tip
重みの共有:LMヘッド=埋め込み行列の転置
現代のLLMの大半は、LMヘッドの重みを入力埋め込み行列と共有する:
lm_head.weight = model.embed_tokens.weight。つまりLMヘッドは独立に学習される層ではなく、埋め込みテーブルを再利用する。利点は、パラメータが少ない(\(\vert \mathcal{V}\vert \times d\)を節約)、一般化がよい、埋め込み空間の幾何構造がトークン確率を直接決めることである。HuggingFaceでは、model.lm_head.weight is model.model.embed_tokens.weightがほとんどのモデルでTrueを返すことで確認できる。
LLM学習の最適化理論
大規模言語モデルの学習とは、損失関数 \(\mathcal{L}(\theta)\)(通常は次トークンの負の対数尤度)を最小化するパラメータ \(\theta\)(数十億の重み)を見つけることです。これは非常に高次元の空間での最適化問題であり、この空間を探索するアルゴリズムによって、学習が成功するか、発散するか、停滞するかが決まります。
勾配降下法:基礎
勾配とは何か?
勾配 \(\nabla_\theta \mathcal{L}\) は、損失が 最も急に増加する 方向を指すベクトルです。各成分 \(\frac{\partial \mathcal{L}}{\partial \theta_i}\) は、パラメータ \(\theta_i\) を少し増やしたときに損失がどれだけ変わるかを示します。損失を 減らす には、反対方向へ進みます。
\[ \theta_{t+1} = \theta_t - \eta \nabla_\theta \mathcal{L}(\theta_t) \]
ここで \(\eta > 0\) はステップ幅である 学習率 です。これが 勾配降下法 です (Rumelhart et al. 1986)。
完全な勾配降下法が実用的でない理由
厳密な勾配を計算するには、学習データ全体(LLMでは数兆トークン)で損失を評価する必要があります。これは計算量が膨大で、勾配の1ステップだけで全データを1周しなければなりません。
確率的勾配降下法(SGD)
解決策は、データの小さなランダム部分集合( ミニバッチ )から勾配を推定することです (Robbins and Monro 1951)。
\[ \nabla_\theta \mathcal{L}(\theta) \approx \frac{1}{B}\sum_{i=1}^{B} \nabla_\theta \ell(\theta; x_i) \]
ここで \(B\) はバッチサイズです(LLMでは通常1K〜4Mトークン)。ミニバッチ勾配は、ノイズを含むが不偏な 真の勾配の推定値です。
Important
ミニバッチSGDが機能する理由
計算効率 :各ステップのコストは \(O(N_{\text{total}})\) ではなく \(O(B)\)。\(B = 4096\) トークン、総計15Tトークンなら、1ステップは \(\sim\) 40億\(\times\)安くなる。
正則化としてのノイズ :確率的ノイズが鋭い局所最小値からの脱出を助け、より汎化する平坦な領域を見つける。
GPU利用率 :ミニバッチはGPUの並列性を飽和させるのに十分大きい(行列積がメモリ律速ではなく計算律速になる)。
収束 :理論上は \(O(1/\sqrt{T})\) の速度で局所最小値へ収束する(厳密なGDの \(O(1/T)\) より遅いが、各ステップは数百万倍安い)。
SGDから適応的手法へ
モメンタム付きSGDは視覚モデル(CNN)ではうまく機能しますが、LLMの学習には 適応的オプティマイザー 、つまりパラメータごとの学習率を維持するアルゴリズムが必要です。
Vanilla SGDがLLMで失敗する理由
確率的勾配降下法は、次のように重みを更新する。
\[ \theta_{t+1} = \theta_t - \eta \nabla_\theta \mathcal{L}(\theta_t) \]
Warning
LLMにおけるSGDの問題
レイヤーごとに異なる勾配スケール :Transformerの前段レイヤーは後段より勾配がはるかに小さい(勾配消失)。単一の学習率 \(\eta\) は、あるパラメータには大きすぎ、別のパラメータには小さすぎる。
スパースな勾配 :埋め込み層は現在のバッチのトークンに対してだけ勾配を受ける。大部分の埋め込み行は勾配ゼロであり、モメンタム付きSGDはゼロ勾配の行にモメンタムを浪費する。
鞍点 :高次元の損失地形には多くの鞍点がある。SGDは停滞し得るが、適応的手法はより速く脱出する。
学習率への感度 :SGDには慎重な調整が必要で、\(\eta\) を2\(\times\)変えるだけで発散する可能性がある。
Adam — 適応的モーメント推定
Adam (Kingma and Ba 2015) は、パラメータごとに1次モーメント(勾配の平均)と2次モーメント(勾配の非中心化分散)の推定値を維持します。
Important
Adamの更新式
勾配 \(g_t = \nabla_\theta \mathcal{L}(\theta_t)\) とハイパーパラメータ \(\beta_1, \beta_2, \epsilon, \eta\) に対して、
ステップ1 — 1次モーメントのバイアス付き推定値を更新 \[ m_t = \beta_1 m_{t-1} + (1 - \beta_1) g_t \]
ステップ2 — 2次モーメントのバイアス付き推定値を更新 \[ v_t = \beta_2 v_{t-1} + (1 - \beta_2) g_t^2 \]
ステップ3 — バイアス補正 \[ \hat{m}_t = \frac{m_t}{1 - \beta_1^t}, \qquad \hat{v}_t = \frac{v_t}{1 - \beta_2^t} \]
ステップ4 — パラメータ更新 \[ \theta_{t+1} = \theta_t - \eta \cdot \frac{\hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon} \]
典型的な値 :\(\beta_1 = 0.9\)、\(\beta_2 = 0.95\) または \(0.999\)、\(\epsilon = 10^{-8}\)、\(\eta = 10^{-4}\)〜\(10^{-5}\)。
Tip
各項の働き
\(m_t\)( モメンタム ):勾配の指数移動平均。ノイズの多い勾配推定を平滑化する。\(\beta_1 = 0.9\) なら、現在の勾配が10%、履歴が90%寄与する。
\(v_t\)( 適応的学習率 ):二乗勾配のEMA。勾配が一貫して大きいパラメータは、より小さい実効学習率(\(\eta / \sqrt{v_t}\))を得る。勾配が小さいパラメータは、より大きい実効学習率を得る。これがレイヤーごとの異なる勾配スケールを扱う鍵である。
\(\hat{m}_t, \hat{v}_t\)( バイアス補正 ):\(t=1\) では \(m_1 = (1-\beta_1)g_1\) が真の平均よりかなり小さい。\((1-\beta_1^t)\) で割ることで、この初期化バイアスを補正する。これがないと初期ステップが小さすぎる。
\(\epsilon\)( 数値安定性 ):ゼロ除算を防ぐ。また実効学習率の下限としても働く。
AdamW — 分離された重み減衰
AdamW (Loshchilov and Hutter 2019) は、重み減衰と適応的オプティマイザーの相互作用に関する、微妙だが重要な問題を修正します。
Important
AdamでL2正則化 $\neq$ 重み減衰となる理由
L2正則化では損失が\(\mathcal{L} + \frac{\lambda}{2}\\vert \theta\\vert ^2\)となり、勾配は\(g_t + \lambda \theta_t\)になる。Adamでは、この正則化勾配が適応係数\(1/\sqrt{\hat{v}_t}\)でスケールされる。 \[ \theta_{t+1} = \theta_t - \eta \cdot \frac{\hat{m}_t + \lambda \theta_t}{\sqrt{\hat{v}_t} + \epsilon} \] \(v_t\)が大きい(勾配分散が大きい)パラメータほど正則化が弱くなる。これは望ましくない。重み減衰は一様であるべきだ。
Important
AdamW — 分離された重み減衰
AdamW(LoshchilovとHutter、2017)は、適応的スケーリングの外側で、重み減衰をパラメータへ 直接 適用します。 \[ \theta_{t+1} = \theta_t - \eta \cdot \frac{\hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon}
- \eta \lambda \theta_t \] 重み減衰項 \(\eta \lambda \theta_t\) は \(\sqrt{\hat{v}_t}\) で割られません。そのため、勾配履歴に関係なくすべてのパラメータに一様な正則化がかかります。
典型値 :LLM学習では \(\lambda = 0.1\)。
Warning
LLMでは常にAdamWを使い、通常のAdamは使わない
AdamとAdamWの違いは微妙ですが重要です。Adam+L2では、実効重み減衰が勾配分散の小さいパラメータ(バイアスやLayerNormパラメータなど)には強く、勾配分散の大きいパラメータ(アテンション重みなど)には弱くなります。AdamWなら意図した一様な正則化になります。多くのフレームワークはAdamWをデフォルトにしていますが、オプティマイザーのクラスを確認してください。
学習率 — 最も重要なハイパーパラメータ
Important
学習段階ごとの典型的な学習率
段階 典型的な学習率 注記 事前学習(ゼロから) \(1\text{e-}4\)〜\(3\text{e-}4\) 大規模モデル、大規模バッチ 継続事前学習 \(1\text{e-}5\)〜\(1\text{e-}4\) 知識を保つため小さい学習率 SFT(教師ありファインチューニング) \(1\text{e-}5\)〜\(2\text{e-}5\) 標準的な範囲 LoRAファインチューニング \(1\text{e-}4\)〜\(3\text{e-}4\) アダプター重みに対して高い学習率 RLの学習率(PPO、DPO、GRPO)については、§8.15を参照。
学習率ウォームアップ
Important
ウォームアップが必要な理由
学習開始時、\(v_t\)(2次モーメント推定値)はゼロに初期化される。バイアス補正後は\(\hat{v}_t = v_t / (1 - \beta_2^t)\)である。\(\beta_2 = 0.999\)の\(t=1\)では、\(\hat{v}_1 = v_1 / (1 - 0.999) = 1000 v_1\)となる。これは実効学習率が\(\eta / \sqrt{1000 v_1}\)、つまり意図よりはるかに小さくなることを意味する。
ただし、最初の勾配が異常に大きい場合(初期化時によくある)、2次モーメント推定値がこの外れ値に支配され、初期ステップが不規則になります。ウォームアップは非常に小さい学習率から始めて徐々に増やし、\(v_t\) が信頼できる推定値を蓄積する時間を与えることで、これを緩和します。
-
線形ウォームアップ :\(\eta_t = \eta_{\max} \times t / T_{\text{warmup}}\)
-
典型的なウォームアップ期間 :事前学習では全ステップの1〜5%、ファインチューニングでは3〜10%(短い実行ほど比例して長いウォームアップが必要)
-
SFTの場合 :50〜200ウォームアップステップが典型的
学習率スケジュール
(a) 一定
最も単純なスケジュール。学習率を減衰させすぎたくない短いファインチューニングに適しています。リスクは、アニーリングがないためモデルが最も鋭い最小値へ収束しない可能性があることです。
(b) コサイン減衰
\[ \eta_t = \eta_{\min} + \frac{1}{2}(\eta_{\max} - \eta_{\min}) \left(1 + \cos!\left(\frac{t - T_{\text{warmup}}}{T - T_{\text{warmup}}} \pi\right)\right) \]
事前学習とSFTの標準です。滑らかな減衰により、学習率の急変を避けます。\(\eta_{\min}\) は通常 \(\eta_{\max} / 10\) です。
(c) 線形減衰
コサインより単純で、実証結果は同程度です。任意のステップで予測可能な学習率が必要な場合に好まれます。
(d) WSD — Warmup-Stable-Decay
大規模事前学習の新しい標準です (S. Hu et al. 2024; Grattafiori et al. 2024)。3つの段階があります。
-
ウォームアップ :\(\eta_{\max}\) まで線形に増加(ステップの1〜5%)
-
安定 :学習の大部分で \(\eta_{\max}\) を一定に保つ
-
減衰 :\(\eta_{\min}\) まで高速なコサインまたは線形減衰(最後の10〜20%)
主な利点は、安定段階のどの時点でもチェックポイントを保存して学習を続けられることです。減衰段階は任意の実行の最後に適用できます。
(e) 再起動付きコサイン(SGDR)
周期的な再起動で学習率を \(\eta_{\max}\) に戻します。局所最小値からの脱出に役立つことがあります。LLMではあまり一般的でなく、小規模モデルにより有用です。
勾配クリッピング
Important
勾配クリッピング
勾配クリッピングは、勾配のグローバルノルムがしきい値を超えたときに勾配を再スケールします。 \[ g_t \leftarrow g_t \cdot \min!\left(1,; \frac{\tau}{|g_t|_2}\right) \] ここで\(\tau\)は
max_grad_norm(通常1.0)である。
Tip
勾配クリッピングと学習率削減の比較
勾配クリッピングと学習率の削減は、どちらもパラメータ更新の大きさを制限します。違いは、クリッピングが勾配の 方向 を保つ(大きさだけをスケールする)のに対し、学習率を下げるとすべての更新を一様にスケールすることです。クリッピングは、通常の学習ステップを遅くせずに、ときどき現れる大きな勾配へ対処するのに適しています。
まとめ:HuggingFaceのオプティマイザー設定
次のスニペットは、この節の概念——分離された重み減衰を持つAdamW(§1.6.6)、線形ウォームアップ付きコサイン学習率スケジュール(§1.6.7)、勾配クリッピング(§1.6.8)——を、HuggingFaceのtransformersライブラリで実際に組み合わせる方法を示す。
from transformers import TrainingArguments, Trainer
from transformers import get_cosine_schedule_with_warmup
import torch
# --- Option 1: Using TrainingArguments (recommended) ---
training_args = TrainingArguments(
output_dir="./checkpoints",
# AdamW optimizer (decoupled weight decay, S1.6.6)
optim="adamw_torch",
learning_rate=2e-5, # peak LR after warmup
adam_beta1=0.9, # first moment decay
adam_beta2=0.999, # second moment decay
adam_epsilon=1e-8, # numerical stability
weight_decay=0.01, # decoupled L2 penalty
# Learning rate schedule (S1.6.7)
lr_scheduler_type="cosine", # cosine decay to 0
warmup_ratio=0.1, # 10% of steps = linear warmup
# Gradient clipping (S1.6.8)
max_grad_norm=1.0, # clip by global L2 norm
# Mixed precision (S1.6.9)
bf16=True, # use BFloat16 on Ampere+ GPUs
# Training duration
num_train_epochs=3,
per_device_train_batch_size=8,
gradient_accumulation_steps=4, # effective batch = 8*4 = 32
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=dataset,
)
trainer.train()
# --- Option 2: Manual control (for custom training loops) ---
from torch.optim import AdamW
# Separate weight-decay groups (don't regularize biases/norms)
no_decay = ["bias", "LayerNorm.weight", "layernorm.weight"]
param_groups = [
{
"params": [p for n, p in model.named_parameters()
if not any(nd in n for nd in no_decay)],
"weight_decay": 0.01,
},
{
"params": [p for n, p in model.named_parameters()
if any(nd in n for nd in no_decay)],
"weight_decay": 0.0,
},
]
optimizer = AdamW(param_groups, lr=2e-5, betas=(0.9, 0.999))
# Cosine schedule with linear warmup
total_steps = len(train_dataloader) * num_epochs
warmup_steps = int(0.1 * total_steps)
scheduler = get_cosine_schedule_with_warmup(
optimizer,
num_warmup_steps=warmup_steps,
num_training_steps=total_steps,
)
# Training loop with gradient clipping
for batch in train_dataloader:
outputs = model(**batch)
loss = outputs.loss
loss.backward()
# Clip gradients before optimizer step
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
optimizer.step()
scheduler.step()
optimizer.zero_grad()
Important
実践的なヒント
重み減衰から除外 :バイアス項とLayerNorm重みは正則化しない。パラメータが少なく、正則化すると性能が低下する (Loshchilov and Hutter 2019)。
ウォームアップ比率 :全ステップの5〜10%が標準。高い学習率でウォームアップが少なすぎると初期学習が不安定になる。
勾配蓄積 :限られたGPUメモリで大きなバッチをシミュレートする。クリッピングは 蓄積された 勾配に適用する。
BF16とFP16の比較 :Ampere以降のGPUでは
bf16=Trueを優先する(広いダイナミックレンジにより損失スケーリングを避けられる)。古いハードウェアではfp16=Trueへフォールバックする。
混合精度学習
Important
BF16とFP16の比較
形式 指数ビット 仮数ビット ダイナミックレンジ FP32 8 23 \(\sim 10^{-38}\)〜\(10^{38}\) BF16 8 7 FP32と同じ(指数が同じ) FP16 5 10 \(\sim 6 \times 10^{-5}\)〜\(65504\)
Tip
FP16よりBF16:LLM学習で精度より範囲が重要な理由
BF16はFP32と同じ指数範囲を持つため、仮数の精度は低いものの同じ値の範囲を表現できます。FP16のダイナミックレンジははるかに小さく、65504を超える勾配や活性値はオーバーフローします(NaN/Inf)。そのためFP16学習では 損失スケーリング(勾配をFP16の範囲に保つため損失を大きな定数倍すること)が必要ですが、BF16学習では通常不要です。A100とH100はBF16をネイティブサポートするため、FP16を使う特別な理由がない限りBF16を使います。
損失スケーリング(FP16のみ)
-
損失にスケール係数\(S\)を掛ける(例:\(S = 2^{15}\))。
-
FP16で勾配を計算する(\(S\)倍にスケール済み)。
-
オプティマイザーステップの前に、勾配を\(S\)で割る。
-
オーバーフロー(NaN/Inf)を確認し、見つかったらステップをスキップして\(S\)を下げる。
-
\(N\)ステップ連続でオーバーフローがなければ、\(S\)を増やす。
FP32マスター重み
混合精度学習では、重みをFP32(マスターコピー)で保存し、順伝播/逆伝播ではBF16/FP16へキャストする。オプティマイザーステップはFP32で行う。これは次の理由で重要である。
-
小さな勾配更新(\(\Delta\theta \ll \theta\))はBF16の精度では失われる(仮数7ビット、相対精度\(\approx\)0.8%)。
-
FP32マスター重みにより、多数のステップにわたる小さな更新を正確に蓄積できる。
-
メモリコスト:重みの保存量が2\(\times\)になる(FP32+BF16コピー)。
Warning
FP32マスター重みが重要な場面
FP32マスター重みは次の場面で特に重要である。
長い学習実行(多数の小さな勾配ステップが蓄積する)
小さな学習率(重みの大きさに比べて更新が極めて小さい)
大きな学習率を使う短いSFTでは、BF16だけの学習(FP32マスター重みなし)でもうまく動くことが多く、メモリを節約できる。RL学習ではFP32マスター重みが不可欠である。§8.15を参照。
実践的な混合精度:HuggingFace
# === HuggingFace TrainingArguments (simplest approach) ===
from transformers import TrainingArguments
# BF16 on Ampere+ GPUs (A100, H100, RTX 30xx/40xx)
args_bf16 = TrainingArguments(
output_dir="./out",
bf16=True, # BF16 forward/backward; FP32 master weights
bf16_full_eval=True, # also use BF16 during evaluation
# No loss scaling needed -- BF16 has FP32-equivalent range
)
# FP16 on older GPUs (V100, T4, RTX 20xx)
args_fp16 = TrainingArguments(
output_dir="./out",
fp16=True, # FP16 forward/backward
fp16_full_eval=False, # keep eval in FP32 for accuracy
# Loss scaling is automatic via PyTorch GradScaler
)
# === Manual PyTorch AMP (for custom training loops) ===
import torch
# Setup (PyTorch 2.x API)
use_fp16 = not torch.cuda.is_bf16_supported()
scaler = torch.amp.GradScaler("cuda", enabled=use_fp16) # only needed for FP16
optimizer = torch.optim.AdamW(model.parameters(), lr=2e-5)
dtype = torch.float16 if use_fp16 else torch.bfloat16
for batch in train_dataloader:
optimizer.zero_grad()
# Autocast: run forward pass in reduced precision
with torch.autocast("cuda", dtype=dtype):
outputs = model(**batch)
loss = outputs.loss
if use_fp16:
# FP16 path: scale loss to prevent gradient underflow
scaler.scale(loss).backward()
scaler.unscale_(optimizer) # unscale before clipping
torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)
scaler.step(optimizer) # skips step on overflow
scaler.update() # adjust scale factor
else:
# BF16 path: no scaling needed
loss.backward()
torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)
optimizer.step()
scheduler.step()
Tip
コードにおけるBF16とFP16の主な違い
BF16 :
autocast(dtype=torch.bfloat16)でラップするだけでよく、スケーラーは不要。コードが単純で数値的にも安定する。FP16 :勾配のアンダーフローを防ぐため
GradScalerが必要。スケーラーは乗数を動的に調整し、オーバーフロー(NaN)が検出されるとオプティマイザーステップをスキップしてスケールを下げる。勾配クリッピング+FP16 :
clip_grad_norm_の前に必ずscaler.unscale_(optimizer)を呼ぶ。そうしないとスケール済み勾配をクリップしてしまい、しきい値が誤る。メモリ削減 :活性値を16-bitで保存することで活性メモリを%削減する。重みメモリはFP32マスターコピーを保持するかどうかに依存する。
学習段階ごとの実践的なオプティマイザー設定
Important
オプティマイザーハイパーパラメータの参照表
段階 オプティマイザー LR WD ウォームアップ スケジュール 事前学習 AdamW \(3\text{e-}4\) 0.1 2000ステップ WSDまたはコサイン SFT AdamW \(2\text{e-}5\) 0.01 100ステップ コサイン LoRA SFT AdamW \(2\text{e-}4\) 0.01 100ステップ コサイン すべての設定で\(\beta_1{=}0.9\)、\(\beta_2{=}0.95\)、\(\epsilon{=}10^{-8}\)、
max_grad_norm=1.0、BF16を使う。RLの設定については§8.15を参照。
Note
学習不安定性の診断
# Monitor these metrics to diagnose optimizer issues: # 1. Gradient norm -- should be < max_grad_norm most of the time # 2. Loss scale (FP16) -- should be stable, not constantly decreasing # 3. Parameter update norm -- should be << parameter norm import torch def log_optimizer_stats(model, optimizer, step): # Gradient norm (before clipping) total_norm = 0.0 for p in model.parameters(): if p.grad is not None: total_norm += p.grad.data.norm(2).item() ** 2 total_norm = total_norm ** 0.5 # Adam second moment stats (proxy for adaptive LR) v_norms = [] for group in optimizer.param_groups: for p in group['params']: state = optimizer.state[p] if 'exp_avg_sq' in state: v_norms.append(state['exp_avg_sq'].mean().item()) print(f"Step {step}: grad_norm={total_norm:.3f}, " f"mean_v={sum(v_norms)/len(v_norms):.6f}") # Red flags: # grad_norm >> 1.0 repeatedly -> reduce LR or increase warmup # grad_norm == 0.0 -> gradient vanishing or wrong loss # loss_scale decreasing -> FP16 overflow, switch to BF16 # v very small -> Adam not warmed up yet, extend warmup
Tip
学習率は最も重要なハイパーパラメータ
実際には、学習率を正しく設定することが他のどのハイパーパラメータより重要である。LLMファインチューニングの経験則は次のとおり。
上の表の値から始める。
損失が発散する(最初は下がるが、その後増える)なら、LRが高すぎる。
損失が非常にゆっくり下がり早く頭打ちになるなら、LRが低すぎる。
損失が不安定(振動)なら、LRが高すぎるか、ウォームアップが短すぎる。
2番目に重要なハイパーパラメータはバッチサイズである(線形スケーリング則を通じて勾配ノイズと実効LRに影響する)。その他は二次的である。
Flash Attention — アルゴリズムとハードウェアへの対応
Flash Attention (Dao et al. 2022; Dao 2024) は、Transformerそのもの以来、ディープラーニングで最も影響力のあるアルゴリズム上の革新の1つです。アテンションの数学的結果は変えず、まったく同じ出力 を計算しますが、メモリアクセスパターンを再構成します。GPUの限られた高速SRAMに重い処理を担わせ、HBMフットプリントを \(O(n^2)\) から \(O(n)\) に削減し、典型的なワークロードでエンドツーエンドの実時間を2〜4\(\times\)改善します。
標準アテンションのメモリ問題
標準的なスケールド・ドット積アテンションは次のとおりである。
\[ \text{Attention}(Q, K, V) = \text{softmax}!\left(\frac{QK^T}{\sqrt{d_k}}\right) V \]
Important
標準アテンションのメモリ計算量
シーケンス長 \(n\)、ヘッド次元 \(d\) に対して、
\(Q, K, V \in \mathbb{R}^{n \times d}\):メモリ \(O(nd)\)
\(S = QK^T \in \mathbb{R}^{n \times n}\): メモリ \(O(n^2)\) — ボトルネック
\(P = \text{softmax}(S) \in \mathbb{R}^{n \times n}\):さらに \(O(n^2)\)
\(O = PV \in \mathbb{R}^{n \times d}\):\(O(nd)\)
\(n=8192\)、\(d=128\)、BF16では、アテンション行列だけでヘッドあたり \(8192^2 \times 2 \approx 134\) MB です。32ヘッドなら、1レイヤーのアテンションスコアだけで4.3 GBになります。
Tip
$O(n^2)$ が壊滅的な理由
アテンション行列はHBMへ書き込まれ(長いシーケンスではSRAMに収まらない)、softmaxのために読み戻され、さらに \(PV\) 積のために再び読み込まれます。HBMとの往復はどれも低速です。\(n=32768\)(32K文脈)では、アテンション行列はヘッドあたり \(32768^2 \times 2 \approx 2\) GB となり、保存するのは完全に非現実的です。
Flash Attentionの核心 — タイル化とオンラインsoftmax
核心となる洞察は、 完全な \(n \times n\) 行列を一度にメモリへ置く必要はない ということです。オンラインsoftmax のトリックを使えば、出力 \(O\) をブロック単位で計算できます。
オンラインsoftmax
softmaxには数値安定性のためグローバル最大値が必要です。
\[ \text{softmax}(x_i) = \frac{e^{x_i - m}}{\sum_j e^{x_j - m}}, \quad m = \max_j x_j \]
トリックは、新しいブロックを処理しながら最大値と正規化係数を 更新 し、行全体を実体化しないことです。
Important
オンラインsoftmaxの更新則
実行中の状態 \((m_{\text{old}}, \ell_{\text{old}}, O_{\text{old}})\) と新しいスコアブロック \(s_{\text{new}}\) に対して、
\(m_{\text{new}} = \max(m_{\text{old}},; \max(s_{\text{new}}))\)
[ \ell_{\text{new}} = e^{m_{\text{old}} - m_{\text{new}}} \cdot \ell_{\text{old}} + \sum_j e^{s_{\text{new},j} - m_{\text{new}}} ]
[ O_{\text{new}} = \frac{1}{\ell_{\text{new}}} \left( e^{m_{\text{old}} - m_{\text{new}}} \cdot \ell_{\text{old}} \cdot O_{\text{old}} + e^{s_{\text{new}} - m_{\text{new}}} \cdot V_{\text{new}} \right) ]
これはすべてのブロックに対して一度にsoftmaxを計算するのと数学的に等価です。
Flash Attentionアルゴリズム
Note
Flash Attentionのフォワードパス — ブロックタイル化
設定 :SRAMサイズ \(M\)。ブロックサイズは \(B_r = \lceil M / (4d) \rceil\)、\(B_c = \min(\lceil M / (4d) \rceil, d)\)。
\(Q\)を\(T_r = \lceil n / B_r \rceil\)個のブロック\(Q_1, \ldots, Q_{T_r}\)に分割する。
\(K, V\)を\(T_c = \lceil n / B_c \rceil\)個のブロック\(K_1, \ldots, K_{T_c}\)に分割する。
出力\(O \in \mathbb{R}^{n \times d}\)、実行中の最大値\(m \in \mathbb{R}^n\)、実行中の和\(\ell \in \mathbb{R}^n\)を初期化する(すべてHBM上)。
\(j = 1, \ldots, T_c\)について 外側ループ を行う。
\(K_j, V_j\)をHBMからSRAMへ読み込む。
\(i = 1, \ldots, T_r\)について 内側ループ を行う。
\(Q_i, O_i, m_i, \ell_i\)をHBMからSRAMへ読み込む。
\(S_{ij} = Q_i K_j^T / \sqrt{d}\)を計算する(SRAMに留める)。
オンラインsoftmaxの更新を適用し、新しい\(m_i, \ell_i, O_i\)を得る。
\(O_i, m_i, \ell_i\)をHBMへ書き戻す。
\(O\)を返す。
要点 :\(S_{ij}\)(アテンションタイル)はSRAMで計算して破棄します。HBMへ書き込むことはありません。
Important
Flash Attentionの計算量
標準アテンション Flash Attention メモリ(HBM) \(O(n^2)\) \(O(n)\) HBMの読み書き \(O(n^2 d)\) \(O(n^2 d / M)\) FLOPs \(O(n^2 d)\) \(O(n^2 d)\)(同じ) 高速化 1\(\times\) 2〜4\(\times\) フォワードパスの総FLOPsは \(O(n^2 d)\) のままで、標準アテンションと同じです。Flash Attentionは演算量を減らすのではなく、低速なHBMトラフィックを大幅に削ることで高速化します。(後方パスは再計算のため実際には より多くの FLOPsを行いますが、節約したメモリ帯域幅が支配的なので実時間は短くなります。)
Flash Attention 2 — 並列性の改善
Flash Attention 2 (Dao 2024) は3つの主要な改善を行いました。
-
行列積以外のFLOPs削減 :元のFAには内側ループに不要な再スケーリング演算がありました。FA2はこれを最小化するようループを再構成します。A100ではTensor Coreの行列積がスカラー演算を約16\(\times\)上回るため、内側ループで行列積以外の処理が少しあるだけでもレイテンシのボトルネックになります。
-
シーケンス次元の並列性向上 :FA1はバッチとヘッドだけを並列化しました。FA2はクエリのシーケンス次元も並列化し、小さいバッチサイズの長いシーケンスでGPU利用率を高めます。
-
因果マスキングの最適化 :自己回帰(因果)アテンションでは、およそ半分のブロックが完全にマスクされます。FA2はこれらのブロックを完全にスキップし、双方向アテンションに対して因果アテンションを \(\sim\) 2\(\times\)高速化します。
Flash Attention 3 — Hopperアーキテクチャ
Flash Attention 3 (Shah et al. 2024) はH100向けに設計され、Hopper固有の3つの機能を活用します。
-
TMA(Tensor Memory Accelerator) :H100にはHBMとSRAM間の非同期バルクデータ移動専用のハードウェアユニットがあります。FA3はTMAを使い、データ読み込みと計算を重ねてメモリレイテンシを隠します。
-
Warp-specialization :FA3は異なるワープに異なる役割を割り当てます(プロデューサーワープはTMAでデータを読み、コンシューマーワープはMMAを計算)。メモリシステムとTensor Coreを同時に稼働させるソフトウェアパイプライン技法です。
-
FP8サポート :H100はBF16の2\(\times\)のスループットでFP8(E4M3/E5M2)Tensor Core演算をサポートします。FA3は精度維持のためブロックごとの量子化を行うFP8アテンションをサポートします。
FA3はFP16アテンションで H100の理論ピークの最大75% を達成します。FA2は \(\sim\) 35%です。
Flash Attention 4 — Blackwellアーキテクチャ
Flash Attention 4(Zadouri et al. 2026)はNVIDIAのBlackwell GPU(B200/GB200)を対象とする。Tensor Coreのスループットを2.25 PFLOP/s(BF16)へ倍増する一方、行列積以外のユニット(指数演算、共有メモリ帯域)はより遅い割合でしか拡大しない。この非対称なハードウェアスケーリングによりボトルネックが移る。Blackwellでは、アテンションは行列積ではなく、softmaxの指数演算とその周辺の共有メモリトラフィックによって制限される。
FA4は4つの主要な技法でこれに対処する。
-
完全非同期のMMAパイプライン :BlackwellのMMA命令は完全に非同期である(完了時にまだブロックされるHopperのwgmmaとは異なる)。FA4はより大きなタイルサイズにわたってMMA、TMAロード、softmax再スケーリングを重ね合わせるようパイプラインを再設計し、すべてのハードウェアユニットを飽和させる。
-
ソフトウェアによる指数演算エミュレーション :スループットのボトルネックであるハードウェアの
ex2ユニットを呼ぶ代わりに、FA4ははるかに高速なTensor Core上で多項式近似を実行し、\(e^x\)をエミュレートする。指数演算ユニットの停止と、追加の行列積命令を交換する。 -
条件付きsoftmax再スケーリング :標準のFlashAttentionはタイルごとに実行中の\(\max\)を再スケールする。FA4は新しいタイルの最大値が実行中の最大値を超えない場合(実際にはよくある)に再スケーリングを省き、レジスタシャッフルと同期バリアの両方を節約する。
-
Tensor Memory+2-CTA MMAモード(逆伝播) :逆伝播ではBlackwellのTensor Memory(共有メモリより大きいSMごとのスクラッチパッド)と、2つのスレッドブロッククラスタにまたがる\(dQ\)の蓄積を融合する2-CTA協調モードを使い、共有メモリへの往復を半減する。
Important
FA4の実装:CuTe-DSL
FA4は、GPUカーネル向けのPython組み込みドメイン固有言語(CUTLASS 4.xの一部)である CuTe-DSL で書かれた最初のFlashAttentionバージョンである。CuTe-DSLはレジスタ割り当てとパイプラインスケジューリングを完全に制御しながら、C++のCUTLASSテンプレートより20〜30\(\times\)高速にコンパイルできる。これによりカーネル開発の反復時間が大幅に短くなる。
結果
BF16、ヘッド次元128のB200(因果、系列長8K)では、
-
1613 TFLOP/s ——Blackwellのピーク利用率の71%
-
1.3\(\times\) ——cuDNN 9.13(NVIDIA独自の融合カーネル)より高速
-
2.7\(\times\) ——同じハードウェア上のTritonより高速
Tip
ハードウェアとソフトウェアの共進化
FlashAttentionシリーズは、GPU世代ごとにボトルネックが移り、単なる再コンパイルではなく新しいアルゴリズムの発想が必要になるという原則を示します。A80 \(\to\) メモリ帯域幅律速(FA1/FA2:タイル化+再計算)。H100 \(\to\) データ移動律速(FA3:TMA+warp-specialization)。B200 \(\to\) 行列積以外の計算律速(FA4:ソフトウェアによるexpエミュレーション+条件付き再スケーリング)。ハードウェアのボトルネックがどこにあるか を理解することが、効率的なカーネルを書く前提です。
事前学習:ベストプラクティス
事前学習はLLM開発で最も高コストな段階です。数百万GPU時間を消費し、データ、計算、ハイパーパラメータの慎重な調整が必要です。この節では、Llama-3 (Grattafiori et al. 2024)、Chinchilla (Hoffmann et al. 2022)、GPT-4 (OpenAI 2023)から得られる主な教訓をまとめます。
学習目的
現代のDecoder-Only LLMはすべて 因果言語モデリング (CLM)を使います。
\[ \mathcal{L}_\text{CLM} = -\frac{1}{T}\sum_{t=1}^T \log P_\theta(x_t \mid x_{<t}) \]
この単純な目的は、十分なデータと規模があれば、明示的な教師なしに創発的能力(文脈内学習、推論、指示追従)を生みます (Brown et al. 2020)。
データパイプライン
Important
事前学習データのレシピ
規模 :最先端モデルでは1〜15兆トークン(Llama-3:15Tトークン)
ソース :ウェブクロール(80%)、コード(10%)、書籍/論文(5%)、選別データ(5%)
重複除去 :MinHash+完全な部分文字列重複除去により、記憶を減らす (Lee et al. 2022)
品質フィルタリング :パープレキシティベースの分類器、ヒューリスティックフィルタ(長さ、言語ID、有害性)
データ混合 :ドメイン間で温度重み付きサンプリングを行い、推論のためコードと数学を重くする
スケーリング則
Hoffmannら (Hoffmann et al. 2022) は、計算量最適な学習にはモデルサイズ \(N\) とデータサイズ \(D\) のバランスが必要だと示しました:\(N_\text{opt} \propto C^{0.50}\)、\(D_\text{opt} \propto C^{0.50}\)。70Bモデルは \(\sim\) 1.4Tトークンで計算量最適になります。実際には、推論コストが学習トークン数ではなくモデルサイズに比例するため、モデルは 過学習 されます(Chinchilla最適より多くのトークン)。小さく過学習させたモデルの方がデプロイ費用が安くなります。
主要ハイパーパラメータ
| Setting | Llama-3 405B | Llama-3 8B | Qwen-2.5 72B | Mistral 7B |
|---|---|---|---|---|
| Tokens | 15T | 15T | 18T | 8T |
| Batch size (tokens) | 16M | 4M | 4M | 4M |
| Peak LR | \(8\text{e-}5\) | \(3\text{e-}4\) | \(3\text{e-}4\) | \(3\text{e-}4\) |
| Schedule | WSD | WSD | Cosine | Cosine |
| Weight decay | 0.1 | 0.1 | 0.1 | 0.1 |
| Context length | 8192 | 8192 | 4096\(\to\)32K | 8192 |
公開モデルの事前学習ハイパーパラメータ。
よくある失敗モード
Warning
事前学習の落とし穴
損失スパイク :悪いデータバッチや数値不安定性による突然の損失増加。Llama-3ではチェックポイントへロールバックし、問題のバッチをスキップする。
記憶 :モデルが学習データをそのまま再現する。対策は積極的な重複除去と抽出攻撃の監視。
文脈長 :短いシーケンスで学習して長い文脈へデプロイすると失敗する。長文書での継続事前学習とRoPEスケーリングを使う。
教師ありファインチューニング(SFT)
SFTは選別したプロンプト・応答ペアで学習し、事前学習済み言語モデルを指示追従アシスタントへ変換します。これは生の言語モデリングとRLHFの橋渡しです。
SFTの目的
損失はCLMと同じですが、 応答トークン に対してだけ計算します。
\[ \mathcal{L}_\text{SFT} = -\frac{1}{|y|}\sum_{t=1}^{|y|} \log P_\theta(y_t \mid x_\text{prompt}, y_{<t}) \]
プロンプトトークンは文脈を提供しますが、勾配は受けません(ラベルを \(-100\) に設定)。
データ品質:LIMAの原則
Zhouら (C. Zhou et al. 2023) は、注意深く選別した1,000例で、ノイズの多い50K以上の例で学習したモデルに匹敵できることを示しました。主な要件は次のとおりです。
-
多様性 :QA、要約、コード、数学、創作、多ターン対話を網羅する
-
正確性 :すべての応答が事実として正確で、書式も整っている
-
長さのバランス :短い応答(1文)と長い応答(複数段落)を混ぜる
-
デコンタミネーション :評価ベンチマークとの重複を除去する
学習設定
from trl import SFTTrainer, SFTConfig
sft_config = SFTConfig(
output_dir="./sft_output",
max_seq_length=4096,
packing=True, # Pack short examples into full sequences
learning_rate=2e-5,
lr_scheduler_type="cosine",
warmup_ratio=0.1,
weight_decay=0.01,
max_grad_norm=1.0,
num_train_epochs=3,
per_device_train_batch_size=4,
gradient_accumulation_steps=8,
bf16=True,
gradient_checkpointing=True,
)
trainer = SFTTrainer(model=model, args=sft_config,
train_dataset=dataset, processing_class=tokenizer)
trainer.train()
効率的な学習ソリューション
標準的なHuggingFace学習では、かなりの性能が取りこぼされます。いくつかのライブラリはSFTワークロードに、そのまま導入できる効率向上を提供します。
Liger Kernel (Hsu et al. 2024)
LinkedInによるオープンソースの Triton融合カーネル で、学習時に標準PyTorch演算子を置き換えます。主な融合は次のとおりです。
-
融合クロスエントロピー :最終線形射影、softmax、損失計算を単一カーネルに統合し、完全な \((\text{batch} \times \text{seq} \times \text{vocab})\) ロジットテンソルの実体化を避ける。
-
融合RMSNorm/SwiGLU/RoPE :一般的なLLM構成要素の中間メモリ割り当てをなくす。
-
チャンク演算 :大きなテンソルをタイルで処理し、ピークメモリを一定に保つ。
結果 :1行の統合(apply_liger_kernel_to_llama())でスループットが20%向上し、メモリを最大60%削減する。FSDP、DeepSpeed、LoRAと互換性がある。
Unsloth (Han and Han 2024)
カスタムCUDA/Tritonカーネル と積極的なメモリ最適化を組み合わせた、専門的なファインチューニングライブラリです。
-
LoRAレイヤーを通る手動バックプロパゲーション(autogradのオーバーヘッドを避ける)。
-
融合デ量子化付き4-bit QLoRA。単一の48 GB GPUで70Bモデルを学習できる。
-
アーキテクチャ(Llama、Mistral、Qwen、Gemma)ごとに最適化したRoPEとアテンションカーネル融合。
結果 :素のHuggingFace+PEFTより2〜5\(\times\)高速で、VRAMを60〜70%削減。単一GPUやコンシューマーハードウェアのワークフローで特に効果的です。
torchtune (P. Team 2024)
MetaのネイティブPyTorchファインチューニングライブラリ(開発は2025年に縮小)。モノリシックな抽象化ではなく 合成可能性 を中心に設計されています。
-
純粋なPyTorch。Trainerクラスはなく、レシピは読みやすい単一ファイルのスクリプト。
-
torch.compile、FSDP2、アクティベーションチェックポイントとのネイティブ統合。 -
QLoRA、完全なファインチューニング、知識蒸留を第一級にサポート。
-
学習後圧縮のための量子化認識学習(QAT)を組み込みで提供。
結果 :カスタムソリューションと同等の速度を、完全なデバッグ可能性とフレームワークロックインなしで実現します。
Important
効率スタックの選択
\(\leq\)1 GPUでの迅速なLoRA/QLoRA :Unsloth(学習時間が最短で、セットアップが最小)。
マルチGPUの完全なファインチューニング :TRL/DeepSpeed+Liger Kernel(大規模で最高のスループット)
研究/カスタム学習ループ :torchtune(透明で改造しやすいネイティブPyTorch)
これらは 相補的 です。LigerカーネルはTRLとtorchtuneの両方のワークフロー内で使えます。
ベストプラクティス
| 実践項目 | 詳細 |
|---|---|
| パッキング | 複数の短い例を1つのシーケンスへ連結する(EOSで区切る)。パディングの無駄を避ける。 |
| NEFTune (Jain et al. 2024) | 埋め込みに一様ノイズを加える(\(\alpha=5\))。コストなしにMT-Benchを5〜15%改善する。 |
| チャットテンプレート | 常にモデル固有のテンプレートを使う。不一致は品質を低下させる。 |
| エポック数 | 大規模データセットでは2〜3、小規模(\(<\)10K)の選別データでは最大5。過学習は書式の記憶を引き起こす。 |
SFT学習のガイドライン。
Tip
SFTだけでは不十分
SFTは書式と基本的な指示追従を教えますが、選好(どの応答がよいか — RLHF/DPOが必要)、拒否(いつ答えないか — 安全性学習が必要)、キャリブレーション(「分からない」と言うこと — 真実性報酬付きRLが必要)、複雑な推論(多段階の連鎖 — 検証可能な報酬付きRLが必要)を確実には教えられません。完全なパイプラインは、事前学習 \(\to\) SFT \(\to\) RLHF/DPOです。
LoRAとパラメータ効率のよいファインチューニング
70Bモデルの完全なファインチューニングには、70B個の学習可能パラメータとオプティマイザー状態を保存する必要があります(メモリ560 GB以上)。LoRA (Hu et al. 2022b)(Low-Rank Adaptation)は、パラメータの \(<\)1% だけで同等の品質を得るファインチューニング方法です。
LoRAの洞察
Important
LoRAの核心
完全な重み行列 \(W \in \mathbb{R}^{d \times d}\) を更新する代わりに、低ランクの摂動を学習します。 \[ W' = W + \frac{\alpha}{r} \cdot BA, \quad B \in \mathbb{R}^{d \times r}, ; A \in \mathbb{R}^{r \times d} \]
\(W\) は 凍結 される(勾配もオプティマイザー状態もない)
\(B\) と \(A\) だけを学習する:\(d^2\) ではなく \(2 \times d \times r\) パラメータ
ランク \(r=16\)、\(d=4096\) では、LoRAはレイヤーあたり \(2 \times 4096 \times 16 = 131K\) パラメータを追加する。完全行列では \(16.8M\)。
\(\alpha/r\) スケーリングが更新の大きさを制御する
Tip
低ランクが機能する理由
Aghajanyanら (Aghajanyan et al. 2021) は、ファインチューニングが非常に低次元の部分空間で行われることを示しました。ファインチューニングタスクの「内在次元」はモデルのパラメータ数よりはるかに小さいのです。175Bモデルのファインチューニングタスクの内在次元は \(<\)10,000かもしれません。LoRAはこれを直接利用し、ランク \(r\) によって重み行列ごとの更新を \(r\) 次元部分空間に制限します。
Tip
$\alpha/r$ スケーリングが重要な理由
スケーリングがなければ、ランク \(r\) を2倍にすると \(\Delta W = BA\) の大きさもおよそ2倍になります(\(B\) のより多くの列が和に寄与するため)。つまりランクを変えるとモデルへの摂動量も変わり、\(r\) を調整するたびに学習率を再調整する必要があります。
\(\alpha/r\) 係数は、ランクによらず更新の大きさがほぼ一定になるよう 正規化 します。 \[ W' = W + \frac{\alpha}{r} \cdot BA \]
\(\alpha\) を固定して \(r\) を変える :実効更新量はランクに関係なく \(\sim\alpha\) に保たれる。学習率を再調整せず \(r \in \{8, 16, 32, 64\}\) を試せる。
一般的な設定 :\(\alpha = r\)(\(\alpha/r = 1\))または \(\alpha = 2r\)(\(\alpha/r = 2\))にする。スケーリング係数が小さな整数になる便利なデフォルトです。
学習率を調整するだけではだめか? それも可能ですが、\(\alpha/r\) は ランクに依存しない 調整つまみになります。異なるランクの実験で学習率のレシピを共有できます。
rsLoRAの洞察 (Kalajdzievski 2023):高ランク(\(r \geq 64\))では、\(BA\) の分散が \(r\) ではなく \(\sqrt{r}\) に比例するため、\(\alpha/\sqrt{r}\) の方が \(\alpha/r\) より安定だという実証結果があります。
LoRAのハイパーパラメータ
LoRAのハイパーパラメータを正しく選ぶことは重要です。ランクやalphaを誤ると、アンダーフィット(制約が強すぎる)か、メモリ浪費(表現力が過剰)になります。
| ハイパーパラメータ | 典型値 | 指針 |
|---|---|---|
r(ランク) | 8、16、32、64 | 高いほど容量が増えるがメモリも増える。16から始める。 |
lora_alpha | 16、32(多くは\(= r\)または\(2r\)) | \(\alpha/r\)スケーリングで更新量を制御する。 |
target_modules | q_proj, k_proj, v_proj, o_proj | すべてのアテンション射影。完全にカバーするにはgate_proj, up_proj, down_projを追加する。 |
lora_dropout | 0.0〜0.1 | 正則化。小規模データセットでは通常0.05。 |
bias | "none" | バイアスを学習してもパラメータはわずかしか増えず、役に立つことは少ない。 |
| 学習率 | \(1\text{e-}4\)〜\(3\text{e-}4\) | 完全なファインチューニングより高い(アダプターだけが更新されるため)。 |
LoRAのハイパーパラメータガイド。
Warning
ランク選択の経験則
r=8 :単純なタスク(単一ドメインチャット、分類)。非常にメモリ効率がよい。
r=16 :汎用ファインチューニング。よいデフォルト。
r=32〜64 :複雑なタスク(数学、コード、多ターン推論)。完全なファインチューニング品質に近づく。
r=128以上 :収穫逓減。完全なファインチューニングや高ランクQLoRAを検討する。
重要な指標 :学習損失が完全なファインチューニングの損失よりかなり高いところで頭打ちなら、ランクを上げる。
LoRAの派生手法
| 手法 | 主な革新 | 使う場面 |
|---|---|---|
| QLoRA (Dettmers et al. 2023) | 4-bit量子化ベース+BF16のLoRA。NF4型+二重量子化。 | 48GB GPU 1台で70Bをファインチューニング。 |
| DoRA (S.-Y. Liu et al. 2024) | \(W\)を大きさと方向に分解し、LoRAは方向だけを更新する。 | 推論の一般化が向上。 |
| LoRA+ (Hayou et al. 2024) | \(A\)と\(B\)で異なるLR(\(\eta_B = \lambda \eta_A\)、\(\lambda \approx 16\))。 | 追加コストなしで2%向上。 |
| AdaLoRA (Q. Zhang et al. 2023) | 層間でランク予算を動的に配分(SVDベースの重要度)。 | 計算予算が非常に厳しい場合。 |
| rsLoRA (Kalajdzievski 2023) | \(\alpha/r\)ではなく\(\alpha/\sqrt{r}\)でスケールする。高ランクで安定。 | \(r \geq 64\)を使う場合。 |
| VeRA (Kopiczko et al. 2024) | 凍結したランダム\(A, B\)を共有し、対角スケーリングだけを学習する。 | 極端なパラメータ効率が必要な場合。 |
| LoRA-FA | 初期化後に\(A\)を凍結し、\(B\)だけを学習する。LoRAのメモリを半減。 | メモリ制約がある場面。 |
LoRAの派生手法とその革新。
主な拡張の説明
DoRA — 重み分解低ランク適応
DoRA (S.-Y. Liu et al. 2024) は、完全なファインチューニングでは重みベクトルの大きさより 方向 が変わりやすいことに着目します。標準LoRAでは両者が混ざります。DoRAは各重み列を大きさ \(m = \\vert W\\vert _\text{col}\) と方向 \(\hat{V} = W / \\vert W\\vert _\text{col}\) に分解し、LoRAを方向だけに適用します。
\[ W' = m \odot \hat{V}', \quad \hat{V}' = \frac{W + BA}{|W + BA|_\text{col}} \]
大きさ \(m\) は別の学習可能なベクトル(列ごとに1スカラー)です。追加の推論コストなし(デプロイ時にマージ)で、推論・指示追従ベンチマークにおいてLoRAを一貫して1〜3%上回ります。
LoRA+ — 非対称学習率
Hayouら (Hayou et al. 2024) は、LoRAの行列 \(A\) と \(B\) には異なる最適学習率があることを示しました。\(B\) はゼロで初期化されるため、\(\mathcal{N}(0, \sigma^2)\) で初期化される \(A\) とは異なる状態から始まります。\(\eta_B \approx 16 \times \eta_A\) にすると、収束速度と最終品質が \(\sim\) 2%向上します。設定を1行変えるだけの追加コストなしの改善です。
# LoRA+ in PEFT: set different LRs per matrix
optimizer_grouped_parameters = [
{"params": [p for n, p in model.named_parameters() if "lora_B" in n],
"lr": 2e-4 * 16}, # B matrix: higher LR
{"params": [p for n, p in model.named_parameters() if "lora_A" in n],
"lr": 2e-4}, # A matrix: base LR
]
VeRA — ベクトルベースのランダム行列適応
VeRA (Kopiczko et al. 2024) はパラメータ効率を極限まで高めます。\(A\) と \(B\) を学習する代わりに、全レイヤーで共有するランダム行列として 凍結 し、2つの対角スケーリングベクトル \(d_b \in \mathbb{R}^r\)、\(d_a \in \mathbb{R}^d\) だけを学習します。
\[ \Delta W = B \cdot \text{diag}(d_b) \cdot A \cdot \text{diag}(d_a) \]
これはLoRAと比べて学習可能パラメータを \(\sim\) 10\(\times\)削減し(レイヤーあたり \(r + d\) パラメータのみ)、LoRA品質の90〜95%を達成します。最小限のストレージで数百のタスク固有アダプターが必要な場面に最適です。
Note
QLoRAによるメモリ削減
70Bモデルの完全なファインチューニング :140 GB(重み)+280 GB(オプティマイザー)+140 GB(勾配)=560 GB(A100-80GBが7\(\times\))。
70B QLoRA(r=16、すべての線形層) :
NF4のベースモデル:\(70\text{B} \times 0.5 = 35\) GB
BF16のLoRAアダプター:\(\sim\)160 MB
オプティマイザー状態(アダプターのみ):\(\sim\)320 MB
活性値(勾配チェックポイント):\(\sim\)8 GB
合計:\(\sim\)44 GB ——48GB GPU 1台に収まる。
# QLoRA configuration with PEFT
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
from transformers import BitsAndBytesConfig
import torch
# 4-bit quantization config
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4", # NormalFloat4 - optimal for weights
bnb_4bit_compute_dtype=torch.bfloat16, # Compute in BF16
bnb_4bit_use_double_quant=True, # Quantize the quantization constants
)
# LoRA config
lora_config = LoraConfig(
r=16,
lora_alpha=32, # alpha/r = 2x scaling
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",
)
model = prepare_model_for_kbit_training(model) # Prepare for QLoRA
model = get_peft_model(model, lora_config) # Add LoRA adapters
model.print_trainable_parameters()
# Output: trainable params: 83,886,080 || all params: 70,553,706,496 || 0.12%
その他のPEFT手法
LoRAは現在の実務で主流だが、パラメータ効率のよい手法はこれだけではない。ここでは主な代替手法を挙げる。
| 手法 | 仕組み | 長所 / 短所 | 状況 |
|---|---|---|---|
| LoRA (Hu et al. 2022b)(および派生手法) | 既存の重みに低ランク行列を追加 | 推論時にマージ可能(オーバーヘッドなし);広くサポート;すべてのアーキテクチャで動作 | 標準 |
| Adapters (Houlsby et al. 2019) | 層の間に小さなボトルネックMLPを挿入 | モジュール化・積層可能;推論レイテンシが増加(逐次層が追加される) | ほぼ使われない |
| Prefix Tuning (Li and Liang 2021) | 各層のキー・バリューの前に学習可能な「仮想トークン」を付加 | 重みを変更しない;生成タスクに有効;コンテキスト長を消費 | ニッチ |
| Prompt Tuning (Lester et al. 2021) | 入力の前に学習可能なソフトプロンプト埋め込みを付加 | パラメータが極めて少ない(\(<\)0.01%);複雑なタスクではLoRAより弱い | ニッチ |
| IA3 (H. Liu et al. 2022) | キー、バリュー、FFN活性を再スケーリングするベクトルを学習 | LoRAよりさらにパラメータが少ない;マージ可能;容量が限られる | 廃止傾向 |
| BitFit (Zaken et al. 2022) | バイアス項だけを学習 | ほぼゼロのパラメータ;単純なタスクには意外に有効;表現力が限られる | 歴史的手法 |
PEFT手法の系統。LoRAはLLMファインチューニングの事実上の標準であり、その他は歴史的背景とニッチな用途のために掲載している。
Tip
LoRAが主流になった理由
LoRAが標準になったのは、(1) 推論オーバーヘッドがゼロ ——アダプターをベース重みにマージでき、レイテンシを増やしたりコンテキストを消費したりするAdaptersやPrefix Tuningとは異なる、(2) 合成可能性 ——マルチテナント環境で、サービング時に複数のLoRAアダプターを交換できる、(3) エコシステムのサポート ——HuggingFace PEFT、TRL、vLLM、主要なフレームワークがすべてLoRAを第一級にサポートしている、(4) 大規模運用で実証済み ——Meta、Google、およびHuggingFace上のオープンソースのファインチューニングの大半で本番利用されている、という特徴を独自に兼ね備えるからである。LoRAでは満たせない具体的な制約がない限り、デフォルトの選択肢にすべきだ。
Mixture of Experts(MoE)
Mixture of Expertsモデル(Shazeer et al. 2017、Jiang et al. 2024)は、トークンごとにパラメータの一部だけを活性化することで、計算コストを比例して増やさずにモデル容量を拡大する。
アーキテクチャ
Important
MoE層
MoEトランスフォーマーでは、各ブロックのFFN層を、並列な\(N\)個の「エキスパート」FFNと、どのエキスパートを使うか選ぶ ルーター に置き換える。 \[ \text{MoE}(x) = \sum_{i=1}^{N} g_i(x) \cdot E_i(x), \quad g(x) = \text{TopK}(\text{softmax}(W_r x)) \]
\(E_i\) はエキスパートネットワーク(標準的なFFN層)
\(g_i(x)\) はルーターから得られるゲーティング重み(上位\(K\)個だけが非ゼロ)
通常、\(N=8\)〜64個のエキスパートのうち\(K=2\)個がトークンごとに活性化される
総パラメータ数は\(N\)に比例し、 活性パラメータ数 はFFNサイズの\(K/N\)に比例する
負荷分散
Warning
負荷分散の問題
制約がなければ、ルーターは大半のトークンを同じ1〜2個のエキスパートに送る可能性がある(「エキスパート崩壊」)。これは容量を無駄にし、GPU間の計算負荷の不均衡を生む(通常、各エキスパートは別々のGPUに配置される)。
解決策 :負荷分散の補助損失を追加する。 \[ \mathcal{L}_{\text{bal}} = \alpha \cdot N \sum_{i=1}^{N} f_i \cdot p_i \] ここで\(f_i\)はエキスパート\(i\)にルーティングされたトークンの割合、\(p_i\)はエキスパート\(i\)に対するルーター確率の平均である。これにより、エキスパートを均等に利用するよう促す。
Noisy Top-Kゲーティング:離散ルーティングを学習可能にする
MoEの中心的な課題は、 top-\(k\)選択が微分不可能 なことである——「上位2個を選ぶ」というハードな操作を通じて逆伝播できない。この問題を解決するため、研究分野では2つの主要な工夫が開発されてきた。
Tip
ルーティングの微分可能性の問題
ルーターは各エキスパートについてロジット\(h(x) = W_r \cdot x\)を計算し、top-\(k\)を選択する。しかし、
選択されたエキスパートは、ゲート重み(選択されたものに対するsoftmax)を通じて勾配を受け取る
選択の判断そのもの(どの\(k\)個を選ぶか)には勾配がない
工夫がなければ、ルーターは行き詰まる可能性がある。あるエキスパートが選ばれない \(\rightarrow\) 勾配信号を受け取れない \(\rightarrow\) その後も選ばれない、という循環に陥るためである
アプローチ1:Noisy Top-Kゲーティング (Shazeer et al. 2017)
top-\(k\)選択の前に、ルーターのロジットへ学習可能なガウスノイズを加える。
\[ \begin{aligned} h(x) &= W_g \cdot x && \text{(clean logits)} \\ H(x) &= h(x) + \epsilon \cdot \text{Softplus}(W_{\text{noise}} \cdot x), \quad \epsilon \sim \mathcal{N}(0, 1) && \text{(noisy logits)} \\ \text{TopK}(v, k)_i &= \begin{cases} v_i & \text{if } v_i \text{ is in the top } k \\ -\infty & \text{otherwise} \end{cases} \\ g(x) &= \text{softmax}\big(\text{TopK}(H(x),, k)\big) && \text{(sparse gates)} \end{aligned} \]
-
\(W_{\text{noise}}\) は学習されるノイズの大きさであり、モデルは各エキスパートにどの程度の探索が必要かを学習する
-
学習中はノイズによって「劣勢」のエキスパートがときどきtop-\(k\)に入り、勾配信号を受け取れる
-
推論時にはノイズを除き、決定的なルーティングのためにクリーンなロジット\(h(x)\)を使う
-
Softplusにより、ノイズのスケールは常に正になる
アプローチ2:Gumbel-Softmaxトリック(微分可能な離散サンプリング)
変分推論の文献に由来する代替手法である(Jang et al. 2017)。 Gumbel-Maxトリック はカテゴリ分布からの正確なサンプリングを提供する。
\[ z = \arg\max_i \left[ \log \pi_i + G_i \right], \quad G_i \sim \text{Gumbel}(0,1) \]
ここで、Gumbelノイズは\(G_i = -\log(-\log(U_i)),; U_i \sim \text{Uniform}(0,1)\)として生成される。
top-\(k\)ルーティング では、\((\log \pi_i + G_i)\)のtop-\(k\)を取ることで、\(\pi\)が定めるカテゴリ分布からの\(k\)個の非復元サンプルが得られる。
\(\arg\max\)は微分不可能なので、 Gumbel-Softmax 緩和ではこれを温度制御されたsoftmaxに置き換える。
\[ \hat{g}_i = \frac{\exp\left((\log \pi_i + G_i) / \tau\right)}{\sum_j \exp\left((\log \pi_j + G_j) / \tau\right)} \]
-
\(\tau \to 0\):ハードなone-hotに近づく(正確だが微分不可能)
-
\(\tau \to \infty\):一様分布に近づく(微分可能だが情報を持たない)
-
実際には、学習中に\(\tau\)を1.0から0.1〜0.5までアニーリングする
-
Straight-through推定量 :順伝播ではハードなtop-\(k\)を使い、逆伝播ではGumbel-Softmaxの勾配を使う——両者の長所を組み合わせられる
Important
実務ではどの手法を使うか
Sparsely-Gated MoE (Shazeer et al. 2017)、Mixtral (Jiang et al. 2024)、DeepSeek-V2 (DeepSeek-AI 2024a) :ガウスノイズを使うNoisy Top-Kを採用する。単純で効果的であり、大規模モデルで十分に実証されている。
Switch Transformer (Fedus et al. 2022) :ノイズなしのTop-1に簡略化している(負荷分散損失だけに依存する)。
研究用/小規模MoE :完全に微分可能なルーティングのためGumbel-Softmaxを使う例もある。特に、ルーティング自体の学習が研究目的である場合に用いられる。
重要な洞察 :どちらの手法も、ノイズ注入によって同じ問題(離散選択を学習可能にすること)を解決する。ガウスノイズはより単純であり、Gumbelノイズはカテゴリサンプリングに対する理論的保証がより強い。
代表的なMoEモデル
| モデル | 総パラメータ数 | 活性パラメータ数 | エキスパート | 新規性 |
|---|---|---|---|---|
| Switch Transformer (Fedus et al. 2022) | 1.6T | 100B | 128, Top-1 | 初の大規模MoE;ルーティングを簡略化 |
| Mixtral 8x7B (Jiang et al. 2024) | 47B | 13B | 8, Top-2 | オープンウェイト;Llama-2 70Bと同等の品質 |
| DeepSeek-V2 (DeepSeek-AI 2024a) | 236B | 21B | 160, Top-6 | 共有エキスパートとルーティングエキスパートを持つDeepSeekMoE |
| Qwen-MoE (Q. Team 2024a) | 14.3B | 2.7B | 60, Top-4 | 効率性のための細粒度エキスパート |
| DBRX (Databricks 2024) | 132B | 36B | 16, Top-4 | ブロックごとに4個の細粒度エキスパート |
LLM学習における多様性
学習データ、モデル出力、最適化の軌跡における多様性は、モード崩壊を防ぎ、頑健で汎用的なLLMを実現するうえで重要である。この節では、LLM学習のすべての段階に適用できる主要な多様性の仕組みを扱う。
サンプリングの多様性
Important
多様な生成のためのサンプリング戦略
温度 \(\tau\) :\(P(x_i) \propto \exp(\text{logit}_i / \tau)\)。\(\tau\)が高いほど分布は一様になり、多様性が増す。RLHFでの生成では通常\(\tau=0.7\)〜\(1.0\)。
Top-\(k\) :確率が最も高い\(k\)個のトークンだけからサンプリングする。確率の低い退化したトークンを防ぐ。
Top-\(p\)(nucleus) :累積確率が\(\geq p\)となる最小のトークン集合からサンプリングする。適応的なので、モデルが不確かなときほど多様になる。
Min-\(p\) :\(P \geq p_{\min} \times P_{\max}\)を満たすトークンだけを残す。top-\(k\)より原理に沿った方法である。
頻度/存在ペナルティ :応答中に現れたトークンにペナルティを与える。語彙の多様性を促す。
学習データの多様性
-
プロンプトの多様性 :異なる領域、難易度、形式をカバーする。ゴルディロックス原理に従い、プロンプトの成功率は20〜80%にする。
-
重複除去 :ほぼ重複する学習例(MinHash、n-gramの重なり)を削除する。重複は特定のパターンへの過学習を招く。
-
データ混合 :温度重み付きサンプリングやカリキュラム戦略を使い、タスクや領域間のバランスを取る。
多様性を促す手法
| 手法 | 多様性を促す仕組み |
|---|---|
| 温度スケーリング | \(\tau\)を高くすると分布が平坦になり、もっと多くのトークンが妥当になる。 |
| Top-\(p\) / Min-\(p\) | 適応的なしきい値により、モデルが不確かなときにより広くサンプリングできる。 |
| 頻度ペナルティ | 繰り返しトークンにペナルティを与え、応答内の語彙の多様性を強制する。 |
| データ重複除去 | 学習データからほぼ重複する例を除き、特定パターンへの過学習を防ぐ。 |
| 複数領域の混合 | 領域間で温度重み付きサンプリングを行い、広いカバレッジを確保する。 |
| 言語化サンプリング | 応答についての確率分布を明示的に言語化するようモデルに促す(J. Zhang et al. 2025)。§4.5を参照。 |
テキスト生成:デコーディング手法
学習済み言語モデルは各ステップで語彙上の確率分布\(P(x_t \vert x_{<t})\)を出力する。 デコーディング戦略 は、この分布から次のトークンをどう選ぶかを決める。この選択は出力の品質、多様性、一貫性に大きな影響を与える。
貪欲デコーディング
最も単純な戦略であり、常に確率が最も高いトークンを選ぶ。
\[ x_t = \arg\max_{v \in \mathcal{V}} P(v | x_{<t}) \]
直感 :文中で常に最も明白な次の単語を選ぶようなもの。「The capital of France is...」\(\to\)「Paris」(確率0.92)。
長所 :決定的で高速、ハイパーパラメータが不要。
短所 :反復的で一般的なテキストを生成する。序盤の確率が低いトークンが全体としてよりよい出力につながる高品質な系列を逃す。多様性がない。
ビームサーチ
\(B\)個(ビーム幅)の部分仮説を並列に保持し、それぞれをtop-\(k\)トークンで展開しながら、スコアの高い\(B\)個の完成系列を残す。
\[ \text{score}(y_{1:t}) = \sum_{i=1}^{t} \log P(y_i | y_{<i}) \]
短い系列が有利になるのを避けるため、 長さ正規化 を行う。
\[ \text{score}_{\text{norm}}(y) = \frac{1}{|y|^\alpha} \sum_{i=1}^{|y|} \log P(y_i | y_{<i}), \quad \alpha \in [0.6, 1.0] \]
直感 :迷路で複数の経路を同時に探索し、分岐点ごとに最も有望な\(B\)本だけを残すようなもの。
長所 :貪欲法より尤度の高い系列を見つける。「正解」が1つに近い翻訳や要約に適する。
短所 :自由生成では一般的で反復的なテキストに偏りやすい。計算量は\(B \times\)になり、すべてのビームが似た出力に収束することも多い。
多様ビームサーチ
標準的なビームサーチでは、ほぼ重複するビームが生じる。多様ビームサーチ(Vijayakumar et al. 2018)はビームを\(G\)個のグループに分け、グループ間に 非類似度ペナルティ を加える。
\[ \text{score}_g(y_t) = \log P(y_t | y_{<t}) - \lambda \sum_{g'<g} \Delta(y_t, Y_{g'}) \]
ここで\(\Delta\)は先行グループがすでに選んだトークンとの重なり(例えばハミング多様性)を測り、\(\lambda\)は多様性の強さを制御する。
直感 :ブレインストーミングのグループに異なるアイデアを出させるようなもの。各サブグループは、先行サブグループの発言を繰り返すとペナルティを受ける。
長所 :本当に異なる候補系列を生成し、再ランキングのパイプラインに有用。
短所 :多様性ペナルティによって個々のビームの品質が低下しうる。ハイパーパラメータ(\(G\)、\(\lambda\))も増える。
Top-\(k\) サンプリング
最も確率の高い\(k\)個のトークンだけからサンプリングし、確率質量を再配分する。
\[ P'(v | x_{<t}) = \begin{cases} \dfrac{P(v | x_{<t})}{\sum_{v' \in \text{Top-}k} P(v' | x_{<t})} & \text{if } v \in \text{Top-}k \\[6pt] 0 & \text{otherwise} \end{cases} \]
直感 :「The cat sat on the...」の後では、もっともらしい上位\(k\)個の続き(「mat」「floor」「couch」など)だけを考え、極端にありそうにないもの(「quantum」「archipelago」など)は無視する。
長所 :裾のノイズを除き、実装が簡単。
短所 :固定された\(k\)は、尖った分布では制限が強すぎて確率質量を無駄にし、平坦な分布では緩すぎて不要なトークンを含めてしまう。
Top-\(p\)(Nucleus)サンプリング
累積確率が\(p\)を超える最小のトークン集合からサンプリングする。
\[ \text{Top-}p = \min \left\{ S \subseteq \mathcal{V} : \sum_{v \in S} P(v | x_{<t}) \geq p \right\} \]
トークンを確率の降順に並べ、しきい値\(p\)に達するまで追加する。
直感 :候補集合の大きさを適応的に変える。モデルが確信している場合(「Paris」が95%)はnucleusが小さくなり、不確かな場合(「The movie was...」)はもっともらしい形容詞を多く含むようnucleusが広がる。
長所 :分布の形状に適応し、広く使われるデフォルト(\(p=0.9\)〜\(0.95\))である。
短所 :nucleusの末尾に低品質なトークンが含まれることがある。しきい値は単一のグローバルなハイパーパラメータである。
Tip
Top-kkとTop-pp
次の単語を予測する場合を考えよう。
「2 + 2 =」の後では分布が尖っており、top-1トークン(「4」)が99%の質量を持つ。Top-\(k\)=50では、間違った答え49個まで無駄に検討する。Top-\(p\)=0.9なら「4」だけを正しく選ぶ。
「I enjoy eating」の後では分布が平坦で、多くの食べ物がもっともらしい。Top-\(k\)=5では制限が強すぎる。Top-\(p\)=0.9なら50個以上のトークンを含むことがあり、実際の不確かさに合う。
Top-\(p\)は適応するが、top-\(k\)は適応しない。実際には両者を組み合わせ、top-\(p\)とtop-\(k\)の共通部分からサンプリングすることが多い。
Min-\(p\) サンプリング
相対的な 確率の下限を設定する近年の代替手法(Nguyen 2024):
\[ \text{Min-}p = \left\{ v \in \mathcal{V} : P(v | x_{<t}) \geq p_{\min} \cdot \max_{v'} P(v' | x_{<t}) \right\} \]
最上位トークンの確率の少なくとも\(p_{\min}\)倍の確率を持つトークンだけを残す。
直感 :「最良のトークンの少なくとも10%の確率を持つトークンだけを考える」。最上位トークンの確率が0.8なら、0.08を超えるトークンだけが残る。最上位トークンの確率が0.05(非常に不確か)なら、0.005を超えるトークンが残り、候補集合は自然に広がる。
長所 :モデルの確信度に自然に応じて変化する。尖った分布ではtop-\(p\)より退化したサンプルが少なく、直感的な単一パラメータで済む。
短所 :新しく、十分に実績が蓄積されていない。すべての推論フレームワークで標準になっているわけではない。
温度スケーリング
どのサンプリング戦略を適用する前にも、ロジットを温度\(T\)で割る。
\[ P_T(v | x_{<t}) = \frac{\exp(z_v / T)}{\sum_{v'} \exp(z_{v'} / T)} \]
-
\(T < 1\):分布が尖る \(\to\) より決定的で焦点の合った出力になる。
-
\(T = 1\):モデルの分布をそのまま使う。
-
\(T > 1\):分布が平坦になる \(\to\) よりランダムで創造的な出力になる。
-
\(T \to 0\):貪欲デコーディングになる。\(T \to \infty\):一様サンプリングになる。
一般的な設定 :事実に関するタスクでは\(T=0.7\)、創作では\(T=1.0\)〜\(1.2\)、コードや数学では\(T=0.0\)(貪欲法)。
対照的デコーディング
対照的デコーディング(X. Li et al. 2023)は、強いモデル(エキスパート)と弱いモデル(アマチュア)の差を利用して、エキスパート固有の知識を増幅する。
\[ x_t = \arg\max_{v \in \mathcal{V}(x_{<t})} \left[ \log P_{\text{expert}}(v | x_{<t}) - \log P_{\text{amateur}}(v | x_{<t}) \right] \]
ここで\(\mathcal{V}(x_{<t}) = \{v : P_{\text{expert}}(v \vert x_{<t}) \geq \alpha \cdot \max_{v'} P_{\text{expert}}(v' \vert x_{<t})\}\)は適応的な妥当性制約である。
直感 :アマチュアモデルは一般的で明白なパターン(よくある単語や反復)を捉える。その対数確率を引くことで、この「一般的な信号」を取り除き、エキスパートの特徴的な知識と推論を残す。録音から背景ノイズを除き、信号を聞き取るようなものだ。
長所 :反復や一般的な言い回しを減らし、追加学習なしに事実性と一貫性を高める。任意のモデルペアで動作する。
短所 :2つのモデルを実行する必要がある(計算量は2\(\times\))。アマチュアモデルの選択に敏感で、妥当性しきい値\(\alpha\)の調整も必要である。
反復ペナルティ
サンプリング戦略とは独立に、反復ペナルティはモデルがトークンを繰り返すのを抑制する。トークン\(v\)の生ロジット\(z_v\)(つまりsoftmax前にLMヘッドが出力する正規化前のスコア)が与えられたとき、ペナルティ後のロジットは次のようになる。
\[ z_v' = \begin{cases} z_v / \theta & \text{if } v \in \text{generated tokens and } z_v > 0 \\ z_v \cdot \theta & \text{if } v \in \text{generated tokens and } z_v < 0 \end{cases} \]
ここで\(\theta > 1\)はペナルティ係数(通常1.1〜1.3)である。どちらの場合も、ロジットを0へ近づけることで、以前に生成したトークンの確率を下げる。頻度ペナルティと存在ペナルティは、OpenAI APIで使われるより単純な加算型の変種である。
\[ z_v' = z_v - \alpha \cdot \text{count}(v) - \beta \cdot \mathbf{1}[v \in \text{generated}] \]
ここで\(\alpha\)は頻度ペナルティ(\(v\)が現れた回数に比例)で、\(\beta\)は存在ペナルティ(過去に一度でも現れた場合に一律で課すペナルティ)である。
実用比較
| 手法 | 決定的 | 多様性 | 品質 | 適した用途 |
|---|---|---|---|---|
| 貪欲法 | あり | なし | 中 | コード、事実性QA |
| ビームサーチ(\(B\)=4〜8) | あり | 低 | 高(狭い) | 翻訳、要約 |
| 多様ビームサーチ | あり | 中 | 高 | 再ランキング用の候補生成 |
| Top-\(k\)(\(k\)=50) | なし | 中 | 中 | 汎用生成 |
| Top-\(p\)(\(p\)=0.9) | なし | 適応的 | 高 | 自由生成タスクのデフォルト |
| Min-\(p\)(\(p_{\min}\)=0.1) | なし | 適応的 | 高 | top-\(p\)の頑健な代替 |
| 対照的 | あり | 低 | 非常に高 | 事実性の高い一貫した長文 |
LLMテキスト生成におけるデコーディング手法の比較。
Note
実際のデコーディング:「Once upon a time」
プロンプト「Once upon a time」が与えられた場合:
貪欲法 :「there was a young girl who lived in a small village...」(一般的なおとぎ話)
Top-\(p\)=0.9、\(T\)=1.0 :「the rivers ran backwards and the fish learned to fly...」(創造的で意外)
Top-\(p\)=0.9、\(T\)=0.3 :「there was a kingdom ruled by a wise and just king...」(一貫していて慣習的)
対照的 :「in the amber-lit corridors of a collapsing star, two minds argued about the nature of time...」(特徴的で、決まり文句を避ける)
同じモデル、同じプロンプトでも、デコーディング戦略が出力の性格を決める。
制約付きデコーディング(構造化生成)
上記の手法はすべて、各ステップで語彙全体からサンプリングする。 制約付きデコーディング は許可されるトークン集合を制限し、出力が形式文法(通常はJSONスキーマ、正規表現、または文脈自由文法(CFG))に従うことを保証する。
中核メカニズム
各デコーディングステップ\(t\)で、現在のパーサ状態から トークンマスク\(M_t \subseteq \mathcal{V}\)を計算する。\(M_t\)内のトークンだけが元のロジットを受け取り、それ以外はsoftmaxの前に\(-\infty\)へ設定する。
\[ P'(v | x_{<t}) = \begin{cases} P(v | x_{<t}) / Z & \text{if } v \in M_t \\ 0 & \text{otherwise} \end{cases} \]
ここで\(Z = \sum_{v \in M_t} P(v \vert x_{<t})\)は再正規化を行う。マスクは各ステップで変化し(それまでに生成された内容に依存する)、制約は逐次的に適用される。そのためモデルはどの時点でも無効な接頭辞を生成できない。
スキーマからマスクへ
コンパイルのパイプラインは次のとおりである。
\[ \text{JSON Schema} ;\xrightarrow{\text{compile}}; \text{Regex} ;\xrightarrow{\text{compile}}; \text{FSM (DFA)} ;\xrightarrow{\text{index}}; \text{Token Mask per State} \]
FSMの状態は正規表現内の位置に対応する。各状態について、文字列をその言語内に保てるすべての語彙トークンをインデックスへ事前計算する(スキーマごとに一度だけ必要なコスト)。実行時のマスク検索は\(O(1)\)のテーブル参照なので、各デコーディングステップへのレイテンシ追加はごくわずかである。
主要ライブラリ
-
Outlines (Willard and Louf 2023:JSONスキーマと正規表現をFSMにコンパイルし、FSMに導かれる生成へ組み込む。ロジットインターフェースを持つ任意のモデルをサポートする。
-
lm-format-enforcer1:同様のFSM方式で、サービングフレームワーク(vLLM、TGI)との統合に重点を置く。
-
Guidance2(Microsoft):制約付き生成を制御フロー(ループ、条件分岐)と組み合わせ、単純なスキーマを超える複雑な構造化出力を可能にする。
-
XGrammar (Dong et al. 2024:プッシュダウンオートマトンに基づくエンジンで、正規言語だけでなく完全な文脈自由文法をサポートする。MLC-LLMやvLLMで文法モードのデコーディングに使われる。
トレードオフ
制約付きデコーディングは構文的な妥当性を保証し、事後のパース失敗やリトライをなくす。ただし、
-
意味的品質 :モデルが「正しい」答えに割り当てる確率質量が文法の外にある場合、構造を強制すると内容の品質が低下しうる。適切に設計されたスキーマと十分に学習されたモデルでは、実際にはまれである。
-
コンパイルコスト :FSMインデックスはスキーマごとに構築する必要がある。複雑なスキーマでは1〜5秒かかることがあるが、そのスキーマを使うすべてのリクエストに対して償却される。
-
文法のカバレッジ :正規表現/FSMはJSON、YAML、SQL断片、その他大半の構造化形式を扱う。完全なCFG(XGrammarやLALRパーサーによるもの)はPythonやXMLのような言語をカバーする。
Important
制約付きデコーディングを使う場面
モデル出力の利用者が人間ではなくプログラムである場合は、制約付きデコーディングを使うとよい。ツール呼び出しエージェント、APIバックエンド、データ抽出パイプラインはいずれも、妥当な構造が保証されることで恩恵を受ける。自由形式の文章や創作テキストには、制約なしのサンプリングが適している。
プロンプトエンジニアリング
プロンプトエンジニアリングとは、モデルの重みを変更せずに、望ましい振る舞いをLLMから安定して引き出す入力を設計する分野である。ファインチューニングがモデルを変更するのに対し、プロンプトエンジニアリングは、適切な枠組み、例、構造によってモデルの既存の能力を引き出す。LLMの出力を改善する最も速く、安価で、利用しやすい手段であり、ファインチューニング済みモデルを使う場合でも不可欠である。
文脈内学習(ICL)
文脈内学習(Brown et al. 2020)は、勾配更新なしに、プロンプトに与えられた例だけから推論時にタスクを学習する大規模言語モデルの注目すべき能力である。モデルは入力と出力のペアのパターンから暗黙にタスクを推測し、新しい入力へ一般化する。
Important
文脈内学習が機能する理由
暗黙のベイズ推論 :モデルは事前学習中に数百万のタスクを見ている。プロンプトの例は、モデルが学習した分布の中で関連するタスクを特定する(Xie et al. 2022)。
誘導ヘッド :特定のアテンションヘッドがパターン(「A is to B as C is to 」)をコピーすることを学び、文脈内での一般化を可能にする(Olsson et al. 2022)。
タスクベクトル :ICLは残差ストリームに暗黙のタスク表現を作り、実演された形式と内容へ生成を誘導する(Todd et al. 2024)。
スケーリングの挙動
ICLは主に\(\sim\)1Bパラメータを超えるモデルで現れ、モデル規模とともに対数線形に向上する(Brown et al. 2020)。小規模モデルは例を記憶できても、同じコンテキストウィンドウ内の未知の入力へ一般化するのは難しい。
ゼロショットプロンプティング
ゼロショットプロンプティングでは例を一切与えず、タスクの説明または指示だけを与える。モデルは正しい形式と内容を生成するため、事前学習で得た知識と指示チューニングだけに頼らなければならない。
Note
ゼロショット分類
次の映画レビューをPOSITIVEまたはNEGATIVEに分類せよ。
レビュー:「映像は息をのむほど素晴らしかったが、筋書きは 急ぎ足で予測可能に感じられた。」 感情:
ゼロショットがうまくいく場合
-
事前学習/SFTでモデルが十分に見てきたタスク(翻訳、要約、感情分析)
-
出力形式が曖昧でない、明確に定義された指示
-
指示チューニングされたモデル(ChatGPT、Claude、Llama-3-Instructなど)は、ゼロショットタスクでベースモデルを大きく上回る(Ouyang et al. 2022)
ゼロショットが失敗する場合
新しい形式、領域固有のラベル体系、または指示だけでは正確な要件を推測できない曖昧なタスクでは失敗する。
few-shotプロンプティング
Few-shotプロンプティング(Brown et al. 2020)では、実際のクエリの前に\(k\)個の入出力例(「ショット」)を与える。これは文脈内学習で最も一般的な形であり、現在でも最も効果的なプロンプティング戦略の一つである。
Note
Few-shot固有表現認識
テキストから固有表現を抽出せよ。形式:ENTITY
テキスト:「Apple released the iPhone 15 in Cupertino.」 固有表現:[Apple](ORG)、[iPhone 15](PRODUCT)、[Cupertino](LOC) テキスト:「Elon Musk announced Tesla's new factory in Berlin.」 固有表現:[Elon Musk](PER)、[Tesla](ORG)、[Berlin](LOC) テキスト:「OpenAI partnered with Microsoft to deploy GPT-4.」 固有表現:
few-shot例の設計原則
-
多様性 :想定される入力の範囲(異なる長さ、エッジケース、カテゴリ)をカバーする。
-
順序 :難しい例や代表的な例を最後に置く(新近性バイアス)(Lu et al. 2022)。
-
ラベルのバランス :分類では、最多クラスへのバイアスを避けるため、すべてのクラスの例を含める。
-
形式の一貫性 :すべての例がまったく同じ構造に従うようにする。モデルはそのパターンを模倣する。
-
関連性 :最良の結果を得るには、対象クエリと意味的に似た例を使う(J. Liu et al. 2022)。
何ショット必要か?
性能は通常、例が0個から4〜8個になるまで向上し、その後は頭打ちになる。\(\sim\)20例を超えると改善はわずかで、コンテキストウィンドウを埋めるリスクがある。Minら(Min et al. 2022)は、例の形式とラベル空間がラベルの正しさより重要であることを示した。ランダムなラベルでも役に立つ(ただし正しいラベルの方がより有効)。
指示追従プロンプト
指示チューニングされたモデルは、明確で構造化された指示に最もよく応答する。重要なのは、プロンプトを提案ではなく仕様として扱うことである。
Important
効果的な指示プロンプトの構成
役割/ペルソナ :モデルが何者かを定義する(「あなたはシニアデータサイエンティストです……」)
タスク :何をするかを明確かつ曖昧さなく述べる
コンテキスト :モデルに必要な背景情報
制約 :長さの上限、語調、避けること、出力形式
例 (任意):望ましい出力形式を示す
入力 :処理対象の実データ
Note
制約付き指示プロンプト
役割:あなたは医学文献のレビュアーです。
タスク:次の研究要旨を一般読者向けに要約せよ。 制約: - 最大3文 - 専門用語を使わない(技術用語は説明する) - 主要な発見とその臨床的含意を含める - 要旨に書かれている以上の推測を絶対にしない Abstract: [...]
システムプロンプトとユーザープロンプト
現代のチャットAPIでは、システムプロンプト(永続的な指示、役割定義)とユーザーメッセージ(ターンごとの入力)を分離する。ほとんどのモデルではシステムプロンプトがより高いアテンション優先度で処理され、役割定義、制約、出力形式の仕様を置く自然な場所となる(OpenAI 2023)。
構造化出力プロンプト(JSON/XML)
プログラムから利用する場合、最も重要なプロンプティング技法は、特にJSONのような構造化出力を強制することである。
Note
JSON出力プロンプト
顧客メールから次の情報を抽出せよ。 有効なJSONだけで応答し、他のテキストは出力しないこと。
Schema: { "intent": "refund|complaint|question|praise", "urgency": "low|medium|high", "product_mentioned": "string or null", "summary": "one sentence summary" } Email: [...]
信頼できる構造化出力の技法
-
スキーマファースト :入力より前に正確なJSONスキーマを示す。モデルはそれをテンプレートとして扱う。
-
制約付きデコーディング :文法ベースのサンプリング(Outlines(Willard and Louf 2023)、Guidanceなど)を使い、トークンレベルで構文的に妥当なJSONを保証する。
-
XMLタグ :入れ子構造や複数部分の出力では、XMLタグ(例:
<thinking>...</thinking>)が曖昧さのない区切りとなり、モデルは安定して従える。 -
Pydantic/TypeScript型 :型定義を与えると、モデルがフィールドの制約を理解しやすい(OpenAIの関数呼び出しは内部でJSON Schemaを使う)。
Warning
プロンプト内のJSON——よくある落とし穴
モデルがMarkdownのフェンス(
‘‘‘json ... ‘‘‘)を追加することがある。生のJSONを出力するよう明示する。入れ子のオブジェクトや配列は幻覚のリスクを高める。可能ならスキーマを平坦化する。
Enumフィールド(選択肢が固定されたフィールド)は自由記述フィールドよりはるかに信頼できる。
必ずプログラムで出力を検証する。制約付きデコーディングなしに、100%の遵守を保証するプロンプトはない。
JSONプロンプティング:入力を構造化する
これとは別だが補完的な技法がJSONプロンプティングである。自然言語ではなく、プロンプト自体をJSONとして整形する。これは構造化データ(API、設定、コード)に対するモデルの豊富な事前学習を利用し、指示への遵守を高め、曖昧さを減らし、複数フィールドの要求を決定的にパースできるようにする。
Note
システムプロンプトを使ったJSONプロンプティング
=== SYSTEM === あなたはシニアコードレビュアーです。コードのバグ、 セキュリティ問題、スタイル違反を分析してください。常に 与えられたJSONスキーマで応答してください。
=== USER (JSON prompt) === { "task": "code_review", "language": "python", "severity_filter": "high", "code": "def login(user, pw):\n query = ...", "output_schema": { "issues": [{ "line": "int", "severity": "critical|high|medium|low", "category": "security|bug|style|performance", "description": "string", "fix": "string" }], "overall_risk": "critical|high|medium|low" } }JSONプロンプティングが機能する理由:
曖昧さのないフィールド境界 :ある指示が終わり、別の指示が始まる場所を混同しない。
型付き制約 :フィールド
"severity_filter": "high"は、「重大度の高い問題だけを表示せよ」より明確である。契約としてのスキーマ :入力に
output_schemaを含めることは、モデルが事前学習中に大量に見てきたAPI設計パターンを反映する。システムプロンプトは依然として不可欠 :システムメッセージは、JSONペイロードには自然に収まらない役割、語調、振る舞いの制約を与える。
Chain-of-Thought(CoT)プロンプティング
Chain-of-thoughtプロンプティング(Wei et al. 2022)は、最終回答の前に中間的な推論ステップを生成するようモデルに求める。この単純な技法により、算術、論理、常識推論、コード生成など、複数ステップの推論を必要とするタスクの性能が大きく向上する。
CoTが機能する理由
-
計算を逐次化する :Transformerの深さは固定だが、生成の長さは可変である。CoTは並列的で難しい問題を逐次的で簡単なステップに変換し、モデルの計算予算を実質的に増やす。
-
誤差の累積を減らす :各ステップがより単純な部分問題となり、ステップごとの誤り率が下がる。
-
中間状態を露出させる :推論を監査・デバッグ可能にする。
Important
Chain-of-Thoughtの変種
手法 説明 Zero-shot CoT (Kojima et al. 2022) 任意のプロンプトに「一歩ずつ考えよう」を追加する Few-shot CoT (Wei et al. 2022) 明示的な推論連鎖を含む例を与える Self-Consistency (X. Wang, Wei, Schuurmans, Q. Le, et al. 2023) \(N\)本のCoT経路をサンプリングし、最終回答を多数決する Tree of Thoughts (S. Yao, Yu, et al. 2023) バックトラッキングしながら複数の推論分岐を探索する Plan-and-Solve (L. Wang et al. 2023) まず手順を計画し、その後各ステップを実行する ReAct (S. Yao, Zhao, et al. 2023) 推論と行動(ツール利用)を交互に行う
Note
ゼロショットChain-of-Thought
Q:店にリンゴが45個ある。午前にその3/5を売り、 午後に残りの1/3を売った。何個残っているか。
一歩ずつ考えてみよう。 A:午前の販売:45 * 3/5 = 27個を販売。 午前後の残り:45 - 27 = 18。 午後の販売:18 * 1/3 = 6個を販売。 残り:18 - 6 = 12個。
自己整合性
Wangら(X. Wang, Wei, Schuurmans, Q. Le, et al. 2023)は、複数のchain-of-thought推論経路をサンプリングし、最終回答を多数決すると、単一経路のCoTを大きく上回ることを示した。直感的には、正しい推論経路は同じ答えに収束しやすい一方、誤りは個別的である。この方法は、計算量(\(N\)個のサンプル生成)と引き換えに精度を得るもので、レイテンシより正しさが重要な場合に実用的である。
CoTが害になる場合
CoTが常に有益とは限らない。単純なタスク(1ステップの分類、検索、整形)では、CoTは不要なトークンを追加し、レイテンシを増やし、考えすぎによって誤りを生むことさえある。複数ステップの推論が必要だと予想されるタスクに限定してCoTを使うべきである。
高度なプロンプティング技法
検索拡張生成(RAG)
モデルのパラメトリック記憶だけに頼るのではなく、RAG(P. Lewis et al. 2020)は関連文書を検索し、プロンプトに含める。
コンテキスト(検索結果):[文書の断片]
質問:[ユーザークエリ]
与えられたコンテキストだけに基づいて回答せよ。
これによりモデルの応答を検証可能な情報源に基づかせ、知識集約型タスクでの幻覚を大きく減らせる。
プロンプト連鎖と分解
複雑なタスクは、より単純なプロンプトのパイプラインへ分解すると効果的である。あるプロンプトの出力を次の入力にする。
-
抽出:文書から重要な事実を取り出す
-
推論:抽出した事実について推論する
-
整形:最終回答を整形する
各ステップで異なるプロンプトテンプレート、モデル、温度設定を使える。単一の巨大なプロンプトより制御しやすく、対象を絞ったデバッグも可能になる。
Constitutional AI/自己批評
Baiら(Bai et al. 2022)は、一連の原則に照らして自分の出力を批評・修正するようモデルに求めるプロンプトを導入した。
[初期応答を生成]
批評:この応答は次の原則のいずれかに違反しているか。
[原則の一覧]
修正:批評に対応するよう応答を書き直す。
メタプロンプティングとプロンプト最適化
プロンプトを手作業で作るのではなく、近年の研究では設計を自動化している。
-
APE (Y. Zhou et al. 2023:LLMを使って候補プロンプトを自動生成し、スコア付けする。
-
DSPy (Khattab et al. 2024:宣言的なタスク記述を、学習されたfew-shot例を持つ最適化済みプロンプトパイプラインへコンパイルする。
-
OPRO (C. Yang et al. 2024:LLMをオプティマイザーとして使い、プロンプト最適化を最適化問題として扱う。
注意を向けた推論クエリ(ARQ)
ARQ(Yang et al. 2025)は、標準的なプロンプティングの根本的な弱点に対処する。コンテキストが長くなるほど、モデルはプロンプト中央の重要情報を失いやすくなる(lost-in-the-middle効果)。ARQは複雑なクエリを複数の焦点化されたサブクエリに分解し、それぞれでコンテキストの特定部分へモデルの注意を向けることで、これを緩和する。
-
クエリ分解 :ユーザーの質問を、狭い側面をそれぞれ対象とする原子的なサブクエリに分ける。
-
注意を向けた検索 :各サブクエリについて、関連するコンテキストの一部分だけを検索または強調し、モデルがそこに注意を向けるようにする。
-
集約 :サブ回答を一貫した最終応答にまとめる。
これは長文書QA、大規模な検索結果集合に対するマルチホップ推論、コンテキストウィンドウに多数のツール出力が含まれるエージェント型タスクで特に有効である。ARQは、モデルがどのように推論するかだけでなく、どこを見るかを明示的に管理する、構造化されたchain-of-thoughtとみなせる。
ベストプラクティス:効果的なプロンプトの作成
文献の実証的知見と実務経験に基づくと、次の原則はプロンプトの品質を安定して高める。
Important
プロンプトエンジニアリングのチェックリスト
具体的かつ明確にする :「これを要約して」ではなく、「実行可能な発見に焦点を当て、各20語未満の箇条書き2〜3個で要約して」と書く。
説明するより示す :良い例1つは指示100語に値する。迷ったらfew-shot例を追加する。
出力形式を明示的に定義する :JSONスキーマ、箇条書き、表形式、正確な区切り文字などを指定する。形式を解釈任せにしない。
入力データに区切り文字を使う :ユーザー入力を明確な区切り文字(
"""、<input>...</input>、---)で囲み、指示とデータを分ける。役割を割り当てる :「あなたは[特定の振る舞い]をする[領域の専門家]です」と書くと、関連する知識と語調が引き出される。
してはいけないことを指定する :「推論を説明しない」「5項目を超えて出力しない」のような否定的制約は、肯定的制約より効果的なことが多い。
推論タスクにはchain-of-thoughtを加える :「一歩ずつ考えて」と追加するか、数学、論理、マルチホップ問題の解答例を与える。
温度を適切に制御する :事実的・決定的なタスクには\(T \approx 0\)、創造的・多様な出力には\(T \approx 0.7\)〜\(1.0\)を使う。
実証的に反復する :プロンプトをコードとして扱い、バージョン管理し、A/Bテストし、代表的な評価セットで性能を測る。
新近性バイアスを活用する :最も重要な指示と例をプロンプトの末尾(生成位置に最も近い場所)に置く。
| 失敗モード | 症状 | 解決策 |
|---|---|---|
| 指示忘却 | 長いプロンプトでモデルが制約を無視する | 制約を末尾に移す;重要な規則を繰り返す;システムプロンプトを使う |
| 形式のずれ | 生成が長くなると出力が正しい形式から崩れる | 制約付きデコーディングを使う;短い連鎖プロンプトに分ける |
| 迎合 | モデルがプロンプト内の誤った前提に同意する | 「誤りなら前提に異議を唱える」と追加する;システムレベルの指示を使う |
| 詳細の幻覚 | モデルが与えられたコンテキストにない事実を作る | 「不明なら分からないと言う」と追加する;出典を付けたRAGを使う |
| 拒否の過剰発動 | 安全学習のためモデルが無害な要求を拒否する | 正当な意図が明確になるよう言い換える;要求が適切な理由を明示的なコンテキストとして与える |
プロンプティングでよくある失敗モードと解決策。
Tip
プロンプトエンジニアリングの考え方
プロンプトエンジニアリングを自然言語によるプログラミングと考える。モデルは強力だが字義通りのインタープリターであり、学習分布から最もありそうな形に解釈して、求めたことをそのまま実行する。ソフトウェア工学の一般的な原則が適用できる。
DRY(Don’t Repeat Yourself) :長いコンテキストで注意の減衰と戦う場合を除き、同じことを繰り返さない
関心の分離 :役割、制約、例、入力をプロンプトの別々のセクションにする
テスト駆動開発 :プロンプトを書く前に期待する出力を定義する
バージョン管理 :プロンプトの反復と評価スコアを追跡する
モジュール性 :再利用可能なプロンプトテンプレートを作り、可変部分をパラメータ化する
体系的に反復してもプロンプティングで望ましい品質に達しないなら、ファインチューニング(SFT)や強化学習(RLHF/DPO)へ移る合図である。
モデル圧縮手法
モデル圧縮は品質を保ちながら、モデルサイズと推論コストを削減する。主なアプローチは3つある。量子化(精度を下げる)、刈り込み(パラメータを削除する)、蒸留(大きなモデルを模倣する小さなモデルを学習する)である。
量子化
量子化は、重み(必要に応じて活性値も)をより低精度の形式で表現し、モデルサイズと推論コストを削減する。中心となるトレードオフは、圧縮率と品質低下のバランスである。
Important
量子化の概要
量子化は、モデルの重み(必要に応じて活性値も)の数値精度をFP32/BF16から低ビット形式へ下げる。 \[ x_q = \text{round}!\left(\frac{x - z}{s}\right), \quad x_{\text{dequant}} = s \cdot x_q + z \] ここで\(s\)はスケール係数、\(z\)はゼロ点である。
| 手法 | ビット数 | 種類 | 主な考え方 |
|---|---|---|---|
| GPTQ (Frantar et al. 2023) | 4-bit | PTQ、重みのみ | 最適脳外科法により、\(\\vert WX - \hat{W}X\\vert ^2\)を最小化する層単位の量子化。 |
| AWQ (Lin et al. 2024) | 4-bit | PTQ、重みのみ | 重要な重み(活性値が大きいもの)を保護する。重みの1%が重要度の99%を担う。 |
| GGUF (Gerganov 2023) | 2〜8 bit | PTQ、重みのみ | CPU最適化形式(llama.cpp)。複数の型を使うブロック単位の量子化。 |
| FP8 (E4M3) | 8-bit | 学習+推論 | H100がネイティブにサポートする。BF16に対してスループット2\(\times\)。 |
| SmoothQuant (G. Xiao et al. 2023) | W8A8 | PTQ、重み+活性 | 量子化前に活性値の外れ値を重みへ滑らかに移す。INT8 GEMMを可能にする。 |
| QAT (Z. Liu et al. 2023) | 4-bit | QAT | 量子化をシミュレートしながら学習する。品質は最高だが高コスト。 |
| AQLM (Egiazarian et al. 2024) | 2-bit | PTQ、加法コード | 学習された加法量子化コードブックにより極端な圧縮を実現する。 |
LLMの量子化手法。
Tip
量子化するタイミング
推論サービング :常に量子化する。W4A16(4-bit重み、BF16活性値)が最適点で、70B以上のモデルではメモリを2\(\times\)削減し、品質低下は\(<\)1%に抑えられる。
学習 :H100上のFP8は品質をほとんど損なわずスループットを2\(\times\)にする。小規模モデルでは現在もBF16がデフォルトである。
エッジ展開 :民生ハードウェアでのローカル推論にはGGUF Q4_K_Mを使う。
RLHF :凍結したモデル(参照モデル、報酬モデル)をINT8/FP8へ量子化する。学習精度のため、方策はBF16のままにする。
刈り込み
なぜ刈り込むのか?
現代のLLMは数十億のパラメータを持つが、実証研究は一貫して、その大部分の重みがモデル出力にほとんど寄与しないことを示している。刈り込みはこの過剰パラメータ化を利用する。冗長な重みを削除することで、 メモリフットプリント (小さなGPUやエッジデバイスへの展開を可能にする)、 推論レイテンシ (順伝播ごとの積和演算を減らす)、 サービングコスト (1ドルあたりのスループットを高める)を削減する。全重みの精度を一様に下げる量子化とは異なり、刈り込みは重みを選択的に除去するため、量子化と組み合わせると乗算的な削減が可能になる(例えば50%スパースな4-bitモデルは、密なBF16ベースラインよりメモリ使用量が\(4\times\)少ない)。生成品質を損なわずに高いスパース性を達成することが課題であり、再学習を必要としない原理的な一括手法の開発につながった。
Important
刈り込み手法
非構造化刈り込み :しきい値未満の個々の重みをゼロにする。高いスパース性(50〜90%)が可能。スパースGEMMカーネル(A100/H100では2:4)が必要。
構造化刈り込み :アテンションヘッド、層、FFNニューロンを丸ごと削除する。特殊なカーネルなしにFLOPSを直接削減できる。
SparseGPT (Frantar and Alistarh 2023:近似逆ヘッセ行列を使う一括刈り込み。175Bモデルで品質をほとんど損なわず50%の非構造化スパース性を実現する。
Wanda (Sun et al. 2024:\(\vert w\vert \times \\vert x\\vert\)(重みの大きさと入力活性値ノルムの積)で刈り込む。キャリブレーションデータは不要で、SparseGPTと競合する。
Warning
NVIDIAの2:4構造化スパース性
A100/H100のTensor Coreは2:4スパース性をネイティブにサポートする。4要素ごとに、非ゼロなのは最大2つである。対応する演算ではハードウェアアクセラレーションにより、正確に2\(\times\)の高速化が得られる。制約は、この特定のパターンでちょうど50%のスパース性を達成しなければならず、任意のスパース性に比べて柔軟性が低いことである。
知識蒸留
知識蒸留(Hinton et al. 2015)は、大きな教師モデルが学習した振る舞いを、より小さく安価な生徒モデルへ移す。中心的な考え方は、教師のトークン上の出力分布が、正解のハードラベルだけよりはるかに豊かな信号を持つことである。クラス間の類似性、キャリブレーション、不確実性が明らかになり、生徒はこれらを利用できる。
温度スケールsoftmax
教師のロジットに含まれる「暗黙の知識」を引き出すため、温度\(T > 1\)で分布を軟化する。
\[ p_i^{(T)} = \frac{\exp(z_i / T)}{\sum_j \exp(z_j / T)} \]
高い温度では確率質量がより多くのトークンへ広がり、惜しい代替候補が見えるようになる。学習中は生徒にも同じ温度を適用し、推論時には生徒が\(T=1\)を使う。
一般的な蒸留損失
\[ \mathcal{L}_{\text{distill}} = \alpha , T^2 \cdot \text{KL}!\bigl(P_{\text{teacher}}^{(T)} ;|; P_{\text{student}}^{(T)}\bigr) ;+; (1-\alpha) \cdot \mathcal{L}_{\text{CE}}(y, P_{\text{student}}^{(1)}) \]
\(T^2\)の因子は、軟化された分布で勾配の大きさが小さくなることを補償する。典型的な値は\(T \in [2, 20]\)、\(\alpha \in [0.5, 0.9]\)である(教師の品質が高いほどKLに大きな重みを置く)。
| パラダイム | 仕組み | 長所 | 短所 |
|---|---|---|---|
| オフライン/ホワイトボックス | 教師のロジットを事前計算し、生徒は完全な分布で学習 | 分布全体の信号;教師コストは一度だけ | データが古くなる;ストレージを大量に消費 |
| オンライン/協調学習 | 教師がオンザフライで生成し、生徒は新しいロジットを見る | 生徒の弱点に適応 | 計算量が\(2\times\);インフラが複雑 |
| ブラックボックス(API) | 教師のテキスト出力だけ利用可能(ロジットなし) | 独自モデルでも動作 | 暗黙の知識を失う;SFTに近い |
| 自己蒸留 | モデル自身の小さい版へ蒸留 | 別の教師が不要 | 教師は同じモデル系列;性能上限がある |
LLMの知識蒸留パラダイム。
オフライン(ホワイトボックス)蒸留
各学習トークンについて、教師の完全なロジットベクトル(またはストレージ効率のためtop-\(k\)ロジット)を記録する。生徒は保存された分布に対するKLダイバージェンスを最小化する。教師へ自由にアクセスできる場合、これは最もデータ効率のよいパラダイムである。
動機 :教師の推論と生徒の学習を分離する。高性能ハードウェアで教師を一度実行し、その後、多数の生徒を安価に学習する。
長所 :決定的で再現可能。教師のコストを償却でき、分布全体の信号を利用できる。
短所 :トークンごとに\(\vert V\vert\)次元のベクトルを保存する必要がある(top-\(k\)刈り込みで緩和可能)。教師は生徒の失敗に適応できない。
オンライン(協調学習)蒸留
教師と生徒を同時に実行し、教師が生徒の現在の学習バッチに対するロジットを生成する。
動機 :教師が、生徒が現在苦手としている入力に集中できるようにする(カリキュラムに似た仕組み)。
長所 :新鮮な信号を得られ、生徒が生成した入力をオンポリシー蒸留に使える。
短所 :GPUコストが倍になる。同期間の複雑さがあり、スケールしにくい。
ブラックボックス(API)蒸留
テキスト出力だけが利用可能な場合(例えば独自APIから蒸留する場合)、生徒を教師の生成結果に対するSFTで学習し、必要に応じてchain-of-thoughtの軌跡を加える。
動機 :実務上の現実として、最先端モデルの大半はロジットを公開していない。
長所 :パイプラインが単純で、APIの背後にある任意のモデルで動作する。
短所 :ソフトラベルの信号がない。幻覚を増幅しやすく、実質的には教師ありファインチューニングである。
自己蒸留
同じアーキテクチャ系列のより大きな版(例えばLlama-3 70B \(\to\) 8B)から、または学習中の自分自身のチェックポイントから蒸留する。
動機 :別の教師を学習する必要をなくし、異なる規模におけるモデル自身の能力を利用する。
長所 :アーキテクチャの互換性があり、外部依存がない。
短所 :教師の上限がモデルの上限と等しく、本当に新しい知識は導入できない。
Tip
暗黙の知識
「The capital of France is」の次の単語を予測する言語モデルを考える。ハードラベルでは「Paris」だけが正解だとする。しかし教師のソフト分布は「Lyon」に5%、「Marseille」に2%、「banana」にほぼ0%を割り当てるかもしれない。これは生徒にどの誤りが妥当かを伝え、キャリブレーションと一般化を大きく改善する。
LLM蒸留の実践的考慮事項
-
系列レベルとトークンレベル :トークンレベルのKLが標準である。系列全体でKLを最小化する系列レベル蒸留は長距離の一貫性をよりよく捉えるが、最適化は難しい。
-
層ごとのヒント :中間表現(アテンションマップ、隠れ状態)を一致させると追加の学習信号が得られる。生徒のアーキテクチャが異なる場合に特に有用である。
-
データ選択 :蒸留データの品質は重要である。多様で難しい例を選ぶ方が、ランダムサンプリングよりよい生徒を生む。
-
生徒の容量 :教師パラメータの\(\sim\)10%未満では収穫逓減が起きる。極端な圧縮では、アーキテクチャの変更(例えばMoE \(\to\)密結合)が必要になる場合がある。
-
量子化との組み合わせ :蒸留と4-bit量子化(例えばQLoRA蒸留モデル)により、\(20\times\)圧縮で教師に近い品質を達成できる。
Note
圧縮手法の比較——70Bモデル
手法 サイズ 速度 品質 用途 BF16(ベースライン) 140 GB 1\(\times\) 100% 学習、参照 FP8(E4M3) 70 GB 2\(\times\) 99.5% H100推論 INT8(SmoothQuant) 70 GB 1.8\(\times\) 99% A100推論 4-bit(AWQ) 35 GB 2.5\(\times\) 97〜98% 大規模サービング 2-bit(AQLM) 17.5 GB 3\(\times\) 90〜93% エッジ、実験 50%刈り込み(2:4) 70 GB 1.8\(\times\) 97% 構造化高速化 蒸留8B 16 GB 10\(\times\) 80〜85% モバイル、エッジ
投機的デコーディング手法
投機的デコーディング(Leviathan et al. 2023)は、複数のトークンを同時に予測し、対象モデルの1回の順伝播で検証することで自己回帰生成を高速化する。標準デコーディングと 同一の出力分布 (品質低下なし)を保ちながら、2〜3\(\times\)の高速化を達成する。
基本原理
Important
投機的デコーディングの枠組み
高速な ドラフト機構 が\(k\)個の候補トークン\(\hat{x}_1, \ldots, \hat{x}_k\)を提案する。
大きな 対象モデル が\(k\)個すべてのトークンに対して1回の順伝播を行う(バッチ処理)。
検証 :\(P_{\text{target}}(\hat{x}_i) \geq r_i \cdot P_{\text{draft}}(\hat{x}_i)\)である間、左から右へトークンを受理する(\(r_i \sim U[0,1]\))。
位置\(j\)で初めて拒否したら、調整済み分布から\(x_j\)を再サンプリングし、\(\hat{x}_{j+1}, \ldots, \hat{x}_k\)を破棄する。
重要な性質 :この受理/拒否方式により、最終分布が厳密に\(P_{\text{target}}\)と等しくなることが保証される。
高速化 :受理率が\(\alpha\)なら、1ステップあたりの期待トークン数は\(\frac{1 - \alpha^{k+1}}{1 - \alpha}\)である。\(\alpha=0.8\)、\(k=5\)では、標準デコーディングの1トークンに対して1ステップあたり3.4トークンが期待される。
手法の比較
| 手法 | ドラフトの供給元 | 高速化 | 主な考え方 |
|---|---|---|---|
| 標準 (Leviathan et al. 2023) | 小規模モデル(1〜7B) | 2〜3\(\times\) | 別のドラフトモデルが候補を生成する。単純だが2つのモデルを読み込む必要がある。 |
| Medusa (Cai et al. 2024) | 並列LMヘッド | 2〜3\(\times\) | 対象モデルに\(k\)個の予測ヘッドを追加する。各ヘッドが\(+1, +2, \ldots, +k\)の位置のトークンを予測する。 |
| Eagle (Li et al. 2024) | 特徴レベル | 2.5〜3.5\(\times\) | 軽量デコーダが対象モデルの隠れ状態からドラフトトークンを生成する。Medusaより受理率が高い。 |
| Eagle-2 (Li et al. 2024) | コンテキスト対応 | 3〜4\(\times\) | 信頼度に基づき拡張する動的ドラフト木。最先端の受理率。 |
| N-gram Lookup | N-gramキャッシュ | 1.5〜2\(\times\) | プロンプトのn-gramを過去に生成したテキストと照合する。コストゼロで、反復的な出力に適する。 |
| Lookahead (Yichao Fu et al. 2024) | Jacobi反復 | 2〜2.5\(\times\) | n-gram検証を伴う並列Jacobiデコーディング。ドラフトモデルは不要で、対象モデル自体を使う。 |
| Multi-token (Gloeckle et al. 2024) | 変更アーキテクチャ | 2〜3\(\times\) | 1ステップで複数トークンを本来の機能として予測するようモデルを学習する(LlamaにおけるMetaの方式)。 |
現代の推論エンジンがサポートする投機的デコーディング手法。
Medusa:マルチヘッド投機的デコーディング
Important
Medusaの仕組み
MedusaはLLMに\(k\)個の追加「予測ヘッド」を加える(同じバックボーンを共有する)。
ヘッド0(元のヘッド):位置\(t+1\)のトークンを予測する(標準的な次トークン予測)
ヘッド1:位置\(t+2\)のトークンを予測する(1つ飛ばす)
ヘッド\(i\):位置\(t+i+1\)のトークンを予測する
すべてのヘッドを1回の順伝播で並列に実行する
木構造の 検証により、複数の候補系列を同時に検証する
学習 :Medusaヘッドだけをファインチューニングする(バックボーンは凍結)。コストは代表的なデータで\(\sim\)1エポック。
利点 :別のドラフトモデルが不要で、ヘッドは小さい(各1線形層)。メモリオーバーヘッドは\(<\)1%。
Eagle:特徴レベルのドラフティング
Tip
EagleがMedusaを上回る理由
Medusaのヘッドは各位置を独立に予測するため、自身の過去の予測を条件にできない(\(t+2\)のトークンは\(t+1\)で何が予測されたかを知らない)。Eagleは、対象モデルの隠れ状態上で動作する軽量な自己回帰デコーダによってこれを解決する。
対象モデルの最終層から隠れ状態を抽出する。
小さな(1層の)デコーダへ入力し、過去の隠れ状態を条件として自己回帰的にドラフトトークンを生成する。
これにより、Medusaが捉えられないトークン間依存を捉える。
結果:Eagleの受理率は85〜95%で、Medusaの60〜80%を上回る。
N-gram投機的デコーディング
Important
N-gram Lookup法
最も単純な投機的デコーディングであり、追加のモデルも学習も必要としない。
プロンプトと過去に生成したテキストのn-gramキャッシュを維持する。
各ステップで、現在のコンテキストの最後の\(n-1\)トークンがキャッシュ済みのn-gramと一致するか確認する。
一致すれば、その続きのトークンをドラフトとして提案する。
通常どおり対象モデルに対して検証する。
適した用途 :コード生成(反復パターン)、構造化出力(JSON/XML)、要素が繰り返されるプロンプト。 コスト :実質ゼロ。
vLLMとの統合
from vllm import LLM, SamplingParams
# Standard speculative decoding (separate draft model)
llm = LLM(
model="meta-llama/Llama-3-70B",
tensor_parallel_size=4,
speculative_config={
"model": "meta-llama/Llama-3-8B",
"num_speculative_tokens": 5,
},
)
# N-gram speculation (zero-cost, no draft model needed)
llm = LLM(
model="meta-llama/Llama-3-70B",
speculative_config={
"method": "ngram",
"num_speculative_tokens": 5,
"prompt_lookup_max": 4, # Match up to 4-grams from prompt
},
)
# EAGLE-style (feature-level draft, high acceptance rate)
llm = LLM(
model="meta-llama/Meta-Llama-3-8B-Instruct",
tensor_parallel_size=4,
speculative_config={
"model": "yuhuili/EAGLE-LLaMA3-Instruct-8B",
"num_speculative_tokens": 2,
"method": "eagle",
"draft_tensor_parallel_size": 1,
},
)
# MLP speculator (IBM-style, lightweight head)
llm = LLM(
model="meta-llama/Meta-Llama-3.1-70B-Instruct",
tensor_parallel_size=4,
speculative_config={
"model": "ibm-ai-platform/llama3-70b-accelerator",
"draft_tensor_parallel_size": 1,
},
)
Warning
投機的デコーディングを使わない場面
大きなバッチサイズ :バッチが\(\geq 64\)では、生成はすでに計算効率がよい。投機ではオーバーヘッド(ドラフト生成+検証)が加わり、効果が得られない。
分布が大きく異なる場合 :ドラフトモデルが対象モデルと大きく異なると、受理率が50%未満に下がり、投機の方が標準デコーディングより遅くなる。
短い出力 :\(<\)20トークンの出力では、投機のセットアップコストが節約分を上回る。
経験則 :投機は、レイテンシが重要な単一ストリーム生成(チャットボット、対話的なコード補完)で最も有効である。
ハルシネーション検出
LLMは流暢だが事実として誤ったテキストを生成することがあり、これは ハルシネーション と呼ばれる(Ji et al. 2023)。この節では、外部検索やマルチエージェント検証を使わず、モデルレベルで検出する基本手法を扱う。
ハルシネーションの種類
Important
ハルシネーションの分類
内在的 :与えられた入力/コンテキストと矛盾する(例えば要約が原文と反対のことを述べる)。
外在的 :入力から検証できず、事実として誤った主張を生成する。
忠実性 :出力が指示や指定された制約から逸脱する。
検出手法(モデルレベル)
| 手法 | 仕組み | シグナル |
|---|---|---|
| トークンレベルのエントロピー | 生成時の高いエントロピーは不確実性を示す(Kadavath et al. 2022) | \(H(P(x_t)) > \tau\) |
| 系列対数確率 | 出力の平均対数確率が低いと、作話が示唆される | \(\frac{1}{T}\sum_t \log P(x_t)\) |
| 一貫性サンプリング | \(N\)個の応答を生成し、一致度が低ければ\(=\)ハルシネーションの可能性が高い(Manakul et al. 2023) | 矛盾率 |
| 意味エントロピー | 文字列ではなく意味をクラスタ化し、意味エントロピーが高ければ\(=\)不確か(Kuhn et al. 2023) | クラスタの多様性 |
| DoLA | 後段と前段の層のロジットを対照し、事実知識を増幅する(Chuang et al. 2024) | 層間の乖離 |
モデルレベルで動作する基本的なハルシネーション検出手法。
意味エントロピー
Kuhnら(Kuhn et al. 2023)は、トークンレベルのエントロピーは信頼できないと観察した(言い換えはトークンが異なっても同じ意味を持つ)。そこで複数の応答を生成し、意味的同値性(NLIによる)でクラスタ化し、意味クラスタ上のエントロピーを計算する。
\[ SE = -\sum_{c \in \text{clusters}} P(c) \log P(c) \]
SEが高いとは、モデルが意味的に異なる答えを生成しているということであり、ハルシネーションの強いシグナルとなる。
SelfCheckGPT
Manakulら(Manakul et al. 2023)は、自己一貫性を確認してハルシネーションを検出する。複数の応答を生成し、主応答の主張が別の応答によって支持されるか検証する。モデルが「自分自身と意見が食い違う」なら、その主張はハルシネーションである可能性が高い。外部知識は不要である。
DoLA(層の対照によるデコーディング)
Chuangら(Chuang et al. 2024)は、事実知識がTransformerの後段の層に現れる一方、前段の層にはより一般的で不確かな表現が残ると観察した。DoLAは各デコーディングステップで、後段の「成熟した」層と前段の「未成熟な」層のロジット分布を対照する。
\[ \text{DoLA}(x_t) = \text{softmax}!\bigl(\log P_{\text{late}}(x_t) - \log P_{\text{early}}(x_t)\bigr) \]
DoLAは深い層に符号化された事実知識の信号を増幅することで、再学習なしに推論時のハルシネーションを減らす。必要なのは対照する層を通る追加の順伝播1回だけである。サンプリングベースの手法を補完し、それらと組み合わせられる。
Warning
モデルレベル検出の限界
これらの手法が検出するのは不確実性であって、誤りではない。モデルは確信を持って誤ることがある(エントロピーが低く、応答も一貫しているが、事実として誤っている)。信頼できる検出には、検索ベースの検証(RAG)や外部ファクトチェックツールを組み合わせる。
LLMの安全性と責任あるAI
安全性は後付けではなく、LLM学習パイプラインの不可欠な一部である。この節では、LLMの安全性に関する主要な側面と、責任ある振る舞いを実施する仕組みを扱う。
脅威の分類
| カテゴリ | 説明と例 |
|---|---|
| 有害なコンテンツ | 毒性、暴力、違法行為に関する指示を生成する(生物兵器、CSAMなど) |
| バイアスと差別 | 固定観念を助長し、人口集団間で不公平に扱う(Gallegos et al. 2024) |
| プライバシー侵害 | 学習データからPIIを漏えいさせる;記憶化攻撃(Carlini et al. 2021) |
| ジェイルブレイク | 安全ガードレールを回避する敵対的プロンプト(Zou et al. 2023) |
| 誤情報 | 説得力はあるが偽の主張を生成する(大規模なハルシネーション) |
| デュアルユース | 正当な能力(コーディング、化学)が害のために悪用される |
LLMの安全性に関する脅威のカテゴリ。
安全性学習パイプライン
主な安全性メカニズム
Important
安全性の技法
データフィルタリング :事前学習コーパスから、毒性、バイアス、PIIを含むテキストを除去する。
安全性SFT :適切な拒否の例(「その理由ではお手伝いできません……」)で学習する。
Constitutional AI (Bai et al. 2022:原則を使って自己批評し、規則の憲法に照らして自分の出力を修正する。
安全性報酬モデル :安全性の注釈付きペアで別のRMを学習し、RLHF中に有用性RMと重み付き和で組み合わせる。
ガードレール :サービング時に有害な要求や応答を遮断する入力/出力分類器。
レッドチーミング (Perez et al. 2022:展開前に失敗モードを見つける体系的な敵対的評価。
有用性と安全性のトレードオフ
Tip
有用性と安全性のバランス
安全性を過度に最適化すると、過剰拒否の問題が生じる。モデルが無害な要求を拒否してしまうためである(例えば教育的な文脈で歴史上の暴力について議論することを拒否する)。目標は、安全性の制約内で最大限に有用なパレート最適方策である。 \[ \max_\theta ; \mathbb{E}[R_\text{helpful}] \quad \text{subject to} \quad \mathbb{E}[R_\text{safety}] \geq \tau \] 実際には、\(R = \alpha R_\text{helpful} + (1-\alpha) R_\text{safety}\)という重み付き報酬として実装し、\(\alpha\)(通常0.6〜0.8)を慎重に調整する。MetaのLlama-3は、マージンベースの重み付けを用いて安全性と有用性に別々の報酬モデルを使うと報告している(Grattafiori et al. 2024)。
評価
-
安全性ベンチマーク :ToxiGen、RealToxicityPrompts、BBQ(バイアス)、CrowS-Pairs
-
ジェイルブレイクへの頑健性 :GCG攻撃(Zou et al. 2023)、マルチターンのジェイルブレイク、エンコードされたプロンプト
-
過剰拒否率 :無害なプロンプトに対する誤検知の拒否を測定する(目標\(<\)5%)。
-
レッドチーム評価 :領域専門家(バイオセキュリティ、サイバーセキュリティ)による人手の敵対的テスト
Warning
安全性に終わりはない
どのような技法の組み合わせでも絶対的な安全性は得られない。新しい攻撃経路は継続的に発見される(マルチモーダルなジェイルブレイク、安全性学習を除去するファインチューニング攻撃、多数ショットプロンプティングなど)。安全性には継続的な監視、新たな脅威への迅速な対応、多層防御(複数の独立した層)が必要である。