LoginSignup
0
2

JBCクラシックの予想モデルをPytorchで作ってみる(1)

Posted at

pytorchの学習がてら、JBCクラシックの予想モデルを作ってみました
pytorchで競馬予想作ってみた系の記事が見当たらなかったので記事を書いてみます。

概要

JBCの1着馬をpytorchで予想するプログラムを作成する。

作成方針

ワインの品種を推測する記事があったので、こちらの記事を参考に1着馬になる確率を推測するように応用する。
各出走馬の1着になる確率を出し、最も高い数値を出した馬を◎にする。

データの収集

netkeibaからスクレイピングしてデータ収集しました。
具体的なコードはネット上に多数転がっているので当記事では記載しませんが、結構面倒な作業となります。

入力

・説明変数

ラベル 内容
horse_id 馬id
sex 性別
age 年齢
dateforda 日付
track 競馬場
weather 天候
race_num レース番号
horse_num_anim 頭数
horse_num 馬番
odds オッズ
popularity 人気
jockey 騎手
weight 馬体重
dirt_grass 芝かダートか
distance 距離
condition 馬場コンディション
same_track 同一競馬場かどうか
g1_age3 3歳G1かどうか
g2_age3 3歳G2かどうか
g3_age3 3歳G3かどうか
g1_age4 古馬G1かどうか
g2_age4 古馬G2かどうか
g3_age4 古馬G3かどうか

目的変数

ラベル 内容
order 順位

これらを1800〜2100mのダートG1を対象にデータ収集しました。
・訓練データ:過去5戦
・テストデータ:ダートG1レース
としています

予測モデル

mlp_pytorch.rb
import pandas as pd
import numpy as np

# pytorch
import torch
import torch.nn as nn
import torch.optim as optim

#参考
#https://qiita.com/__Rossi__/items/a0ea3a8d6e24d0755737

#ここに大量のレースをベタ書きする
lists =[
    "CHAMPIONSCUP_2018",
]

jbc_all_lists_train = pd.DataFrame()
jbc_all_lists_test = pd.DataFrame()

for train_or_test in range (0,2):
    if(train_or_test == 0):
        jbc_all_lists_tmp = jbc_all_lists_train
        TRAIN_OR_TEST = 'train_'
    else:
        jbc_all_lists_tmp = jbc_all_lists_test
        TRAIN_OR_TEST = 'test_'
    for list in lists:
        try:
            horse_info_new_path ='/home/xxx/workspace/vscode/horserace/python_ci/csv/horse_id_new/JBC2022/'+TRAIN_OR_TEST+list+'.csv'
            jbc_2021_df = pd.read_csv(horse_info_new_path,index_col=0)
            #print(jbc_2021_df)

            jbc_all_lists_tmp = jbc_all_lists_tmp.append(jbc_2021_df)
        except:
            print("file not found")

    horse_info_new_path ='/home/xxx/workspace/vscode/horserace/python_ci/csv/horse_id_new/JBC2022/JBC_CATALL.csv'

    #jbc_all_lists_tmp = jbc_all_lists_tmp.drop(columns='horse_id')
    #jbc_all_lists_tmp = jbc_all_lists_tmp.drop(columns='jockey')
    jbc_all_lists_tmp = jbc_all_lists_tmp.drop(columns='date')
    jbc_all_lists_tmp = jbc_all_lists_tmp.drop(columns='weight_incdec')
    jbc_all_lists_tmp = jbc_all_lists_tmp.drop(columns='3furlong')
    #jbc_all_lists_tmp = jbc_all_lists_tmp.drop(columns='distance')
    jbc_all_lists_tmp = jbc_all_lists_tmp.drop(columns='horse_weight')

    #print(jbc_all_lists_tmp)

    f_horsediv = lambda x: x / 10000000
    jbc_all_lists_tmp['horse_id'] = jbc_all_lists_tmp['horse_id'].apply(f_horsediv)

    f_distancediv = lambda x: x / 100
    jbc_all_lists_tmp['distance'] = jbc_all_lists_tmp['distance'].apply(f_distancediv)

    f_jockey = lambda x: x / 100
    jbc_all_lists_tmp['jockey'] = jbc_all_lists_tmp['jockey'].apply(f_jockey)

    f_money = lambda x: x / 100
    jbc_all_lists_tmp['money'] = jbc_all_lists_tmp['money'].apply(f_money)

    f_dateda = lambda x: x / 100
    jbc_all_lists_tmp['dateforda'] = jbc_all_lists_tmp['dateforda'].apply(f_dateda)

    get_odd_even = lambda x: 10000 + x if x % 2 == 0 else x
    f_dateda = lambda x: x / 100
    jbc_all_lists_tmp['jockey'] = jbc_all_lists_tmp['jockey'].apply(f_dateda)

    #jbc_all_lists_tmp = jbc_all_lists_tmp.drop(columns='horse_id')
    jbc_all_lists_tmp = jbc_all_lists_tmp.drop(columns='money')
    jbc_all_lists_tmp = jbc_all_lists_tmp.drop(columns='time')
    #jbc_all_lists_tmp = jbc_all_lists_tmp.drop(columns='weight')
    #jbc_all_lists_tmp = jbc_all_lists_tmp.drop(columns='jockey')

    jbc_all_lists = jbc_all_lists_tmp

    print(jbc_all_lists)

    if train_or_test == 0:
        t_train = torch.Tensor(jbc_all_lists['order'].values.astype(np.int64))
        x_train = torch.Tensor(jbc_all_lists.drop('order', axis=1).values.astype(np.float32))
    else:
        t_test = torch.Tensor(jbc_all_lists['order'].values.astype(np.int64))
        x_test = torch.Tensor(jbc_all_lists.drop('order', axis=1).values.astype(np.float32))

