この記事を読む前に「Kerasで実現するディープラーニングによるAI競艇予想(準備編)」の記事を先に読んでください。その中には、機械学習の基礎知識や、学習データで使う説明変数の内容など、他のデータ分析方法と共通する説明が含まれています。
多クラス分類(multiclass)
「多クラス分類」は目的変数を多クラスに分類する方法です。「二値分類」の三値以上版みたいなイメージ。
ここに公開するPythonのソースコードは「正解率・適合率・再現率・F値」の評価指標を計算する機能を実装しています。学習データを作るSQLで目的変数の項目名を「target」にすれば、オリジナルの学習データで分析する場合でもそのまま使えます。
ソースコードは学習用と予測用に分けてます。
欠損値(null)は、SQLで何らかの値(0など)に変換しておくことを前提にしてます。欠損値についてPythonでは何もしてないってことです。
学習用ソースコード
以下が「多クラス分類」で学習するPythonのソースコードです。この学習用ソースコードのファイル名は「dl_multiclass_train.py」とします。
PythonのソースコードはUTF-8で保存する必要があります。何のこっちゃ分からん場合は、このページの最後の、有料会員限定のダウンロードリンクからもファイルをダウンロードできます。
ソースコードはQiitaの記事から簡単にコピーできます。
※ソースコードの右上にあるアイコンをクリックしてください。
https://qiita.com/PC-KYOTEI/items/55b35cc3ed5921d176d8
import joblib
import numpy as np
import pandas as pd
from keras.layers import Dense, Dropout
from keras.models import Sequential
from keras.utils import to_categorical
from sklearn.metrics import classification_report, roc_auc_score
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
# CSVファイル読み込み
in_file_name = 'dl_multiclass_train.csv'
df = pd.read_csv(in_file_name, encoding='SHIFT_JIS')
# 説明変数(x)と目的変数(y)を設定
target = 'target'
x = df.drop(target, axis=1)
y = df[target]
# 訓練データとテストデータを分割
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42)
# 特徴量の標準化
scaler = StandardScaler()
x_train = scaler.fit_transform(x_train)
x_test = scaler.transform(x_test)
# スケーラーを保存
joblib.dump(scaler, 'multiclass_scaler.joblib')
# 目的変数をカテゴリカルに変換
num_classes = len(y.unique()) # クラスの数を自動で検出
y_train = to_categorical(y_train, num_classes)
y_test = to_categorical(y_test, num_classes)
# モデルの構築
model = Sequential()
model.add(Dense(128, input_dim=x_train.shape[1], activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(64, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))
# モデルのコンパイル
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
# モデルの学習
model.fit(x_train, y_train, epochs=50, batch_size=32, validation_data=(x_test, y_test))
# モデルをファイルに保存
model.save('multiclass_model.h5')
# 評価指標
loss, accuracy = model.evaluate(x_test, y_test)
# 正解率、適合率、再現率、F1
y_probs = model.predict(x_test)
y_pred = np.argmax(y_probs, axis=1) # 予測クラス
y_true = np.argmax(y_test, axis=1) # 実際のクラス
# AUC
auc = roc_auc_score(y_test, y_probs, average='macro', multi_class='ovr')
print(f'正解率 = {accuracy:.4f}')
print(f'AUC = {auc:.4f}')
print(classification_report(y_true, y_pred))
学習データを作る
説明変数は他の分析方法と共通にしました。内容は「Kerasで実現するディープラーニングによるAI競艇予想(準備編)」の記事を見てください。学習データのファイル名は「dl_multiclass_train.csv」とします。
今回のサンプルでは目的変数の「着順」を、次のように分類してみます。
- 1着→2
- 2〜3着→1
- 上記以外→0
このページの最後に、サンプルのSQLを有料会員に公開しています。ユーザーがカスタマイズして利用することも可能ですし、SQLを学習したい方の参考にもなります。
Kerasに学習させる
今回の例では、Cドライブの直下に「pckyotei」というフォルダを作って、
- 学習データ(dl_multiclass_train.csv)
- 学習用ソースコード(dl_multiclass_train.py)
2つのファイルを置きます。こういう状態です。
そして、コマンドプロンプトを起動し、次の2つのコマンドを「1行ずつ」実行してください。
cd C:\pckyotei
python dl_multiclass_train.py
Kerasが学習を開始します。処理が終わると評価指標を表示します。
モデルを評価する
今回のサンプルでは、次の3つの評価指標を表示します。
- 「正解率」= 全てのサンプルを正解した割合
- 「適合率」= 1と予測したサンプルのうち、実際に1であった割合
- 「再現率」= 実際に1であるサンプルのうち、1と予測した割合
- 「F値」= 適合率と再現率の調和平均を表す指標
- 「AUC」= ROC曲線の下の面積を示し、1に近いほど分類精度が高い
今回のモデルでは、このような結果になりました。これを競艇場ごとに分析したら、もっと精度の高いモデルに出来るかもしれません。多クラス分類の評価指標は、この他にもあるのでググって研究してください。
このモデルを「multiclass_model.h5」に、スケーラーを「multiclass_scaler.joblib」に保存しています。このファイルは予想するとき使います。
これを使って明日のレースを予想させます。
予測用ソースコード
以下が「多クラス分類」で予想するPythonのソースコードです。
PythonのソースコードはUTF-8で保存する必要があります。何のこっちゃ分からん場合は、このページの最後の、有料会員限定のダウンロードリンクからもファイルをダウンロードできます。
ソースコードはQiitaの記事から簡単にコピーできます。
※ソースコードの右上にあるアイコンをクリックしてください。
https://qiita.com/PC-KYOTEI/items/55b35cc3ed5921d176d8
import joblib
import numpy as np
import pandas as pd
import os
import sys
from keras.models import load_model
# 出走表ファイル読み込み
fname = sys.argv[1]
x_test = np.loadtxt(fname, delimiter=',', skiprows=1)
# 1行だけの場合でも2次元配列に変換
if x_test.ndim == 1:
x_test = x_test.reshape(1, -1)
# モデル読み込み
model = load_model('multiclass_model.h5')
scaler = joblib.load('multiclass_scaler.joblib')
# 特徴量の標準化
scaled = scaler.transform(x_test)
# データの予測
y_pred = model.predict(scaled)
# 拡張子を除いたファイル名を取得
fname = os.path.splitext(os.path.basename(fname))[0]
# 予測値を出力
pred_classes = np.argmax(y_pred, axis=1)
df = pd.DataFrame(pred_classes, columns=['予測値'])
df.to_csv(fname + '_pred.csv', encoding='SHIFT_JIS', index=False)
# 予測確率を出力
df = pd.DataFrame(y_pred, columns=[f'{i}の確率' for i in range(y_pred.shape[1])])
df.to_csv(fname + '_prob.csv', encoding='SHIFT_JIS', index=False)
出走表データを作る
予測させる出走表データは、学習データ作成のSQLと出力後のファイルを少し改造すれば作れます。学習データとの違いは次の2つです。
- SQLで目的変数「target」の項目を消す。
- SQLで予想するレースでレコードの抽出条件を設定する。
出走表データのファイル名は何でも良いですが、ここでは「レースID(※1).csv」とします。
今回のサンプルでは「2022/10/25(火)常滑12R 第69回ボートレースダービー(SG)」を予想してみます。
(※1)レースID | 年月日場R yyyymmddjjrr(12桁) |
---|
このページの最後に、サンプルのSQLを有料会員に公開しています。ユーザーがカスタマイズして利用することも可能ですし、SQLを学習したい方の参考にもなります。
予測(予想)させる
先ほどと同じ「pckyotei」というフォルダに、
- 出走表(レースID(※1).csv)
- モデル(multiclass_model.h5)
- スケーラー(multiclass_scaler.joblib)
- 予測用ソースコード(dl_multiclass_pred.py)
3つのファイルを置きます。こういう状態です。
そして、コマンドプロンプトを起動し、次の2つのコマンドを「1行ずつ」実行してください。2番目は、予測用ソースコードの後に、半角スペースと出走表のファイル名です。
cd C:\pckyotei
python dl_multiclass_pred.py 202210250812.csv
処理が終わると2つのファイルが出力されます。「予測値」と「確率」のファイルです。
- レースID(※1)_pred.csv (予測値)
- レースID(※1)_prob.csv (確率)
このファイルには数値データしか含まれていないので、分かりにくいかもしれませんが、出走表データと同じ艇番の昇順で出力されます。舟券を買うときは、SQLで艇番とレーサー氏名だけの出走表をCSVに出力して、そこへ貼り付けて確率で並べ替えると便利です。例えば、こんな感じです。
「多クラス分類」による競艇予想AIの話は以上です。
今回のサンプルはあくまで1つの「サンプル」でしかありません。完成させるのはユーザーのあなたです。
「Pythonデータ登録」画面のクラス数について
クラス数は、目的変数の分類数と一致する必要があります。例えば、目的変数を0から2までの範囲で分類した場合、クラス数は「3」となります。
df = pd.DataFrame({'0の確率':y_prob[:,0], '1の確率':y_prob[:,1], '2の確率':y_prob[:,2], '3の確率':y_prob[:,3]})