藤井聡太七段のタイトル獲得数を勾配ブースティングで予測

# 概要
史上最年少でプロデビューし、デビューから前人未到の29連勝を達成して世間に'藤井フィーバー'を巻き起こした天才棋士、藤井聡太七段がプロになって早くも3年が過ぎました。タイトルを獲るのも時間の問題と思われていましたが、昨年はタイトル挑戦まであと1勝と迫るも惜敗し、2020年4月現在まだタイトル挑戦は決めていません。一方で将棋界ではここ数年で大きな変動がありました。30年近くタイトルを保持し続けた羽生善治九段をはじめとした'羽生世代'が若手に押され始め、さらにAIを用いた将棋ソフトの進展によって将棋界は群雄割拠となり、誰がタイトルを獲ってもおかしくない状況になりました。藤井七段をもってしても常に勝つことは難しく、タイトルの厳しさを感じます。
そこで、ここ3年間でのタイトル戦登場棋士の成績から、藤井七段のタイトル獲得数を予測し、どれくらいタイトルに近いのか評価してみました。[^1]
コードは[GitHub](https://github.com/tsekine2/Shogi-Title-Prediction)に挙げています。

# データセット
学習用データとして、[日本将棋連盟のHP](https://www.shogi.or.jp/match/)から、2020年4月1日時点でのB級1組以上の棋士、2017年~2019年のタイトル戦に登場した棋士、永世称号有資格者の①年齢、②プロ入り年齢、③順位戦クラス[^2]、④竜王戦クラス[^3]、⑤王位リーグ[^4]在位数、⑥王将リーグ[^5]在位数、⑦勝数、⑧対局数、⑨一般棋戦優勝数[^6]をまとめ、タイトル戦登場数とタイトル獲得数をtsvファイルにまとめました。該当棋士は28名いました。(本来なら全棋士を対象とするべきですが、かなり手間がかかるので絞っています。)ここで、③~⑧は過去3年間で計上し、順位戦ならばA級:5点、B級1組:4点、B級2組:3点、C級1組:2点、C級2組1点で加算、竜王線も同様に1組:5点、2組:4点、3組:3点、4組:2点、5組:1点、6組:0点で加算し(最大15点)、王位/王将リーグは在籍数*1点(最大3点)を足しています。

# 手法
今回はKaggle界で良く使われている[lightGBM](https://lightgbm.readthedocs.io/en/latest/index.html)の勾配ブースティングを使い、①~⑨の変数を学習変数としてタイトル獲得数またはタイトル戦登場数を予測しました。勾配ブースティングについては[こちら](https://qiita.com/woody_egg/items/232e982094cd3c80b3ee)が参考になります。決定木を使ったアンサンブル学習で、勾配降下法を用いて前の木の誤差を改善していくという特徴があります。また、比較として[scikit-learn](https://scikit-learn.org/stable/)の線形回帰およびニューラルネットワークでも予測してみました。

# 実装
今回もGoogle Colaboratoryを使って実装していきます。

### ライブラリインポート
```python:ライブラリインポート
import numpy as np
import pandas as pd
% matplotlib inline
import matplotlib.pyplot as plt
!pip install japanize-matplotlib
import japanize_matplotlib
import seaborn as sns
sns.set(font='IPAexGothic')
import lightgbm as lgb
from lightgbm import LGBMRegressor
```
matplotlibはそのままでは日本語表記が使えないのでライブラリをインポートしています。([参考](https://qiita.com/makaishi2/items/d47d0d1b8eb05e5605b9))

### 学習データ

```python:学習データ読み込み
train_path = "/content/drive/My Drive/Colab Notebooks/成果物/将棋タイトル/棋士解析(2017_2019) - train.tsv"
train = pd.read_csv(train_path, delimiter='\t')
```
今回データは自作なので、Google Driveに置いてマウントして読み込みにいきます。データ情報を見てみましょう。

```python:学習データ情報
train.head(len(train))
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570054/15fcfdb2-855b-7c7f-3a26-462557087a37.png)

順番は日本将棋連盟での上座順(竜王→名人→その他タイトル→永世称号有資格者→段位(棋士番号順))に則っています。おおよそ若い番号ほど強いと考えて差し支えないです。タイトル獲得数を見るとここ数年では豊島竜王・名人と渡辺三冠が突出しており、次いで永瀬二冠や羽生九段が追っています。
上記でタイトル獲得者の変数をグラフ化してみます。

```pyrhon:可視化 
train[train['get_titles'] > 0].plot.bar(x='name', figsize=(20,20), sharex=True, subplots=True, layout=(4,3))
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570054/be935704-1075-5d0b-f246-f63cc91dd4fd.png)

特に上位3人の特徴として、年齢が20代~30代、プロ入りは10代、勝数や対局数が多い(勝ちまくっている)という共通点があります。これは直感とも一致します。

### テストデータ

```python:テストデータ読み込み
test_path = "/content/drive/My Drive/Colab Notebooks/成果物/将棋タイトル/棋士解析(2017_2019) - test.tsv"
test = pd.read_csv(test_path, delimiter='\t')
test.head(len(test))
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570054/03217a33-5be0-20c0-11c5-1c53abd6072e.png)

続いてテストデータを見ていきます。せっかくなので藤井七段に加え、個人的に将来有望だと思う若手棋士を4人持ってきました。

```python:可視化
test.plot.bar(x='name', figsize=(15,10), sharex=True, subplots=True, layout=(3,3))
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570054/31172675-736a-52e0-d199-edc321351396.png)

佐々木大地五段もすごいですが、藤井七段の対局数と勝数からどれだけ勝ってるか良くわかりますね。

# 学習

```python:
train_x = train.loc[:, 'age' : 'champions']
train_y = train['get_titles']
test_x = test.loc[:, "age" : "champions"]
params = {
    'learning_rate' : 0.01,
    'min_child_samples' : 0,
}
model = LGBMRegressor(**params)
model.fit(train_x, train_y)
y_pred = model.predict(test_x)
```
実際に学習していきます。まず「タイトル獲得数」をターゲットとします。
paramsでLGBMRegressorに渡すハイパパラメタを設定できます。今回は学習データが少ないので学習率は小さくし、min_child_samples(最終的な予測ノードに含まれるサンプル数)は最小にします。

# 結果

結果をプロットします。

```pthon:結果表示
names = test["name"]
display(pd.DataFrame(y_pred, index=names, columns=['タイトル獲得数']))
```
<img width=250 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570054/fc9324df-2930-4124-087e-54b035c17346.png>

藤井七段は約4期獲れるという予測になりました。これはすでにトップ棋士に匹敵する数字ですね。次いで増田六段が約3期、佐々木大地五段が1期半でした。誰をとってもタイトルを獲得できると予測されるほど活躍していることが分かりました。
なお、今回学習したモデルで重要視された変数を見ることができます。

```python:学習変数重要度
features = test.loc[:, 'age' : 'champions']
display(pd.DataFrame(model.feature_importances_, index=features.columns, columns=['importance']).sort_values('importance', ascending=False))
```
<img width=250 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570054/08e126e2-fe96-7e71-8fab-2eab9269993a.png>

最も重要視された変数は「年齢」でした。将棋は一般に年齢が若いほど有利であること、近年の若手棋士の活躍ぶりからこれは納得です。続いて勝利数(勝てば勝つほどタイトルに近づく)、プロ入り年齢(大棋士は総じて若くしてプロになっている)、対局数(勝てば勝つほど対局が増える)が重要なようです。上記で抜群の数字を持つ藤井七段が高く評価されるのは必然です。一方で王位リーグや王将リーグに在籍することは重要でないと判断されています。もしかすると値のオーダーが小さいからでしょうか？

# タイトル戦登場数予測

```python:タイトル戦登場数予測
train_y2 = train['titles']
model.fit(train_x, train_y2)
y_pred2 = model.predict(test_x)
display(pd.DataFrame(y_pred2, index=names, columns=['タイトル登場数']))
```
ターゲットを「タイトル獲得数」の代わりに、「タイトル戦登場数」にして予測もしてみました。おおよそ同じ結果になるはずですが、獲得数よりは大きな数になるはずです。

<img width=250 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570054/8002860c-adfe-e42f-1594-a371f7386d1d.png>

興味深いことに藤井七段と増田六段が並びました。次いで佐々木大地五段、佐々木勇気七段と青嶋五段が同じになるのは変わりませんでした。先ほどの結果と比べると、藤井七段はタイトル戦に5回登場して内4回は勝てるということでしょうか(末恐ろしいですね…)

```python:学習変数重要度
display(pd.DataFrame(model.feature_importances_, index=features.columns, columns=['importance']).sort_values('importance', ascending=False))
```
<img width=250 alt="image.png" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570054/bc4bcc74-232e-8705-6471-f101147f9489.png>

今度はプロ入り年齢を最も重視しています。タイトル戦登場数の多い羽生九段(プロ入り15歳)の寄与が効いたのでしょうか。

# 線形回帰

勾配ブースティングでの回帰と比べ、線形回帰ではどうなるのでしょうか。線形回帰とは、下式のように線形関数でフィッティングすることです。

```math
y=b_0+b_1x_1+b_2x_2+\cdots+b_Nx_N \\
(b_0,b_1,\cdots,b_N \in \mathbb{R}, x_1, x_2,\cdots, x_N \in 学習変数)
```
```python:線形回帰
from sklearn.linear_model import LinearRegression
reg = LinearRegression()
reg.fit(train_x, train_y)
lr_pred = reg.predict(test_x)
```

<img width=250 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570054/35bc977f-1873-a77f-a828-3e2f27f04251.png>

藤井七段はやはり4期という結果になりましたが、他の棋士は値が変わりました。青嶋五段に至ってはマイナスとなってしまいました。線形回帰の場合直線になるので確かにマイナスとなる可能性はありますが、ここまで差が出たのは意外でした。
ちなみにこのモデルの係数と切片は次のようになりました。

```python:係数可視化
display(pd.DataFrame(reg.coef_, index=features.columns, columns=['coef']))
print('intercept = {}'.format(reg.intercept_))
```
<img width=250 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570054/77893e8c-82a4-e18d-322a-0934bc91e6c8.png>

係数がマイナスのものは変数値が低いほど予測値が高くなるので、年齢、プロ入り年齢がマイナスなのは分かりますが、順位戦の点数と対局数がマイナスなのは不可解です。順位戦に関してはA級やB1にいながらもタイトルには絡んでいないベテラン勢の寄与かもしれません。

# ニューラルネットワーク
最後にニューラルネットワークでも予測してみます。

```python:ニューラルネットワーク
from sklearn.neural_network import MLPRegressor
nn = MLPRegressor()
nn.fit(train_x, train_y)
nn_pred = nn.predict(test_x)
display(pd.DataFrame(nn_pred, index=names, columns=['タイトル獲得数']))
```

<img width=250 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570054/e4afba80-ce3d-90c4-0acc-8b62278dc1e3.png>

なんと藤井七段よりも佐々木勇気七段の方が高くなりました。佐々木大地五段が最下位になるなど、直感とは異なる結果です。ニューラルネットワークは非線形変換をして予測しているので、今回のタスクに有効なのか疑問ですが、他の方法と比べても少なくともデフォルトでは上手くいきませんでした。

# まとめ
今回は将棋新時代でのデータから、藤井七段のタイトル獲得数を予測してみました。これほど活躍しているにも関わらずまだタイトルは獲れていませんが、タイトルを獲った棋士と成績を比較するとこの3年間で約4期は獲れているという予測となり、十分タイトルに近いという結果となりました。また、今回変数として考慮していないシードも多くの棋戦でされるようになり、今後タイトルを獲る確率はますます上がっていると思われます。将棋ファンとして楽しみな限りです。
また、今回性能比較(例えば正解値と予測値の差の二乗和を比較)は、テストデータの棋士が全員タイトル獲得数0のため行っていませんが、個人的な直感と比べて勾配ブースティングが最も正しく予測できていたように思います。できればもっとデータを集めて、また何か分析したいです。

# 参考文献
[棋士プロ入り年齢](https://depalma01.com/2018/11/23/%E5%B0%86%E6%A3%8B%E3%81%AE%E6%A3%8B%E5%A3%AB%E3%81%8C%E3%83%97%E3%83%AD%E5%85%A5%E3%82%8A%E3%81%97%E3%81%9F%E5%B9%B4%E9%BD%A2%E3%81%BE%E3%81%A8%E3%82%81%E3%80%90%E6%9C%80%E5%B9%B4%E5%B0%91%E3%83%BB/)
[棋士年齢](http://kishibetsu.com/age1.html)
[pandasグラフ描画](https://note.nkmk.me/python-pandas-plot/)
[lightGBM予測が同じになる時](https://kiseno-log.com/2019/12/08/lightgbm%E3%81%A7%E3%81%AE%E4%BA%88%E6%B8%AC%E5%80%A4%E3%81%8C%E3%81%99%E3%81%B9%E3%81%A6%E5%90%8C%E3%81%98%E5%80%A4%E3%81%AB%E3%81%AA%E3%82%8B%E3%81%A8%E3%81%8D%E3%81%AE%E5%8E%9F%E5%9B%A0%E3%81%A8/)


[^1]: 将棋に詳しくない方に簡単に説明すると、将棋界には現在8つのタイトルがあり、各棋戦で一年を通して争って挑戦者を1名決定し、挑戦者と現タイトル保持者が番勝負を行い、勝者がタイトルを得ます。タイトルを一つでも取ることは大偉業です。

[^2]: 順位戦はA級からC級2組まで5つのクラスに分かれ、1年を通してクラス内で対局をし、上位者が一つ上のクラスへ昇級、下位者が一つ下のクラスへ降級します。最上位のA級は10人しかいないトップ棋士の証であり、A級優勝者が名人(将棋界で最も伝統のあるタイトル)に挑戦します。藤井七段は現在B級2組、現名人は豊島将之名人。

[^3]: 竜王戦は1組から6組まで6つのクラスに分かれ、クラス内でトーナメント戦を行って上位者が一つ上のクラスへ昇級、下位者が一つ下のクラスへ降級します。その後、各クラスの上位者から竜王(将棋界最高タイトル)への挑戦者を決めます。順位戦との大きな違いとして、名人はA級にならなければ挑戦もできないのに対し、竜王はどのクラスにいてもチャンスがあります。藤井七段は現在3組、現竜王は豊島将之竜王。

[^4]: 王位リーグは紅組と白組2つのリーグに分かれ、王位への挑戦者を決定するリーグです。厳しい予選を抜けてリーグ入りしなければ挑戦できません。藤井七段は現在王位リーグに在籍中、現王位は木村一基王位。

[^5]: 王将リーグは王将への挑戦者を決定するリーグです。こちらも厳しい予選を抜けてリーグ入りしなければ挑戦できません。枠も少ないことから棋界屈指の難関リーグと言われています。藤井七段は現在王将リーグに在籍中、現王将は渡辺明王将。

[^6]: 8大タイトルとは別にテレビ棋戦など1年を通して優勝者を決める棋戦もあります。タイトル戦と違い優勝しても翌年もトーナメントを勝ち抜かなければ優勝できません。藤井七段は朝日杯将棋オープン戦で2連覇し、若手のみ出場の新人王戦でも優勝しています。