TadaoYamaokaの開発日記

個人開発しているスマホアプリや将棋AIの開発ネタを中心に書いていきます。

将棋倶楽部24万局集の統計

昨日の記事で書いた通り、「将棋倶楽部24万局集」のデータベースを読めるようになったので、棋譜の統計情報を調べた。

期間

1999年5月から2002年2月のデータが格納されている。
ほとんどは、2001年9月以降のデータである。

count                  240000
unique                    159
top       2001-12-02 00:00:00
freq                     4234
first     1999-05-25 00:00:00
last      2002-02-27 00:00:00
Name: date, dtype: object


レーティングの分布

ヒストグラム

全体的に幅広いレーティングのデータが格納されている。
しかし、特定のレーティング帯の数が多くなっているため、無作為に抽出されているわけではなさそうである。
書籍の説明によると「好局24万局を選んで収録した」とあるので、このデータで分析した統計が実際の人間の対局の統計を表しているとも言えなそうである。

対局者間のレーティングの散布図

近いレーティング同士で対局が行われている。

対局者間のレーティング差

レーティングが0のデータを除いた、対局者間のレーティング差は、中央値0、標準偏差109で、約68%がレーティング差109の間で対局が行われている。

count    239957.000000
mean         -0.808349
std         108.639578
min       -1949.000000
25%         -50.000000
50%           0.000000
75%          49.000000
max         399.000000


対局者

対局者の出現頻度

ほとんどは1回のみで、ユニーク数は16237で、最頻値は666である。

count       480000
unique       16237
top       koubekko
freq           666


手数

手数の平均は112手、標準偏差は23である。
特定の手数の頻度が高い理由は不明だが、収録されているデータの偏りのためと思われる。
手順が重複した棋譜はなく、すべて異なる棋譜であった。

count    240000.000000
mean        112.057221
std          24.993857
min          44.000000
25%          94.000000
50%         107.000000
75%         125.000000
max         256.000000


先手勝率

棋譜全体の先手勝率は、50.34%である。

count    240000.000000
mean          0.503396
母比率に関する仮説検定

標本数が十分に大きい場合、下記統計量zは標準正規分布に従う。
\displaystyle
z=\frac{\hat{p} - p_0}{\sqrt{p_0(1-p_0)/n}} \sim N(0, 1)
帰無仮説を先手と後手の勝率が等しい(0.5)とすると、
\begin{aligned}
z &= \frac{0.503396 - 0.5}{\sqrt{0.5(1-0.5)/240000}} \\
&= 3.327386866596624
\end{aligned}
有意水準 片側5%の場合、z\geq1.65なので、帰無仮説は棄却される。
よって、先手の勝率は有意に高い。ただし、その差は0.34%とわずかである。
p値は、0.00044である。

戦型

データベースでは戦型が分類されている。
その戦型別の統計を調べた。
なお、戦型の分類基準は不明である。

戦型別の頻度

戦型別の頻度は以下の通り。

頻度は四間飛車に偏っている。
これが好局を選んだ結果なのか、元の分布が四間飛車に偏っていたのかは不明である。

戦型別先手勝率

戦型別の先手勝率は以下の通り。

戦型別に勝率に違いがあるように見えるが、標本数が異なっているため単純に比較できない。
独立性の検定を行うと、p値は0.4008016431231313となり、勝敗は戦型によらず独立であるという帰無仮説は棄却できない。
よって、戦型によって勝率差があるとは言えない。

from scipy.stats import chi2_contingency
df3 = pd.crosstab(df['openingstr'], df['endcode']).sort_values(by=1, ascending=False)
chi2, p, dof, expected = chi2_contingency(df3, correction=False)
chi2, p, dof
Out: (14.673921304473138, 0.4008016431231313, 14)
手数

戦型別の手数の平均は以下の通り。

戦型により手数の違いがあるように見える。
最も手数が長い戦型はひねり飛車で、短い戦型は横歩取りである。

独立性の検定を行うと、p値は0.0で、手数は戦型によらず独立であるという帰無仮説は棄却される。
よって、戦型により手数に有意に違いがあると言える。

from scipy.stats import chi2_contingency
df4 = pd.crosstab(df['openingstr'], df['len'] // 8)
chi2, p, dof, expected = chi2_contingency(df4, correction=False)
chi2, p, dof
Out: (3607.020081496307, 0.0, 378)

レーティングと手数

200で区切ったレーティング帯別の手数の平均は以下の通り。

1200~2000の中間のレーティングで手数が長くなり、レーティングが低くても高くても手数は短くなっている。

独立性の検定を行うと、p値は0.0で、手数はレーティング帯によらず独立であるという帰無仮説は棄却される。
よって、レーティング帯により手数に有意に違いがあると言える。

from scipy.stats import chi2_contingency
df7 = pd.crosstab(df5['rating200'], df5['len'] // 8)
chi2, p, dof, expected = chi2_contingency(df7, correction=False)
chi2, p, dof
Out: (29923.955884650593, 0.0, 351)

まとめ

将棋倶楽部24万局集を使用するにあたって、データの傾向を把握しておきたかったので統計情報を調べた。
戦型別の勝率に違いがないことや、戦型別に手数が異なること、レーティング帯により手数が異なることなど興味深い結果が得られた。
なお、無作為に抽出したデータではなく収録されているデータには偏りがある可能性がありそうなため、このデータを使用する場合は注意が必要である。