
2026/10/11 7:50
独自の意思決定モデルを構築する
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
本研究の核心となる洞察は、言語モデルは単一パスの意思決定システムを模倣することは可能であるが、特定のカリブレーションが行われる限りでは、しばしば危険な過剰な自信を示すという点にある。標準的なモデルが複数のパスを通じて順次テキストを生成するのに対し、システムワンアプローチは制約付きデコーディング(例えば、選択肢 A〜E の語彙をマスキングする)を用いて、AI に固定されたオプションを 1 パスで選択させる。この手法は推論速度を向上させるが、信頼スコアの膨張というリスクをもたらす;具体的には、ネイティブ出力トークンの確率は次のトークンに対する自信を反映しており、正しい答えの真なる確率を反映していない。CommonsenseQA の保持サンプルでの評価では、ファインチューニングの後であっても未カリーブレーテッドなモデルは、明確な単一の答えが存在しない困難な Commonsense 問題に対して高い不確かさ(例:99.78%)を割り当てることができ、マクロ F1 精度は約 58%に留まり、高自信ビンに至っては単なる 70%に過ぎなかった。本研究では、LLM 模倣(Qwen/Qwen3-1.7B)における温度スケイリングを用いてこの問題を成功裏に解決し、モデルの報告された自信を実際の性能と数学的に整合させ、結果として適合温度が約 3.8 となった。したがって、制約付きデコーディングは標準化テストのような多選択タスクに対して効率的を提供するものの、その後のカリブレーションなしで展開することは、過剰な自信による誤りを招き、ユーザーを欺くことになる。今後、事前に定義された答えへの厳格な遵守が求められる適用においては、信頼性指標が真に信頼性を反映するように、事後処理ステップ(例えば温度スケイリング)の優先を確保する必要がある。
本文
「System One」決断モデルの実装と較正:Qwen3-1.7B を用いた検証
概要
System One(システム・ワン)とは、較正された確率値あるいは許容される全ての選択肢を出力するよう設計された決定型モデルのことです。
なぜ必要か?
日常的な言語モデルから JSON 形式の構造化された出力を得る場合、単なるプロンプトでは不十分であり、Structured Output を用いて有効な出力を強制する必要があります。
- モデルは入力に対して 1 つのパス(prefill)で埋めるが、有効な応答生成には各トークンごとにパスを実行する必要があるため、通常の生成では最終出力まで多くのパスを要します(例:11 パス)。
- これに対し、決断モデルは固定された選択肢から単一パスで選べることを前提としています。
実装手法:出力制限による挙動の模倣
LLM を用いて出力トークンのセットを制限することで、System One の振る舞いを模倣できます。ここでは Qwen/Qwen3-1.7B を使用して実装と検証を行います。
コードスニペット
以下の Python スクリプトにより、選択肢のみから推論を行い、確率分布を取得します。
import argparse import json import torch from transformers import AutoModelForCausalLM, AutoTokenizer model_name = "Qwen/Qwen3-1.7B" options = ["A", "B", "C", "D", "E"] parser = argparse.ArgumentParser() parser.add_argument("--input", default="question.json") args = parser.parse_args() # トークナイザーとモデルを読み込む tokenizer = AutoTokenizer.from_pretrained(model_name) model = AutoModelForCausalLM.from_pretrained( model_name, torch_dtype="auto", device_map="auto" ) # モデルが各選択肢に対して最初に発音するトークン ID option_token_ids = [tokenizer.encode(opt, add_special_tokens=False)[0] for opt in options] def format_prompt(item): prompt = item["question"] + "\n" for opt in options: prompt += f"{opt}. {item[opt]}\n" prompt += "Answer:" messages = [ {"role": "user", "content": prompt} ] return tokenizer.apply_chat_template( messages, tokenize=False, add_generation_prompt=True, enable_thinking=False ) with open(args.input) as f: item = json.load(f) model_inputs = tokenizer(format_prompt(item), return_tensors="pt").to(model.device) with torch.no_grad(): logits = model(**model_inputs).logits[0, -1] # 制約付きデコード:選択肢のトークンのみが許可される probs = torch.softmax(logits[option_token_ids].float(), dim=-1) print(f"予測結果: {options[probs.argmax().item()]}") for opt, prob in zip(options, probs.tolist()): print(f"{opt}: {prob:.4f} {item[opt]}")
テスト実行例(単純な質問)
入力データ:
{ "question": "空の色は何ですか?", "A": "赤色", "B": "青色", "C": "緑色", "D": "紫色", "E": "知りません" }
出力結果:
- 予測結果: B(青色)
- 確率分布:
- A: 0.0000, B: 0.9988, C: 0.0000, D: 0.0000, E: 0.0012
モデルは入力を正しく理解し、正解に対応する予測を行えています。
精度評価:公開データセットによるテスト
CommonsenseQA のランダムなサンプルホールドアウトに対し、未学習のモデルを実行した結果です。
1. ファインチューニング前の結果(ベースライン)
| 適合率 (precision) | 再現率 (recall) | F1 スコア | サポート数 | |
|---|---|---|---|---|
| A | 0.5733 | 0.7197 | 0.6382 | 239 |
| B | 0.5506 | 0.7686 | 0.6416 | 255 |
| C | 0.5372 | 0.6598 | 0.5922 | 241 |
| D | 0.7206 | 0.3904 | 0.5065 | 251 |
| E | 0.7519 | 0.4255 | 0.5435 | 235 |
- 全体精度: $725/1221 \approx 0.5938$
- マクロ F1 スコア: 0.5844
2. ファインチューニング後の結果
データセットに対する簡易なファインチューニングを行うことで性能が向上しました。
| 適合率 (precision) | 再現率 (recall) | F1 スコア | サポート数 | |
|---|---|---|---|---|
| A | 0.6475 | 0.6611 | 0.6542 | 239 |
| B | 0.6113 | 0.6784 | 0.6431 | 255 |
| C | 0.6234 | 0.5975 | 0.6102 | 241 |
| D | 0.6700 | 0.5418 | 0.5991 | 251 |
| E | 0.5808 | 0.6426 | 0.6101 | 235 |
- 全体精度: $762/1221 \approx 0.6241$
- マクロ F1 スコア: 0.6234
モデルの較正(Calibration)検証
モデルの出力スコアが実際の精度を反映しているか確認する必要があります。曖昧な問題に対するテストで、過信傾向が浮き彫りになります。
テスト例:極めて曖昧な質問
入力: 「コウモリを見かける可能性が最も高い場所はどこですか?」(選択肢:鍾乳洞、野球ゲーム中、屋根裏部屋、動物園、スポーツ用品店)
- 出力結果: A(鍾乳洞)で確率 0.9978 を獲得。
- 問題点: 明確な正解が存在するはずのない問題に対して、モデルが極端に高確率を割り当てていることが示されています。これは出力確率を「信頼スコア」として扱う際の誤りです(追加学習なしでは自信度=真の確率は保証されません)。
未較正状態のデータ分布
信頼スコアのビン区間ごとの精度を見てみると、自信度と精度が一致していないことがわかります。モデルは一般的に過信しています。
| ビン区間 | 件数 | 自信度 (確率) | 精度 |
|---|---|---|---|
| (0.00, 0.10] | 0 | 0.0000 | 0.0000 |
| (0.10, 0.20] | 0 | 0.0000 | 0.0000 |
| (0.20, 0.30] | 3 | 0.2834 | 0.0000 |
| (0.30, 0.40] | 26 | 0.3761 | 0.2692 |
| (0.40, 0.50] | 41 | 0.4538 | 0.2683 |
| (0.50, 0.60] | 70 | 0.5490 | 0.3286 |
| (0.60, 0.70] | 74 | 0.6476 | 0.3649 |
| (0.70, 0.80] | 77 | 0.7495 | 0.4286 |
| (0.80, 0.90] | 121 | 0.8555 | 0.4711 |
| (0.90, 1.00] | 809 | 0.9855 | 0.7009 |
- 課題: 自信度 0.9〜1.0 の予測でも正解率はわずか 70% です。
- 過信の例: 0.8〜0.9 の自信度でも精度は約 40% にとどまります。
較正手法:温度スケールリングと曲線適合
モデルの出力スコアが精度を反映するようにするため、以下の手法を用いて較正を行います。
1. 温度スケールリング(Temperature Scaling)
温度値を変更することで、出力確率分布を平坦化し、実際の精度に近似させることができます。
2. 曲線適合による最適温度の探索
モデルの精度に合わせて温度パラメータをフィットさせました。
- 発見された温度: 3.797280788421631
これにより、はるかに良い較正が得られました。調整後のデータ分布は以下のようになります。
| ビン区間 | 件数 | 自信度 (確率) | 精度 |
|---|---|---|---|
| (0.00, 0.10] | 0 | 0.0000 | 0.0000 |
| (0.10, 0.20] | 0 | 0.0000 | 0.0000 |
| (0.20, 0.30] | 82 | 0.2712 | 0.2317 |
| (0.30, 0.40] | 217 | 0.3507 | 0.3917 |
| (0.40, 0.50] | 199 | 0.4472 | 0.5126 |
| (0.50, 0.60] | 166 | 0.5475 | 0.5482 |
| (0.60, 0.70] | 139 | 0.6562 | 0.5827 |
| (0.70, 0.80] | 140 | 0.7492 | 0.7714 |
| (0.80, 0.90] | 169 | 0.8507 | 0.7988 |
| (0.90, 1.00] | 109 | 0.9333 | 0.9541 |
- 効果: 高自信度(0.9 以上)の予測でも精度は 95% 以上 に向上しており、モデルの過信傾向が大幅に改善されました。
次のステップ
より詳細な検証やデータセットの構築、評価、ファインチューニング、そしてモデル自体の較正を行うスクリプトは GitHub リポジトリにて公開しています。より大規模なモデルでも同様のアプローチを試してみることを強くお勧めします。