やってみた。プロ棋士の強さ推定

階層ベイズモデルで勝敗データからプロ棋士の強さを推定する,StatModeling Memorandumという実験があります。大変面白いので私もやってみました。

データ収集

まず将棋のプロ棋士の対局結果を将棋連盟 棋士別成績一覧から収集しました。こちらのサイトは1964年度以降の棋士公式戦対局結果がまとまっています。米長邦雄の四段昇段が1963年、中原誠の四段昇段が1965年です。大昔ですね。素晴らしいですね。以下の方針でスクレイピングしました。

  1. データベース中のプロ棋士同士の対局をすべて収集する
  2. 対局者のどちらかあるいは両方が四段昇段前(奨励会員もしくはアマチュア)であっても収集対象とする
  3. 不戦勝、不戦敗は除外

2017年7月30日時点で、対局総数は103849局、棋士総数292人でした。

また、参考用にプロ棋士の生年月日および四段昇段日も収集しました。こちらは将棋連盟のデータベース将棋順位戦データベースWikipediaの個別ページを基にしました。将棋順位戦データベースも暗記したいほどの素晴らしいサイトです。

モデル

Memorandumの記事で使われたモデルのキモは次の2点だと思います。

  • 棋士のskill値+勝負ムラの大小で対局の勝敗をモデル化する
  • 棋士のskillの推移を自己相関モデルでモデル化する

モデルはBUGS文法で書かれており、とても複雑に見えます。BUGSはStan以上に使い方が分からないので、私はMemorandumのモデルをせめてStanに移植できないかと試行錯誤しましたが、何をどうしてもサンプリング結果が収束しませんでした。残念です。素人には高いハードルでした。

しょうがないのでモデルを変更しました。対局の勝敗は、勝者の勝率pをskill値の差(勝者-敗者)によるロジットモデルで表します。勝率pはそのまま尤度となります。勝負ムラは考慮しません。


logit(p) = a \times \Delta skill

このロジットモデルというのは今回初めて知りましたが1、いかにも便利で使い出がありそうですね。

skillの自己相関は下のように定めました。iは年度のインデックスです。sは全棋士全年度で共通としてます。また、これを正しく自己相関と呼んでいいのか、私は知りません。


skill_i \sim \mathcal{N}(skill_{i-1}, s^2)

aが1/400 * log(10)の場合、スキル差と勝率の関係がイロレーティングと同じになります。つまりこのモデルは、棋士レーティングを自己相関モデルで推定するものです。

完成したStanのモデルです。dataの構造はMemorandumを参考にしています。

model <- "
data {
  int N_kishi;
  int N_game;
  int N_year;
  int Winner[N_game];
  int Loser[N_game];
  int Year[N_game];
  int Career[N_kishi, 2];
}

parameters {
  real i_skill[N_kishi];
  real r_skill[N_kishi, N_year-1];
  real<lower=0> a;
  real<lower=0> s;
}

transformed parameters {
  real skill[N_kishi, N_year];
  real log_p[N_game];

  for(k in 1:N_kishi) {
    for (y in 1:Career[k,1])
      skill[k, y] = i_skill[k];

    for(y in (Career[k,1]+1):Career[k,2])
      skill[k, y] = skill[k, y-1] + r_skill[k, y-1];

    for (y in (Career[k,2]+1):N_year)
      skill[k, y] = skill[k,Career[k,2]];
  }

  for (g in 1:N_game)
    log_p[g] = log_inv_logit(a * (skill[Winner[g], Year[g]] - skill[Loser[g], Year[g]]));
}

model {
  for (k in 1:N_kishi) {
    target += normal_lpdf(i_skill[k] | 0, 100);
    for (y in Career[k,1]:(Career[k,2]-1))
      target += normal_lpdf(r_skill[k, y] | 0, s);
  }

  target += sum(log_p);

  target += uniform_lpdf(s | 0, 100);
}
"

モデル中のYearは公式戦準拠で年度単位となっています。スキル値も同様です。 全棋士の初期skillの事前分布は平均ゼロ、分散100の正規分布としました。 skillの自己相関モデルの標準偏差sの事前分布はゼロから100までの一様分布としました。 Careerは四段昇段以前の対局を含んだ、各棋士の実績の開始年度、終了年度のインデックスです。Career前のskillは初期skillと同じ値、Career後のskillはCareer終了年度のskillと同じ値にします。Career外の年度のskillは本来不要なので、サンプリング後に別処理でNAにしました。

サンプリングの実施

skill、a、sを収集対象パラメータとして、iter=12000、warmup=2000、thin=5、chains=4でサンプリングしました。対局結果データは収集した全データを使用しました。とてもものすごく時間がかかりました。よくやったもんです。

結果

Stanが計算してくれるRhatは全パラメータで1.1以下でした。収束したようです。やりました。

