Chapter2では特徴量に血統情報として、馬のラベルを入れました。
これについて、少し話をしたいと思います。
まず話したいことは
「競馬において血統情報は重要である」
ということです。
これは、事実です。
現に、競馬はサラブレット競技であり、良い馬と良い馬をかけ合わせて新世代の馬を生み出してきました。もしも、競馬において血統情報が意味を持たないのであれば、牧場や生産者は数百、数千万円をかけて良い馬をかけ合わせる必要はないでしょう。
しかし、今回の話は少し異なります。
今回重要なのは、「私達が得られる血統情報は重要か?」ということです。
例えば、適当な馬の血統情報を見てみます
これはどの様な馬でも良いです。
さらに、父親や母親、祖父母といった馬の名前を選択すれば、その馬のデータが見れます。
ここでは、母親のデータを見てみます
確かに、母親の戦績が表示されます。問題はこの中の何を特徴量として持ってくるか、ということです。実際には、戦績表や獲得賞金等のデータがほしいのだけども、これが残っていない馬も多数存在します。
一つ前の血統表に戻り、適当な祖父のデータを見てみます
二世代前に遡るだけで、戦績や賞金等のデータは見れなくなりました。つまり、詳細なデータが残っていないのです。
適正レビューデータは使えるか
そして、唯一どの馬にも表示されるデータは、「適性レビュー」と書かれた、謎のデータだけです。
これは、どれほど正確なデータなのでしょう。何しろ、戦績が残っていないので、手元で検証できません。
では、このデータが使い物になるかというと、まったく使い物になりません。
当たり前ですが、数世代前のレビューと現役世代のレビューで、同じ適正値であったとしても、現役世代のほうが強いことが多そうです(競技として進化しているのであれば)。
ましてや、それぞれの馬ごとに、出場しているレースのグレードや回数が違うのだから、同じ長さの物差しで、適正値を測るのはかなり難しいです。
実際に、この適正レビューデータを学習に入れても、1ミリも精度は向上しません。これは裏で検証しました。
個人的な推測になってしまいますが、おそらく、このレビューは人間が肌感で書いているデータだと思われます。
実際、新馬や未勝利馬などは、この適正値は全く変動しない固定値です。
血統データだけを入れて学習してみる
つまり、どの様な血統データが扱えるかと言うと、血統表に書かれた名前だけです。
Chapter2では、この名前をラベル化して学習に入れてきました。
そうしたときに、次に疑問になるのはこのラベルデータが役に立つかです。
では、それを検証したいと思います。
学習データの切り分けをする際に、血統データとレース情報のみを入れてみます
予測対象は、三位以内になるかのBinary Classification
df = df.sort_values(['race_date']).reset_index(drop=True)
not_use_columns = [
'race_date', 'race_id', 'race_grade', 'name', 'jocky_name', 'odds', 'popular', 'rank', 'time', 'prize', 'tansyo_hit', 'tansyo_payout', 'hukusyo_hit', 'hukusyo_payout'
]
not_use_df = df[not_use_columns]
target_df = df.drop(columns=not_use_columns)
train_df = target_df.loc[not_use_df['race_date'] < '2020-01-01', :].reset_index(drop=True)
test_df = target_df.loc[not_use_df['race_date'] >= '2020-01-01', :].reset_index(drop=True)
from sklearn.preprocessing import StandardScaler
ped_columns = [col for col in target_df.columns if 'ped' in col]
X_columns = ['place_id', 'race_distance', 'race_type', 'race_total_prize', 'weather', 'race_condition', 'horse_count', 'waku', 'horse_number', 'sex', 'age'] + ped_columns
categoriy_columns = ['place_id', 'race_type', 'weather', 'race_condition', 'horse_count', 'waku', 'horse_number', 'sex', 'age'] + ped_columns
train_X = train_df.loc[:, X_columns]
test_X = test_df.loc[:, X_columns]
scaler = StandardScaler()
train_X = pd.DataFrame(data=scaler.fit_transform(train_X), columns=train_X.columns)
test_X = pd.DataFrame(data=scaler.transform(test_X), columns=test_X.columns)
for col in categoriy_columns:
train_X.loc[:, col] = train_df.loc[:, col].astype('int64')
test_X.loc[:, col] = test_df.loc[:, col].astype('int64')
train_y = not_use_df.loc[not_use_df['race_date'] < '2020-01-01', 'rank'].reset_index(drop=True)
test_y = not_use_df.loc[not_use_df['race_date'] >= '2020-01-01', 'rank'].reset_index(drop=True)
train_y = (train_y <= 3).astype('int64')
test_y = (test_y <= 3).astype('int64')
学習結果は次のようになりました。
train base acc : 0.7875074420784617
train acc : 0.8480295909707004
valid base acc : 0.7875375375375375
valid acc : 0.7906469461587572
test base acc : 0.7829890414949492
test acc : 0.781018395551481
テストデータの精度は、ベースラインよりも下である。つまり、この血統情報はあまり役に立つデータでは無いということです。
一応考察を書いておきます。
御存知の通り、競馬は血統競技です。つまり、ほぼすべての馬の血統が良いのです。ということは、血統は意味を持つけども、「他の馬と比較しての良し悪しには使えない可能性が高い」ということが推測されます。もちろん、遺伝子レベルでのデータがあれば役に立つ可能性は残っていますが、血統の名前データだけだと、他の馬の同じような感じなので、役に立たないのではないでしょうか。
ただ、それでもChapter2ではこの血統情報を学習に入れ続けてきました。
その理由は、血統情報だけでは意味を持たないが、他のデータと合わせて意味を持つかもしれないからです。