# numpyからtensorに変換
x_train = torch.tensor(x_train, dtype=torch.float32)
t_train = torch.tensor(t_train, dtype=torch.int64) 
x_test = torch.tensor(x_test, dtype=torch.float32)
t_test = torch.tensor(t_test, dtype=torch.int64) 

# シードを固定
torch.manual_seed(100)

net = nn.Sequential(
    nn.Linear(23 ,128),  
    nn.ReLU(),
    nn.Linear(128 ,128),  
    nn.ReLU(),
    nn.Linear(128 ,128),  
    nn.ReLU(),  
    nn.Linear(128 ,32),  
    nn.ReLU(),          
    nn.Linear(32, 8),
    nn.ReLU(),
    nn.Linear(8, 2)
)
net.train() #学習モードに切り替え

# 交差エントロピー誤差関数
loss_fnc = nn.CrossEntropyLoss()

# SGD
optimizer = optim.SGD(net.parameters(), lr=0.1)  # 学習率は0.01

# 損失のログ
record_loss_train = []
record_loss_test = []

# 1000エポック学習
for i in range(2000):

    # 勾配を0に
    optimizer.zero_grad()
    
    # 順伝播
    y_train = net(x_train)
    y_test = net(x_test)
    
    # 誤差を求める
    loss_train = loss_fnc(y_train, t_train)
    loss_test = loss_fnc(y_test, t_test)
    record_loss_train.append(loss_train.item())
    record_loss_test.append(loss_test.item())

    # 逆伝播(勾配を求める)
    loss_train.backward()
    
    # パラメータの更新
    optimizer.step()

    if i%100 == 0:
        print("Epoch:", i, "Loss_Train:", loss_train.item(), "Loss_Test:", loss_test.item())

y_test = net(x_test)
#print(y_test)
count = (y_test.argmax(1) == t_test).sum().item()
print("正解率:", str(count/len(y_test)*100) + "%")

sample = torch.tensor([
    [ 202.0104376    ,3   ,3     ,85.00,45       ,6      ,11.0             ,15         ,2    ,1.0         ,1.0        ,54.04    ,55.0          ,2      ,20.0         ,4            ,1       ,0       ,0       ,0       ,1       ,0       ,0],     
    ],dtype=torch.float32)

net.eval() #推論モードに切り替え
for i in range (0,1):
    y_test2 = net(sample[i])
    y_test2 = y_test2.softmax(dim=0)
    print(y_test2)

訓練データとテストデータで事前に学習し、それを基に推論するプログラムを作成しました。
まだ絶賛作成中でベタ書きなのと実験繰り返し状態ですので、今後改修を進めます。

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2