先後差を考慮した将棋のプロ棋士の強さモデリング(1)
はじめに
将棋は先手有利であるという通説があるが、実際にその効果はどのぐらいなのだろうか。また、「振り飛車党は先後の不利を克服できる」という説があるが、その説はどのぐらい信憑性があるのか、という点に対して、PyMC3 を用いたベイズモデリングによって解析してみたいと思う。
本稿で解析する内容は以下である。
- 2021 年のデータを用いて、棋士の強さモデリングの先行例を再現する (1)
- 全棋士共通の先手・後手の影響をモデルに組み込むことで、その差を除いた強さ・勝負ムラを見てみる (1)
- 棋士ごとの先手・後手の影響をモデルに組み込むことで、先後の強さ差が大きい棋士、少ない棋士を見てみる (2)
MCMC の手法的な性質、またデータが少ないことに起因して、何度か実行した時に結果がばらつくことがある。そのため、ここでの結果はあくまで1回の試行によって得られたものであって、絶対的なものではないということを先に述べておきたい。
先行例の調査
こちらの記事では、 PyMC3 を用いて棋士の強さをモデリングしており、強さの平均と勝負ムラについて解析している。
また、次の記事では、 PyStan を用いて同様のモデルでモデリングしている。この例では、先手と後手を別々の棋士であるとみなしてモデリングすることで、先手後手の棋士の実力差を見ている。
ここでは、 これらの記事を参考にしながら、PyMC3 を用いて 先手後手の差を組み込んだモデル を作り、それを用いて最新の勝敗データを用いて以下のことを検討してみたい。
対象は2021年のデータを用いた。その中で、日本将棋連盟に所属するプロ棋士どうしの対局であり、勝敗が判明しているもののみを対象とした。(対象となる対局は2330局、棋士数は174人)
のちの解析で利用するため、先手勝ちか後手勝ちかという情報も入れてある。
2021年のデータで同じ実験を再現してみる
まずは、2021年の勝敗データを用いた場合に、どのような結果になるか見てみよう。先行例2に倣ってそのモデルを表現すると、
- 棋士の強さをμ、実力のムラをσとして、対局時の実力を
normal(μ, σ)
として定める。 - 実力が高いほうが対局に勝利する。具体的には、実力の差をシグモイド変換した確率値 p に対して、 その確率 p で 1 が出るような試行であったとモデリングする(ベルヌーイ分布)。
モデルコードは PyMC3 による先行例を参考にした。先行例では s_mu = pm.Normal('s_mu', mu=0, sd=100)
としていたが、サンプリングの初期化の過程で、μ = -inf
となるときに発散してしまうことがわかってきた。以下がエラーメッセージである。
SamplingError: Initial evaluation of model at starting point failed! Starting values: {'s_mu': array(0.), 'mu': array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]), 'sigma_log__': array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]), 'loser_perf': array([0., 0., 0., ..., 0., 0., 0.]), 'winner_perf': array([0., 0., 0., ..., 0., 0., 0.])} Initial evaluation results: s_mu -5.52 mu -inf sigma_log__ 38.98 loser_perf -2142.05 winner_perf -2142.05 z -1615.73 Name: Log-probability of test_point, dtype: float64
そこで、ある程度上限の大きい一様分布で表現することにして、上記のエラーを回避している。 このことの意味は、実力の分散の事前分布を一様分布で与えている、ということになる。
pm.traceplot(trace, var_names=['mu','sigma'])
2021 年の対局における計算結果は以下。
各棋士の強さの平均(強い順)
mean | sd | hdi_3% | hdi_97% | mcse_mean | mcse_sd | ess_bulk | ess_tail | r_hat | |
---|---|---|---|---|---|---|---|---|---|
藤井聡太 | 2.982 | 0.458 | 2.173 | 3.853 | 0.03 | 0.021 | 228 | 553 | 1.01 |
渡辺明 | 1.834 | 0.48 | 0.896 | 2.694 | 0.028 | 0.02 | 303 | 674 | 1.01 |
永瀬拓矢 | 1.76 | 0.415 | 1.005 | 2.565 | 0.026 | 0.018 | 262 | 627 | 1.01 |
伊藤匠 | 1.726 | 0.452 | 0.929 | 2.601 | 0.024 | 0.017 | 352 | 871 | 1 |
出口若武 | 1.719 | 0.461 | 0.866 | 2.569 | 0.023 | 0.016 | 419 | 810 | 1.01 |
各棋士の勝負ムラの平均(大きい順)
mean | sd | hdi_3% | hdi_97% | mcse_mean | mcse_sd | ess_bulk | ess_tail | r_hat | |
---|---|---|---|---|---|---|---|---|---|
石田直裕 | 1.108 | 0.34 | 0.519 | 1.752 | 0.019 | 0.013 | 318 | 484 | 1.02 |
豊島将之 | 1.081 | 0.318 | 0.52 | 1.673 | 0.02 | 0.014 | 230 | 268 | 1.01 |
高崎一生 | 1.073 | 0.328 | 0.461 | 1.654 | 0.018 | 0.013 | 311 | 551 | 1 |
渡辺和史 | 1.071 | 0.335 | 0.48 | 1.709 | 0.019 | 0.014 | 296 | 704 | 1 |
佐藤和俊 | 1.065 | 0.336 | 0.495 | 1.72 | 0.02 | 0.014 | 268 | 488 | 1 |
各棋士の勝負ムラの平均(小さい順)
mean | sd | hdi_3% | hdi_97% | mcse_mean | mcse_sd | ess_bulk | ess_tail | r_hat | |
---|---|---|---|---|---|---|---|---|---|
丸山忠久 | 0.935 | 0.308 | 0.414 | 1.514 | 0.018 | 0.012 | 278 | 701 | 1.01 |
豊川孝弘 | 0.934 | 0.292 | 0.4 | 1.459 | 0.013 | 0.009 | 478 | 582 | 1 |
塚田泰明 | 0.932 | 0.287 | 0.437 | 1.465 | 0.013 | 0.009 | 446 | 888 | 1 |
永瀬拓矢 | 0.93 | 0.276 | 0.456 | 1.45 | 0.018 | 0.013 | 219 | 552 | 1.02 |
藤井聡太 | 0.912 | 0.284 | 0.411 | 1.406 | 0.02 | 0.014 | 189 | 299 | 1 |
興味深いこととして、藤井聡太五冠(記事執筆当時)は強さが高く、勝負ムラが最も少ない。言い換えるとどの対局においても平均的に高いパフォーマンスを発揮しているということがいえるだろう。
グローバルな先手後手の差をモデルに埋め込んだモデル
次のモデルでは、先手・後手の差には全体的な傾向(具体的には、先手の方が若干有利)があるとして、その傾向をモデルに反映させるということをおこなってみたい。こうすることで、先手・後手のバイアスを除いて強さや勝負ムラを計算するということができるのではないかと考えている。
モデルは色々試行錯誤したが、以下のように定めた。
- 棋士の強さをμ、実力のムラをσとして、対局時の実力を
normal(μ, σ)
として定める。 - 実力が高いほうが対局に勝利する。具体的には、実力の差をシグモイド変換した確率値 p に対して、 その確率 p で 1 が出るような試行であったとモデリングする(ベルヌーイ分布)。
with pm.Model() as model: # prior s_mu = pm.Uniform('s_mu',upper=300) mu = pm.Normal('mu', mu=0, sd=s_mu, shape=len_players) sigma = pm.Gamma('sigma', alpha=10, beta=10, shape=len_players) #delta = pm.Normal('delta', mu=0) delta = pm.Uniform('delta', lower=-1, upper=1) loser_perf = pm.Normal('loser_perf', mu=mu[battles.Loser-1], sd=sigma[battles.Loser-1], shape=len(battles)) winner_perf = pm.Normal('winner_perf', mu=mu[battles.Winner-1], sd=sigma[battles.Winner-1], shape=len(battles)) sente_perf = delta * battles.FirstWin diff = winner_perf-loser_perf+sente_perf p = pm.math.sigmoid(diff) z = pm.Bernoulli('z', p=p, observed=np.ones(len(battles)))
pm.traceplot(trace, var_names=['mu','sigma','delta'])
各棋士の強さの平均(強い順)
mean | sd | hdi_3% | hdi_97% | mcse_mean | mcse_sd | ess_bulk | ess_tail | r_hat | |
---|---|---|---|---|---|---|---|---|---|
藤井聡太 | 3.003 | 0.509 | 2.06 | 3.962 | 0.041 | 0.029 | 156 | 346 | 1.01 |
渡辺明 | 1.839 | 0.484 | 0.915 | 2.735 | 0.032 | 0.023 | 230 | 585 | 1.01 |
伊藤匠 | 1.814 | 0.468 | 0.963 | 2.741 | 0.023 | 0.016 | 430 | 727 | 1 |
永瀬拓矢 | 1.8 | 0.434 | 1.025 | 2.607 | 0.029 | 0.021 | 217 | 709 | 1.01 |
出口若武 | 1.662 | 0.477 | 0.78 | 2.577 | 0.028 | 0.02 | 289 | 755 | 1 |
各棋士の勝負ムラの平均(大きい順)
mean | sd | hdi_3% | hdi_97% | mcse_mean | mcse_sd | ess_bulk | ess_tail | r_hat | |
---|---|---|---|---|---|---|---|---|---|
渡辺和史 | 1.105 | 0.343 | 0.498 | 1.735 | 0.02 | 0.015 | 285 | 602 | 1.01 |
山本博志 | 1.096 | 0.34 | 0.482 | 1.718 | 0.022 | 0.016 | 224 | 446 | 1.01 |
伊藤真吾 | 1.086 | 0.35 | 0.461 | 1.721 | 0.019 | 0.013 | 334 | 559 | 1 |
船江恒平 | 1.082 | 0.341 | 0.478 | 1.719 | 0.019 | 0.014 | 292 | 706 | 1 |
高崎一生 | 1.08 | 0.339 | 0.482 | 1.747 | 0.019 | 0.014 | 289 | 269 | 1.01 |
各棋士の勝負ムラの平均(小さい順)
mean | sd | hdi_3% | hdi_97% | mcse_mean | mcse_sd | ess_bulk | ess_tail | r_hat | |
---|---|---|---|---|---|---|---|---|---|
竹内雄悟 | 0.93 | 0.291 | 0.432 | 1.514 | 0.019 | 0.013 | 228 | 498 | 1.01 |
田中寅彦 | 0.929 | 0.297 | 0.44 | 1.511 | 0.017 | 0.012 | 290 | 659 | 1.01 |
藤井聡太 | 0.921 | 0.268 | 0.446 | 1.424 | 0.021 | 0.015 | 158 | 332 | 1.01 |
池永天志 | 0.912 | 0.294 | 0.411 | 1.467 | 0.02 | 0.014 | 203 | 376 | 1 |
永瀬拓矢 | 0.887 | 0.278 | 0.425 | 1.413 | 0.02 | 0.014 | 190 | 342 | 1 |
まとめ
まずは、各棋士の強さ及び勝負ムラについて調査した。次に、先後の差をモデルに組み入れることで、先後の差を除いた各棋士の強さ及び勝負ムラについて調査した。