a, sの推定結果

skill差にかける係数aの平均は0.00671でした。イロレーティングの係数1/(400 * log(10))=0.0058と近いと言えるかもしれません。

meanse_meansd2.5%25%50%75%97.5%n_effRhat
a 0.00670692.7922e-050.00044769 0.0058647 0.0063853 0.0066965 0.0070188 0.0075937257.07 1.0092
s21.60418001.2963e-011.9210991818.245761520.184668821.536526222.904853925.5018467219.62 1.0108

skill差(レート差)と勝率の関係を可視化しました。イロレーティングとよく似ていますが偶然でしょう。適当に決めた初期スキルなどの事前分布が偶々こうなるような事前分布であった、ということだと思います。

skill差と勝率

skillの推定結果

skillの推定結果の統計量をこちらに載せています。

佐藤天彦のskill値の事後分布

Rhat的にはskill値はよく収束しているそうですが、安全安心のために事後分布を可視化してみます。実力制第十三代名人 佐藤天彦のskill値を年度ごとchainごとに可視化しました。

佐藤天彦

上下のヒゲの伸び方に差はありますが、それ以外はchain間の差がほとんど見られません。いい感じです。

棋士全年度についてskill値の平均値と中央値を比較すると大体同じでした。skill値の平均値と中央値の差の統計量を下に示します。どのskillも釣鐘型の綺麗な分布をしているんじゃないでしょうかと思います。

 diff_mean_median
 Min.   :-3.383  
 1st Qu.:-0.668  
 Median :-0.222  
 Mean   :-0.269  
 3rd Qu.: 0.172  
 Max.   : 1.734  

以降はskill値の代表値として平均値を使っていきます。

棋士レーティングとの比較

推定された2017年度のskill値(平均と95%区間)と棋士レーティング(2017年7月30日時点)を比較しました。Memorandumでも同様の可視化をしています。どうしても巨大な画像になりますね。

レーティングとの比較

大体整合的ですね。藤井聡太、大橋貴洸、大橋貴洸、杉本和陽の新人四人は95%区間が大きいです。それ以外の棋士の95%区間は大体同じような大きさに見えます。

下表は2017年度のskill値上位20人です。微差ながら藤井聡太佐藤天彦を抑えて堂々1位となりました。青嶋未来や近藤誠也もskill値では評価高く、まだレーティングが追いついていない状態と言えます。

skill順位名前skill平均skill95%区間skill95%区間レーティングレーティング順位
1 藤井聡太 318.15 206.71 438.42 1703 32
2 佐藤天彦 317.40 243.53 397.99 1884 1
3 羽生善治 315.03 243.92 394.22 1849 4
4 豊島将之 313.00 240.05 390.72 1878 2
5 渡辺明 288.24 213.38 367.98 1828 7
6 菅井竜也 286.98 216.12 365.51 1856 3
7 稲葉陽 274.81 201.85 354.58 1837 6
8 久保利明 274.77 202.91 352.13 1839 5
9 永瀬拓矢 258.59 186.67 334.47 1825 8
10 糸谷哲郎 252.53 182.40 327.20 1808 9
11 千田翔太 244.15 173.17 319.49 1790 11
12 斎藤慎太郎240.46 169.81 313.21 1801 10
13 佐々木勇気238.27 170.34 310.52 1778 13
14 広瀬章人 234.33 163.60 309.05 1780 12
15 山崎隆之 229.63 160.52 304.31 1776 14
16 中村太地 226.65 153.89 300.82 1775 15
17 三浦弘行 224.80 151.06 303.74 1767 17
18 青嶋未来 224.12 147.35 302.01 1715 26
19 近藤誠也 224.00 142.70 307.73 1701 33
20 松尾歩 219.55 148.18 295.29 1766 18

棋士のskill値の推移

せっかく50年余りの推定を行ったので、全棋士のskill値の平均の推移をプロットしました。

15MBのpngファイル

デカイです。棋士名が重なって見づらいです。個別の棋士の推移を追うことができないですね。

全体の傾向として、どうもskill値の分布の裾が時間経過とともに広がっていることがわかります。 試しに5年単位でskill値の平均のバイオリンプロットを描いてみました。

skillの密度分布の推移

分布の中心とばらつきが一定だと年度間でのskill値を容易に比較できて大変便利だと思う、のですが。

  1. 中央値、平均値とも上昇傾向, skill値はインフレしている
  2. ばらつきも大きくなる傾向があるような気がするが、はっきりしない。1995年付近を境界にしてばらつきが大きくなった=棋力の格差が広がった、ように見える。

これでは、年度をまたいだskillの値そのものの比較はできませんね。具体的に今回のモデルの何が悪いのかは分かりません。

ちなみにイロレーティングもインフレ・デフレするそうです。

