女子卓球レーティング

囲碁将棋などで有名な実力計算方式である"イロレーティング"を卓球に応用し、ITTFランキングでは測れない「実力」を試算しました。イロレーティングをもとに、トーナメントドローに応じたモンテカルロシミュレーションを加えた勝敗予想を提供します。さらにイロレーティングを超える「AIレーティング」を開発しています。

【テクニカル】イロレーティングからディープラーニングへ・初期実装

女子卓球レーティングのディープラーニング版を初期実装してみました。

【テクニカル】イロレーティングからディープラーニングへ・事前知識 - 女子卓球レーティングから、かなり方針転換をしています。まずは、既存のイロレーティングと同等の予想ができる状態になりました。今後が楽しみです。

1. 方針

1.1. 以前の方針

  • 誰と誰が対戦して結果はどうだったか、を時系列問題として将来予測する

1.2. 以前の方針の課題

  • 特定の人同士の対戦は年間でも存在しないか、多くても数試合しかない
  • 一方、ディープラーニングを機能させるには、数十試合のデータが必要になる

1.3. さらにわかったこと

  • ディープラーニングの入力値である「特徴量」は、解きたい問題と相関が高そうな数値を選択することが望ましい
  • 特徴量は、解きたい問題領域の専門家がカンと経験を元に選ぶか、データ分析の専門家がデータを多方面から観察することにより選ぶか、いずれにしても匠の業が必要になる

1.4. 新しい方針

  • 特徴量の候補として、イロレーティング値、ランキング、戦型などが考えられる
  • よって、まずはイロレーティング値だけをもとに、既存のイロレーティングと同等の予想ができるモデルを作り、順次、他の特徴量を付加して、予想を改善していく
  • 特定の人同士の対戦だけを並べるのではないため時系列による相関はあまり高く無い→時系列問題ではなく、通常の(勝利・敗退の)教師データあり2値分類問題として扱う

2. 実装

tf.kerasを使って、典型的な教師データあり2値分類問題の実装をしてみます。

import tensorflow as tf
import numpy as np
from tensorflow_core.python.keras.metrics import binary_accuracy
from sklearn.preprocessing import MinMaxScaler
import matplotlib.pyplot as plt

# 前処理は省略
# match_featuresは試合ごとの特徴量のリスト
# match_lablesは試合ごと正解ラベル(どちらが勝ったかを1または0で表す)のリスト
# 対象試合は2018年以降の有効試合(試合成立、レーティングやランキングが計測可能など)
# split_countで2018〜2019年を学習用、2020年1月だけを検証用と区別する

ds_features = np.array(match_features)
ds_labels = np.array(match_labels)
ms = MinMaxScaler()
ds_features = ms.fit_transform(ds_features)  # 正規化

# データセットを訓練用と検証用に分割
training_features, validation_features = np.split(ds_features, [split_count])
training_labels, validation_labels = np.split(ds_labels, [split_count])

# モデル準備
INPUT_FEATURES = ds_features.shape[1]   # 特徴量の次元
LAYER1_NEURONS = int(INPUT_FEATURES * 1.2 + 1)   # 入力次元より少し広げる
LAYER2_NEURONS = LAYER1_NEURONS
LAYER3_NEURONS = LAYER1_NEURONS  # 隠れ層は3層
OUTPUT_RESULTS = 1  # 出力は一次元
ACTIVATION = 'tanh'
model = tf.keras.models.Sequential([
    tf.keras.layers.Dense(input_shape=(INPUT_FEATURES,), units=LAYER1_NEURONS, activation=ACTIVATION),
    tf.keras.layers.Dense(units=LAYER2_NEURONS, activation=ACTIVATION),
    tf.keras.layers.Dense(units=LAYER3_NEURONS, activation=ACTIVATION),
    tf.keras.layers.Dense(units=OUTPUT_RESULTS, activation='sigmoid'),
])
LOSS = 'binary_crossentropy'
OPTIMIZER = tf.keras.optimizers.Adam   # 典型的な最適化手法
LEARNING_RATE = 0.03   # 学習係数のよくある初期値
model.compile(optimizer=OPTIMIZER(lr=LEARNING_RATE), loss=LOSS, metrics=[binary_accuracy])

# 学習
BATCH_SIZE = 30
EPOCHS = 100
result = model.fit(x=training_features, y=training_labels,
                   validation_data=(validation_features, validation_labels),
                   batch_size=BATCH_SIZE, epochs=EPOCHS, verbose=1)

# 表示
plt.plot(range(1, EPOCHS+1), result.history['binary_accuracy'], label="training")
plt.plot(range(1, EPOCHS+1), result.history['val_binary_accuracy'], label="validation")
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()
plt.show()

3. 結果

イロレーティングそのものの予想成績はイロレーティングとランキング・どちらが勝敗を正確に予想できるか - 女子卓球レーティングを参照してください。学習データとしての2018年〜2019年の試合は予想的中率72%、検証データとしての2020年1月は予想精度80%でした。この値と同等にすることが当面の目標です。なお、上記ではイロレーティング値は各月の月初の値を使っていますが、今回のディープラーニングでも同一条件としています。

こちらが結果グラフです。左から右に学習が進んでいき、各学習段階での予想精度を学習データ、検証データそれぞれについて求めています。学習データそのものに過学習していないかがわかるように、学習対象としない検証データでの精度を常に確認します。

f:id:miumima:20200224105232p:plain
結果グラフ

4. 考察と今後の展開

学習データの予想的中率は70〜71%、検証データの予想的中率は78%前後と、ほぼ目標を達成しています。もっとも、「イロレーティングが高い方が勝利する」という単純な条件を学習しただけなので、スゴい話ではありません。今後、特徴量を追加して、イロレーティング予想を上回るようになってくると、初めてスゴいと言えるようになります。