分散削減テクニック
対局スコアのばらつきを抑えると、Elo 推定の信頼区間を狭め、SPRT の判定や SPSA の勾配推定に必要な対局を減らせます。 共通乱数法(CRN)、先後を入れ替えるペアゲーム、複数の結果をまとめるバッチ処理を扱います。
分散が問題になる理由
エンジン対局の結果は本質的に確率的です。 同じエンジンペアでも、対局ごとに勝ち、引き分け、負けのいずれにもなります。
このばらつきは、次の推定や判定に影響します。
- SPRT:判定に到達するまでの対局数が増加する
- SPSA:勾配推定がノイズに埋もれ、最適化が不安定になる
- Elo 推定:信頼区間が広くなり、実用的な判断が困難になる
CRN(共通乱数法)
原理
2 つのシステムを比べるとき、結果の差にはシステムの違いだけでなく、実験条件の当たり外れも混ざります。 Common Random Numbers(CRN) は、両者に同じ乱数列(ここでは同じ開始局面)を与えて、この共通の変動要因を相殺する手法です。
CRN なし:
θ⁺ → 局面 A で対局 → スコア s⁺
θ⁻ → 局面 B で対局 → スコア s⁻
→ 局面 A と B の難易度の差がノイズに加算
CRN あり:
θ⁺ → 局面 A で対局 → スコア s⁺
θ⁻ → 局面 A で対局 → スコア s⁻
→ 局面の影響がキャンセルされ、純粋なパラメータの差を測定
数学的背景
2 つのスコアの差の分散は、次のように分解できます。
\[ \text{Var}[s^+ - s^-] = \text{Var}[s^+] + \text{Var}[s^-] - 2\text{Cov}[s^+, s^-] \]
同じ局面を使えば、局面自体の難易度が両者のスコアを同じ向きに動かすため \(\text{Cov}[s^+, s^-] > 0\) となります。 共分散の項が引かれるぶんだけ、差の分散が小さくなります。
ShogiArena の実装
現在のSPSAは、plusとminusを直接対戦させます。 各ペアの開始局面を更新ごとの決定的な乱数で抽選し、同じ局面でplus/minusの先後を入れ替えて2局対戦します。 局面は入力ファイル全体から復元抽出するため、重複する場合があります。 更新間で同じ局面列に固定する必要はありません。
割当の再現条件は、sealed run seed、run ID、更新番号、ペア番号、局面ファイルの内容と順序、割当規則の版が同じことです。
並列実行順や中断・resumeによって割当は変わりません。
variants.crnは旧設定の互換入力として受け付けますが、値によってこの動作を切り替えることはありません。
ペアゲーム(先後入れ替え)
原理
将棋(およびチェス)では先手が有利です。この先後バイアスは、エンジンの実力差とは無関係のノイズです。
ペアゲームでは、同じ開始局面で先後を入れ替えた 2 局をセットにします。
ペア:
Game 1: Engine A (先手) vs Engine B (後手) → 結果 r₁
Game 2: Engine A (後手) vs Engine B (先手) → 結果 r₂
ペアスコア = r₁ + r₂ (先後バイアスが相殺)
分散削減効果
先手勝率を \(p_b\)(先手有利バイアス)、Engine A の実力による勝率を \(p_a\) とすると、次のようになります。
- 独立した 2 局:\(\text{Var} \propto p_b(1-p_b) + p_a(1-p_a)\)
- ペアゲーム:\(\text{Var} \propto p_a(1-p_a)\)(\(p_b\) の項が消える)
ペアの中で先手番が両エンジンに 1 回ずつ割り当てられるため、先後バイアス由来の分散が残りません。
五項分布との関係
ペアゲームの結果は 五項分布 でモデル化できます。 5 カテゴリ(0.0, 0.5, 1.0, 1.5, 2.0)による分析は、三項分布(勝/引/負)よりも情報量が多く、 SPRT の判定に必要な対局数を 20-40% 削減できます。
バッチ処理
原理
SPSA の 1 回の更新で、同じ摂動に対して複数の対局を実行し、スコアを平均します。
\[ \bar{s}^+ = \frac{1}{B} \sum_{b=1}^{B} s^+_b \qquad \bar{s}^- = \frac{1}{B} \sum_{b=1}^{B} s^-_b \]
分散削減効果
\[ \text{Var}[\bar{s}^+ - \bar{s}^-] = \frac{1}{B} \text{Var}[s^+ - s^-] \]
バッチサイズ \(B\) に反比例して分散が減少します。
実装
現在の実装はplus/minusの直接対戦を先後反転して行い、全対局の「plus勝ち数−plus負け数」を合計します。
上の平均スコアの式は分散削減の説明用であり、runtimeでは平均しません。
pairs_per_updateを増やす場合は、更新幅も変わるためr_endの再調整が必要です。
コストと利益のトレードオフ
バッチサイズを \(B\) にすると、次のようになります。
- 分散:\(1/B\) に削減
- 1 更新あたりの対局数:\(2B\) に増加
- 総対局数:\(N \cdot 2B\)(更新回数 \(N\) が同じ場合)
総対局数を固定するなら、バッチサイズを上げたぶんだけ更新回数 \(N\) は減ります。 1 回の更新は安定しますが、パラメータを更新できる回数は減ります。
手法の組み合わせ
これらの手法は直交しており、すべて同時に使用できます。
1 回の SPSA 更新:
┌─────────────────────────────────────────────┐
│ CRN: 同じ SFEN を θ⁺ と θ⁻ に使用 │
│ ┌────────────────────────────────────────┐ │
│ │ ペアゲーム: 先後入れ替え 2 局 │ │
│ │ ┌───────────────────────────────────┐│ │
│ │ │ バッチ: B ペアのスコアを集計 ││ │
│ │ └───────────────────────────────────┘│ │
│ └────────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
現在の直接対戦方式では、1回の更新あたりの対局数は2B局です。
推奨設定
spsa:
pairs_per_update: 4 # 1 回の更新に使うペア数(バッチサイズ)
inflight_factor: 8 # 同時進行させる対局数の乗数
効果の比較
以下は概念的な比較です(実際の効果は問題に依存します)。
| 手法 | 分散削減率 | 追加コスト | 実装の複雑さ |
|---|---|---|---|
| CRN | 30-50% | なし | 低い |
| ペアゲーム | 20-40% | 2倍 | 低い |
| バッチ (B=4) | 75% | 4倍 | 低い |
| 全手法併用 | 80-90% | 8倍 | 中 |
現在の
plus_minusではペア内の局面共有が常時行われます。crnの指定は不要です。
実装リファレンス
| ファイル | 設定キー/関数 | 役割 |
|---|---|---|
| config_spsa_models.py | variants.crn | 旧設定の互換入力 |
| config_spsa_models.py | pairs_per_update | 1 回の更新に使うペア数 |
| orchestrator.py | SpsaOrchestrator | ペアゲームの実行制御 |
| pentanomial.py | compute_pentanomial() | 五項分布の計算 |
参考文献
- Asmussen, S. and Glynn, P. (2007). Stochastic Simulation: Algorithms and Analysis. Springer. — CRN を含むモンテカルロ法の分散削減手法の体系的な解説
- Spall, J. C. (2003). Introduction to Stochastic Search and Optimization. Wiley. — SPSA におけるバッチ処理と分散削減の理論
次に読む
設定や実行手順は、次のページを参照してください。
- SPRT の設定と解釈:設定パラメータの選び方
- SPSA のゲインスケジュール:最適化の微調整
- ユーザーガイド: SPSA チューニング:実際の設定と実行手順