前回の第2回までで、データの前処理まで完了
Python に関しては完全な初心者だが、Google 検索だけで何とかなるもんだ
今回は、とりあえず モデルの学習・予測 まで一気に進めてみるのだ
開発環境
Anaconda3 のインストール
データの取得
ターゲットフロンティアの出力データを使用
ターゲットフロンティアのレース検索で CVS 出力
※第1回はここまで終了-------------------------------
データの前処理
CVS の読込みについて
20年分の全データを読み込んでみたら Wall time: 41.3 s
20年分の使うかもしれないデータだけを読込み
n 走前までのデータを連結
欠損地処理、データ型処理、目的変数の処理
※第2回はここまで終了-------------------------------
モデルの学習
機械学習の種類や選び方を、よく分かってないのだが、
他の方のコードでよく使われている sklearn のロジスティック回帰を使用
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
# 説明変数をdataXに格納
dataX = rd.drop(['3着以内'], axis=1)
# 目的変数をdataYに格納
dataY = rd['3着以内']
# データの分割を行う(学習用データ 0.8 評価用データ 0.2) stratify:層化抽出
X_train, X_test, y_train, y_test = train_test_split(dataX, dataY, test_size=0.2, stratify=dataY)
# 分類器を作成(ロジスティック回帰)
clf = LogisticRegression()
# 学習
clf.fit(X_train, y_train)
これだけで モデルの学習 は完了。簡単
モデルの評価
とりあえず、学習した結果から予測をしてみます
予測結果を、様々な指標で評価してみます
詳しくは ↓ を参考に
from sklearn.metrics import accuracy_score
from sklearn.metrics import confusion_matrix
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import f1_score
# 予測
y_pred = clf.predict(X_test)
# 正解率を表示
print('正解率', accuracy_score(y_test, y_pred))
# 混同行列を表示
print('混同行列\n', confusion_matrix(y_test, y_pred, labels=[1, 0]))
# 適合率を表示
print('適合率', precision_score(y_test, y_pred))
# 再現率を表示
print('再現率', recall_score(y_test, y_pred))
# F値を表示
print('F値', f1_score(y_test, y_pred))
正解率 0.7828058218782488
混同行列
[[ 707 36705]
[ 900 134828]]
適合率 0.4399502177971375
再現率 0.01889767988880573
F値 0.03623875547810041
正解率は0.7828058218782488
すごい!!と思ったが、これは4着以下と予想して4着以下になったのも含んでいるのだ
「この馬はこない!」と予想して「予想が、当たった!当たった!」と喜んでいるのと同じなのだ
再現率は0.01889767988880573
再現率は、実際に 3着以内 だった中で、どの程度正しく予測できているかの割合
混合行列の数字から ↓ の数式で算出される
\frac{707}{707+36705}
98%以上の取りこぼしがあるので、使い物にならん💦
3着以内のデータ数と 4着以下のデータ数の不均衡を修正
アンダーサンプリングの最適化
4着以下のデータ比率を 2倍
学習データの 3着以内と 4着以下のデータ比率を調整して改善させよう(アンダーサンプリングというらしい)
アンダーサンプリングを最適化する方法があるのかもしれないが、わからないのでマニュアルで検証
とりあえず、4着以下のデータ比率を 2倍にすると
from imblearn.under_sampling import RandomUnderSampler
# 学習データをアンダーサンプリング
f_count = y_train.value_counts()[1] * 2
t_count = y_train.value_counts()[1]
rus = RandomUnderSampler(sampling_strategy={0:f_count, 1:t_count})
X_train_rus, y_train_rus = rus.fit_sample(X_train, y_train)
# 学習
clf.fit(X_train_rus, y_train_rus)
# 予測
y_pred = clf.predict(X_test)
# 正解率を表示
print('アンダーサンプリング')
print('正解率', accuracy_score(y_test, y_pred))
# 混同行列を表示
print('混同行列\n', confusion_matrix(y_test, y_pred, labels=[1, 0]))
# 適合率を表示
print('適合率', precision_score(y_test, y_pred))
# 再現率を表示
print('再現率', recall_score(y_test, y_pred))
# F値を表示
print('F値', f1_score(y_test, y_pred))
アンダーサンプリング 1:2
正解率 0.7591140117823727
混同行列
[[ 13926 23486]
[ 18221 117507]]
適合率 0.4331974989890192
再現率 0.3722335079653587
F値 0.40040828649060506
正解率は0.7591140117823727
、僅かに下がったが、
再現率は0.3722335079653587
、かなり良化
4着以下のデータ比率を 1倍
アンダーサンプリング 1:1
正解率 0.6473085364444958
混同行列
[[27155 10257]
[50808 84920]]
適合率 0.34830624783551173
再現率 0.7258366299583021
F値 0.47072589382448543
正解率は0.6473085364444958
、かなり低下、
適合率は0.34830624783551173
、かなり低下
再現率は0.7258366299583021
、かなり良化
これは、取りこぼしは少なくなるが負ける回数も増えるということか?
実際に馬券を買ったときのシミュレーションしてみないとなんとも言えないが、比率は 2倍のほうが良い感じ
馬券シミュレーションの段階で再検証ということで・・・
とりあえず 2倍で続行
説明変数の標準化
今後、値が大きな説明変数などを使用することも考え標準化を実施
from sklearn.preprocessing import StandardScaler
# 説明変数を標準化
sc = StandardScaler()
X_train_rus_std = pd.DataFrame(sc.fit_transform(X_train_rus), columns=X_train_rus.columns)
X_test_std = pd.DataFrame(sc.transform(X_test), columns=X_test.columns)
# 学習
clf.fit(X_train_rus_std, y_train_rus)
# 予測
y_pred = clf.predict(X_test_std)
# 正解率を表示
print('アンダーサンプリング,標準化')
print('正解率', accuracy_score(y_test, y_pred))
# 混同行列を表示
print('混同行列\n', confusion_matrix(y_test, y_pred, labels=[1, 0]))
# 適合率を表示
print('適合率', precision_score(y_test, y_pred))
# 再現率を表示
print('再現率', recall_score(y_test, y_pred))
# F値を表示
print('F値', f1_score(y_test, y_pred))
アンダーサンプリング,標準化
正解率 0.7581668014323669
混同行列
[[ 14143 23269]
[ 18602 117126]]
適合率 0.43191326920140477
再現率 0.37803378595103176
F値 0.40318143592228856
今回、標準化してもしなくても結果に影響はなし
今後、どのような説明変数を追加するかわからないので標準化は組み込んでおくのだ。
第3回はここまで