Decoding Strategy(出力戦略)
LLM のトークン選択を決定的 (Greedy/Beam) と確率的サンプリング (T/Top-k/Top-p) と出力モード (Streaming/Non-Streaming) の三軸で整理、合成順序と 5 大ピットフォールを定義。
article technology ja LLM のトークン選択を決定的 (Greedy/Beam) と確率的サンプリング (T/Top-k/Top-p) と出力モード (Streaming/Non-Streaming) の三軸で整理、合成順序と 5 大ピットフォールを定義。Decoding Strategy(出力戦略)
LLM の「次トークン生成」は決定的デコーディング (Greedy / Beam Search)、確率的サンプリング (Temperature / Top-k / Top-p)、出力モード (Streaming / Non-Streaming) の三軸で決まる。本記事はトークン選択と出力配信に集中し、KV キャッシュ管理は tech-43、TTFT/TPOT/ITL 指標は tech-44、Prefill/Decode 分解は tech-45、量子化・投機的デコードは tech-46、注意機構は tech-38、Transformer は tech-35 を参照。
決定的デコーディング(Deterministic Decoding)
貪欲法(Greedy Decoding)
各ステップで y_t = argmax_v softmax(z_t)_v を取る最小実装。同一入力で常に同一出力を返し、ハイパーパラメータは max_new_tokens のみ。HF Transformers は do_sample=False, num_beams=1 で既定有効、vLLM は SamplingParams(temperature=0)、OpenAI/Anthropic API は temperature=0 で実質貪欲。典型的失敗: 繰り返しペナルティ無しで「the the the…」型の縮退ループ (高確率トークンが直前のトークンに引き戻されるため)、多様性が無いため創作・チャット用途で機械的な出力。実用: JSON モード、CI 評価の再現性、コード生成の syntax 厳密性、分類・抽出タスクなど多様性不要な場面。
ビームサーチ(Beam Search)
各ステップで K 個の仮説を保持し、累積対数尤度 Σ log P(y_i | y_<i, x) で上位 K を残す。長さペナルティは Wu et al. 2016 (Google NMT, https://arxiv.org/abs/1609.08144) の Score / ((5 + |y|) / 6)^α で α ∈ [0.6, 1.0] が典型。多様性崩壊問題: Holtzman et al. 2020「The Curious Case of Neural Text Degeneration」(ICLR 2020, https://arxiv.org/abs/1904.09751) は beam の出力が greedy とほぼ同一に収束することを実証 — 全ビームが最尤プレフィックスの周辺に密集し、open-ended 生成では beam を増やしても fluent だが generic で繰返しの多い文しか出ない。用途: NMT、短い要約、k-best ランキング必要な構造化出力。HF では do_sample=True と num_beams>1 は相互排他で ValueError、計算量 O(K·V) で K=8 なら 8 倍遅い。LLM チャットでは既定でほぼ非採用。
確率的サンプリング(Stochastic Sampling)
温度スケーリング(Temperature)
softmax 適用前にロジットを T で除算: P_T(v) = softmax(z / T)_v。T → 0 で argmax (貪欲)、T = 1 は素の分布、T < 1 でシャープ化、T > 1 で平坦化 (多様性増、インコヒーレンスのリスク)。源流は Hinton et al. 2015 (https://arxiv.org/abs/1503.02531) の soft target、統計力学の Boltzmann 分布。既定: OpenAI/Anthropic/HF/vLLM とも temperature=1.0、llama.cpp は --temp 0.8。典型レンジ: チャット 0.7–1.0、創作 1.0–1.5、コード 0.0–0.3。
Top-k サンプリング
上位 K 個のトークンのみ残し残りを -∞ にマスクして再正規化、カテゴリカル分布からサンプリング。論文: Fan et al. 2018 (ACL 2018, https://arxiv.org/abs/1805.04833)。典型値: HF top_k=50、vLLM top_k=-1 (無効)、llama.cpp --top-k 40、Anthropic は top_k 対応。弱点: K が分布形状に追従しない — 分布が既に尖っている (top-1 が 0.9) 場合でも残り 49 個の低確率トークンも候補に入る。Top-p が後継として提案された理由。K=1 は実質 greedy。
核サンプリング(Top-p / Nucleus Sampling)
確率降順にソートし、累積確率が p を超えた最小集合 V_p だけ残しサンプル: V_p = argmin{|V| : Σ_{v∈V} P(v) ≥ p}。論文: Holtzman et al. 2020 (ICLR 2020, https://arxiv.org/abs/1904.09751)。Top-k と違い候補数が分布形状に動的適応 — 尖った分布で 1〜3 個、平坦分布で数百個。既定: OpenAI/Anthropic/HF とも top_p=1.0 (実質無効)、vLLM 同じだが本番 0.9–0.95 が定石、llama.cpp --top-p 0.95。事実上の標準: temperature=0.7–1.0 × top_p=0.9–0.95 がチャット LLM の本番既定。
その他の手法(Min-p / Typical-p / Mirostat)
Min-p (Nguyen et al. 2024, https://arxiv.org/abs/2407.01082): P(v) ≥ p_min × max_v P(v) で最頻トークンに対する相対比で残す — Top-p が高温で低確率 noise を大量に含む問題を緩和、llama.cpp --min-p 0.05。Mirostat (Basu et al. 2021, https://arxiv.org/abs/2007.14966): クロスエントロピーを目標値に保つフィードバック制御、llama.cpp --mirostat 2。Typical-p (Meister et al. 2023): 情報理論的、本番採用は限定的。
繰り返しペナルティ(Repetition / Presence / Frequency)
Repetition penalty (Keskar et al. 2019 CTRL, https://arxiv.org/abs/1909.05858): 既出トークンを P / penalty で減衰、典型 1.0–1.3、1.5 超で文体硬直化。Presence penalty (OpenAI): 既出ならバイナリで固定加算 logit[v] -= presence_penalty。Frequency penalty (OpenAI): 出現回数比例 logit[v] -= frequency_penalty × count(v)。繰り返しループ脱出には frequency 側、話題多様化には presence 側が効きやすい。HF の LogitsProcessorList では RepetitionPenalty が Top-p/Top-k の前に適用されるため、ペナルティ後分布で核を切り出す。ペナルティが強いと既に核内の頻出語が脱落 (P3 の元ネタ)。
サンプリング合成とパラメータ順序
HF Transformers / vLLM の標準合成順序:
ロジット z
↓ 温度除算 (z / T)
↓ Top-k マスク (上位 K 以外を -∞)
↓ Top-p マスク (核外を -∞)
↓ 繰り返し/Presence/Frequency ペナルティ (実装で位置変動)
↓ softmax → Categorical sampling
HF LogitsProcessorList 既定は Temperature → TopK → TopP → RepetitionPenalty。vLLM SamplingParams も同フィールド順。温度ゼロでは Top-k/Top-p は実質無効 — argmax が決まれば 1 トークンの確率質量が 1.0 となり追加マスクが効かないため、temperature=0, top_p=0.9 は単に貪欲と等価 (P1 の元ネタ)。
出力モード(Output Mode)
逐次出力(Streaming)
生成された各トークンをサンプリング直後にクライアントへ push する伝送形態。伝送機構: SSE (text/event-stream、サーバ→クライアント単方向、OpenAI/Anthropic 採用)、WebSocket (双方向、リアルタイム UI)、gRPC server streaming (vLLM generate_stream)、HTTP Chunked Transfer Encoding。HTTP/2 多重化で SSE の HoL ブロックを緩和。UX: 知覚上の TTFT が体感即応化 (LLM の TPOT 30〜80 ms/tok は人の読速 ~250 tok/min を上回り、streaming 時のみ可視化)、progressive 描画、誤生成の早期 abort、TPOT/ITL が直接 SLO に紐づく。デコーディングとの相互作用: Greedy/T/Top-k/Top-p は完全互換。Beam search × streaming は原理的に困難 — beam は全 K 仮説を完成後にスコアして 1 系列を確定するため、途中送信は後で pruning される。OpenAI/Anthropic stream=True、vLLM (HTTP SSE + gRPC)、HF TGI (/generate_stream)。
一括出力(Non-Streaming)
完全な生成系列を 1 レスポンスボディで返却する古典的 request/response。選好理由: ① トークン使用量の確定値が完成後にしか出ないため課金ログがシンプル、② JSON モード/構造化出力で atomic にパースでき部分パースの複雑性が無い、③ コンテンツモデレーション分類器が完成テキスト前提、④ Beam search との相性、⑤ オフラインバッチ推論、⑥ レスポンスのコンテンツハッシュキャッシュが可能 (streaming は不可)。落とし穴: HTTP gateway timeout (ALB 60 s、nginx 75 s) を長生成が超過 — streaming へ切替えるか timeout を引き上げる。
5 大ピットフォール
tech-43 はバッチング、tech-44 は指標、tech-45 はフェーズ、tech-46 は加速の各観点を担い、本記事はトークン選択と出力モードの観点で重複なく定義する。
P1: temperature=0 と top_p<1 を同時設定して効くと信じる — T=0 は argmax を取るため top-1 の確率質量が 1.0 となり、top_p の核フィルタは何もマスクしない (1 個でカバー率 ≥ p)。temperature=0, top_p=0.9 は単に貪欲。top_p を活かしたいなら T > 0 (典型 0.7–1.0) と組合せる。
P2: Beam search とサンプリングを同時に有効化 — HF では do_sample=True かつ num_beams>1 は ValueError、両者は実装的にも理論的にも相互排他。Open-ended 生成では Holtzman 2020 通り beam は多様性に寄与せず、T/top_p 経由の確率的多様化が標準。Beam search は NMT/短要約など決定的目標が明確なタスクに用途を絞る。
P3: 繰り返しペナルティを Top-p の前に適用する効果を見落とす — HF の既定順序が RepetitionPenalty → TopK → TopP のため、ペナルティ後分布から核を切り出す。ペナルティが強い (>1.3) と既出頻出語が核から脱落し候補集合が突然狭まる。中庸 (1.1–1.3) を起点に A/B 評価する。Frequency penalty はループ脱出、presence penalty は話題多様化で効きどころが異なる点も混同しやすい。
P4: ストップ列と EOS トークンの違いを設計から落とす — stop は生成テキストへの文字列マッチ、<eos> はモデルが内生的に出すトークン。ストップ列で停止しても EOS 未出 (モデル視点では未完了) のケースがあり、ストリーミング受信側で「最後の partial token」がストップ列の一部を含むと UI 表示が乱れる。クライアント側でストップ列 strip と EOS 検知を両方実装し、サーバから finish_reason (stop / length / tool_calls / content_filter) を必ず返す API 設計にする。
P5: JSON モード/構造化出力で temperature=0 + logit_bias を素朴に組合せる — logit_bias で特定トークンを -∞ に押し下げると、T=0 では残候補での argmax がループしやすく、無限「{」連発や同一 key の繰返しに陥ることがある。構造化出力は制約付きデコーディング (logit マスキング+文法駆動) に委譲し、logit_bias は微調整用と割り切る。
制約付きデコーディング(Structured Output)
JSON モード、関数呼び出し、正規表現/EBNF 文法準拠は、各ステップで「文法上 valid なトークン」のみロジットで許可する logit masking として実装される。Outlines (Willard & Louf 2023, https://arxiv.org/abs/2307.09702) は正規表現/JSON Schema から FSM を構築し vLLM/HF に統合、jsonformer は HF generate の wrapper で構造トークンは強制し値トークンのみサンプル、guidance は Python 制御フローと LLM 呼出のインターリーブ、lm-format-enforcer は vLLM/HF 両対応。OpenAI response_format (json_object / json_schema) も内部的に logit マスキング。投機的デコード (Medusa, EAGLE) は加速技術であり所掌外 — tech-46 を参照。
参考文献
- Wu et al. (2016). Google NMT. https://arxiv.org/abs/1609.08144
- Fan et al. (2018). Hierarchical Neural Story Generation. https://arxiv.org/abs/1805.04833
- Holtzman et al. (2020). The Curious Case of Neural Text Degeneration. https://arxiv.org/abs/1904.09751
- Keskar et al. (2019). CTRL. https://arxiv.org/abs/1909.05858
- Nguyen et al. (2024). Min-p Sampling. https://arxiv.org/abs/2407.01082
- Basu et al. (2021). Mirostat. https://arxiv.org/abs/2007.14966
- Hinton et al. (2015). Distillation. https://arxiv.org/abs/1503.02531
- Willard & Louf (2023). Outlines. https://arxiv.org/abs/2307.09702
- HF text generation strategies. https://huggingface.co/docs/transformers/generation_strategies
- vLLM SamplingParams. https://docs.vllm.ai/en/latest/dev/sampling_params.html
Related
Backlinks
- related Hallucination and Factuality(ハルシネーションと事実性)
- related LLM SDK App Development