歴代のトップ棋士

各年度におけるskill値の順位TOP10を可視化しました。黒丸は公式戦デビュー時点でランクインしたことを示します。黒字のラベルは翌年度にランク外に陥落したことを示します。

トップ棋士のskill推移

大山→中原→羽生と続く棋界の頂点の推移がよくわかりますね。また、中原誠羽生善治とも、デビュー時で2位にランクインし、すぐに1位に上り詰めています。先程藤井聡太がskill1位すごいすごいと書いたわけですが、確かにすごいが前例はあるのでした。羽生世代やポスト羽生世代には、デビュー即トップ10入りという棋士が結構います。もちろんデビュー直後なので信頼区間の幅も大きいわけですが。

谷川浩司渡辺明は一度も1位になっていません。これは違和感があります。谷川浩司については、中原以降羽生以前に覇権を握ったイメージがあったのですが、今回のモデルでは、skill上はそのような時代は無かった、となります。

羽生世代が80年代後半にドカドカと現れて、2010年台にドカドカと退場する、世代交代の様が一目瞭然です。羽生善治も2016年度に1位の座を明け渡したようです。レーティングもそんな感じですね。次なる頂点の候補は佐藤天彦藤井聡太と、最近の若手では珍しくデビュー時点でトップ10入りの菅井竜也でしょうか。私は糸谷哲郎推しですが、この人ポカが多いんですよね。

山田道美、村山聖はトップ10のまま夭折しました(村山聖は最期は休場)。山田道美は山田定跡の考案者ですね。大山康晴相手にタイトルもとりました。棋士番号制定前の棋士であるためか、将棋連盟棋士データベースには個別ページさえもありません。

TOP10の棋士のスキルはおおむね右肩上がりに上昇しています。その中で羽生善治は、1995年から2010年まで、2位の棋士相手に常に50以上のskill差をつけています。やはり化物ですね。

棋士の全盛期と年齢

棋士の全盛期と年齢の関係を可視化しました。年齢はデータ収集のところで書いた生年月日をもとに、年度ベースの数え歳で計算しました。つまり平成27年度生まれは平成27年度に1歳、という換算になります。

全盛期をskill値そのもので求めるのは危ないので、期歴におけるskill値の年度順位が最高の年度を全盛期としました。例えば羽生善治は15歳から46歳まで1位を32年間維持したので、この間ずっと全盛期という扱いになります。また、この計算で全盛期が年度期間の両端(1964年、1965年、2016年、2017年)となった棋士は、真の全盛期は計算期間の範囲外にあるものと思われるため、除外しました。

棋士の全盛期年齢

棋士全体ではskill値は20代半ばに全盛期が来ることが多いようです。トップ棋士の場合は山がもっとのっぺりしてます。

40過ぎで全盛期が来て(あるいは全盛期を維持して)、それがトップ20以内の棋士は以下になります。花村元司以上は、1963年以前に全盛期があった可能性があると思います。加藤一二三は名人獲得直前が全盛期ですね。加藤一二三は早熟の天才というイメージがありましたが、今回収集したデータの範囲では40歳前後で順位を上げており、実に不思議な棋士です。「大山康晴に苛められすぎたのが中年になって吹っ切れた」と、中原誠渡辺明との対談で言っていたような記憶があります(たしか将棋世界誌上)。

idname年度skill値の平均順位誕生年度年齢
1026 大山 康晴 1966 197.1745 1 1922 45
1035 原田 泰夫 1966 -4.2594 19 1922 45
1035 原田 泰夫 1967 -5.3930 19 1922 46
1039 花村 元司 1966 7.0797 16 1917 50
1064 加藤 一二三1981 131.3172 3 1939 43
1085 米長 邦雄 1982 141.3653 2 1943 40
1175 羽生 善治 2009 337.4900 1 1970 40
1175 羽生 善治 2010 349.6142 1 1970 41
1175 羽生 善治 2011 353.2264 1 1970 42
1175 羽生 善治 2012 358.3190 1 1970 43
1175 羽生 善治 2013 352.0057 1 1970 44
1175 羽生 善治 2014 344.3521 1 1970 45
1175 羽生 善治 2015 330.5932 1 1970 46
1204 三浦 弘行 2015 230.0110 13 1973 43

今回のモデルは単純なので、推定されたskillの平均の推移は、1963年からイロレーティングを計算した場合と大きな違いはないと思います。 デビュー直後の棋士の強さを推定できるのことが優位点でしょうか。 モデルにもっと棋士個人差のパラメタを組み込むと面白いと思います。例えばskillの自己相関の標準偏差や、勝負ムラなど。

色々な可視化ができたのは楽しかったです。

おわり。


  1. 久保拓弥著 「データ解析のための統計モデリング入門」という本の読書会資料をググって漁っていたところ、知りました。