lightGBMでボート予想AIを作ってみた②|データの取得と前処理編

Boat race

今回の内容

今回は、前回CSV形式で作ったデータの前処理と、新たな特徴量を作っていきます。

前回の記事はこちらから。

前処理と特徴量作成

さて、さっそく前処理と特徴量の作成をしていきます。

先に私がどのように完成したAIを運用しているのかというと、

  1. 過去8ヶ月分のデータを取得してモデルを作る。
  2. 月が変わったタイミングで先月のデータを追加、最も古いデータを除いた8ヶ月分のデータで再度学習。

というような形で運用しています。

なので、1ヶ月ごとに以下のファイルを実行しデータをアップデートしています。

選手の個人データを作っていきます。

def make_csv_personal():
    import pandas as pd
    import os
    import numpy as np
    
    csv_rsult_dir = '/Users/tom/boat_pred/data_csv/data_result_csv'
    csv_result_file = os.listdir(csv_rsult_dir)
    csv_result_file.sort()
    csv_result_file.remove('.ipynb_checkpoints')
    
    df_r = []
    for i in csv_result_file[-8:]:
        d = pd.read_csv(f'/Users/tom/boat_pred/data_csv/data_result_csv/{i}')
        df_r.append(d)
    
    df_results = pd.concat(df_r)
    df_results = df_results.reset_index(drop=True)
    
    
    num = df_results['選手登番'].unique()
    num.sort()
    
    id = df_results['id'].unique()
    
    ## STランク付
    re_df = []
    for i in id:
        o_df = df_results[df_results['id']==i]
        o_df = o_df.sort_values('ST')
        o_df['STR'] = np.arange(1,7)
        o_df.sort_values('艇番', inplace=True)
        re_df.append(o_df)
    
    #再生
    df_results = pd.concat(re_df)
    
    ## 平均ST
    lis = []
    lis1 = []
    lis2 = []
    lis3 = []
    lis4 = []
    lis5 = []
    lis6 = []
    avest_all = []
    avest1 = []
    avest2 = []
    avest3 = []
    avest4 = []
    avest5 = []
    avest6 = []
    for i in num:
        st=df_results[df_results['選手登番']==i]['ST'].values
        st1 = df_results[(df_results['選手登番']==i)&(df_results['艇番']==1)]['ST'].values
        st2 = df_results[(df_results['選手登番']==i)&(df_results['艇番']==2)]['ST'].values
        st3 = df_results[(df_results['選手登番']==i)&(df_results['艇番']==3)]['ST'].values
        st4 = df_results[(df_results['選手登番']==i)&(df_results['艇番']==4)]['ST'].values
        st5 = df_results[(df_results['選手登番']==i)&(df_results['艇番']==5)]['ST'].values
        st6 = df_results[(df_results['選手登番']==i)&(df_results['艇番']==6)]['ST'].values
        lis.append(np.nanmean(st))
        lis1.append(np.nanmean(st1))
        lis2.append(np.nanmean(st2))
        lis3.append(np.nanmean(st3))
        lis4.append(np.nanmean(st4))
        lis5.append(np.nanmean(st5))
        lis6.append(np.nanmean(st6))
    # 艇番STR
        win = df_results[df_results['選手登番']==i]['STR'].values
        avest_all.append(np.nanmean(win))
        #1枠
        win = df_results[(df_results['選手登番']==i)&(df_results['艇番']==1)]['STR'].values
        avest1.append(np.nanmean(win))
        #1枠
        win = df_results[(df_results['選手登番']==i)&(df_results['艇番']==2)]['STR'].values
        avest2.append(np.nanmean(win))
        #1枠
        win = df_results[(df_results['選手登番']==i)&(df_results['艇番']==3)]['STR'].values
        avest3.append(np.nanmean(win))
        #1枠
        win = df_results[(df_results['選手登番']==i)&(df_results['艇番']==4)]['STR'].values
        avest4.append(np.nanmean(win))
        #1枠
        win = df_results[(df_results['選手登番']==i)&(df_results['艇番']==5)]['STR'].values
        avest5.append(np.nanmean(win))
        #1枠
        win = df_results[(df_results['選手登番']==i)&(df_results['艇番']==6)]['STR'].values
        avest6.append(np.nanmean(win))
    
    ## 連対率
    df_results['1着'] = df_results['着順'].apply(lambda x : 0 if x == 1 else 1)
    df_results['2連対'] = df_results['着順'].apply(lambda x : 0 if x <= 2 else 1)
    df_results['3連対'] = df_results['着順'].apply(lambda x : 0 if x <= 3 else 1)
    
    waku1rentai1 = []
    waku1rentai2 = []
    waku1rentai3 = []
    waku2rentai1 = []
    waku2rentai2 = []
    waku2rentai3 = []
    waku3rentai1 = []
    waku3rentai2 = []
    waku3rentai3 = []
    waku4rentai1 = []
    waku4rentai2 = []
    waku4rentai3 = []
    waku5rentai1 = []
    waku5rentai2 = []
    waku5rentai3 = []
    waku6rentai1 = []
    waku6rentai2 = []
    waku6rentai3 = []
    for i in num:
        #1枠
        try:
            win = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==1)&(df_results['1着']==0)])
            total = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==1)])
            winpercent11 = win/total
            waku1rentai1.append(winpercent11)
        except ZeroDivisionError:
            waku1rentai1.append(0)
    ## 2連対
        try:
            win = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==1)&(df_results['2連対']==0)])
            total = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==1)])
            winpercent12 = win/total
            waku1rentai2.append(winpercent12)
        except ZeroDivisionError:
            waku1rentai2.append(0)
    ## 3連対        
        try:
            win = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==1)&(df_results['3連対']==0)])
            total = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==1)])
            winpercent13 = win/total
            waku1rentai3.append(winpercent13)
        except ZeroDivisionError:
            waku1rentai3.append(0)
    
    #2枠
        try:
            win = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==2)&(df_results['1着']==0)])
            total = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==2)])
            winpercent21 = win/total
            waku2rentai1.append(winpercent21)
        except ZeroDivisionError:
            waku2rentai1.append(0)
    ## 2連対
        try:
            win = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==2)&(df_results['2連対']==0)])
            total = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==2)])
            winpercent22 = win/total
            waku2rentai2.append(winpercent22)
        except ZeroDivisionError:
            waku2rentai2.append(0)
    ## 3連対        
        try:
            win = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==2)&(df_results['3連対']==0)])
            total = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==2)])
            winpercent23 = win/total
            waku2rentai3.append(winpercent23)
        except ZeroDivisionError:
            waku2rentai3.append(0)
    #3枠
        try:
            win = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==3)&(df_results['1着']==0)])
            total = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==3)])
            winpercent31 = win/total
            waku3rentai1.append(winpercent31)
        except ZeroDivisionError:
            waku3rentai1.append(0)
    ## 2連対
        try:
            win = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==3)&(df_results['2連対']==0)])
            total = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==3)])
            winpercent32 = win/total
            waku3rentai2.append(winpercent32)
        except ZeroDivisionError:
            waku3rentai2.append(0)
    ## 3連対        
        try:
            win = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==3)&(df_results['3連対']==0)])
            total = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==3)])
            winpercent33 = win/total
            waku3rentai3.append(winpercent33)
        except ZeroDivisionError:
            waku3rentai3.append(0)
    #4枠
        try:
            win = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==4)&(df_results['1着']==0)])
            total = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==4)])
            winpercent41 = win/total
            waku4rentai1.append(winpercent41)
        except ZeroDivisionError:
            waku4rentai1.append(0)
    ## 2連対
        try:
            win = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==4)&(df_results['2連対']==0)])
            total = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==4)])
            winpercent42 = win/total
            waku4rentai2.append(winpercent42)
        except ZeroDivisionError:
            waku4rentai2.append(0)
    ## 3連対        
        try:
            win = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==4)&(df_results['3連対']==0)])
            total = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==4)])
            winpercent43 = win/total
            waku4rentai3.append(winpercent43)
        except ZeroDivisionError:
            waku4rentai3.append(0)
    #5枠
        try:
            win = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==5)&(df_results['1着']==0)])
            total = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==5)])
            winpercent51 = win/total
            waku5rentai1.append(winpercent51)
        except ZeroDivisionError:
            waku5rentai1.append(0)
    ## 2連対
        try:
            win = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==5)&(df_results['2連対']==0)])
            total = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==5)])
            winpercent52 = win/total
            waku5rentai2.append(winpercent52)
        except ZeroDivisionError:
            waku5rentai2.append(0)
    ## 3連対        
        try:
            win = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==5)&(df_results['3連対']==0)])
            total = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==5)])
            winpercent53 = win/total
            waku5rentai3.append(winpercent53)
        except ZeroDivisionError:
            waku5rentai3.append(0)
    
    #6枠
        try:
            win = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==6)&(df_results['1着']==0)])
            total = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==6)])
            winpercent61 = win/total
            waku6rentai1.append(winpercent61)
        except ZeroDivisionError:
            waku6rentai1.append(0)
    ## 2連対
        try:
            win = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==6)&(df_results['2連対']==0)])
            total = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==6)])
            winpercent62 = win/total
            waku6rentai2.append(winpercent62)
        except ZeroDivisionError:
            waku6rentai2.append(0)
    ## 3連対        
        try:
            win = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==6)&(df_results['3連対']==0)])
            total = len(df_results[(df_results['選手登番']==i)&(df_results['艇番']==6)])
            winpercent63 = win/total
            waku6rentai3.append(winpercent63)
        except ZeroDivisionError:
            waku6rentai3.append(0)
    
    st_data = pd.DataFrame({'選手登番':num,
                            '1枠1着率':waku1rentai1,
                            '1枠2連対率':waku1rentai2,
                            '1枠3連対率':waku1rentai3,
                            '2枠1着率':waku2rentai1,
                            '2枠2連対率':waku2rentai2,
                            '2枠3連対率':waku2rentai3,
                            '3枠1着率':waku3rentai1,
                            '3枠2連対率':waku3rentai2,
                            '3枠3連対率':waku3rentai3,
                            '4枠1着率':waku4rentai1,
                            '4枠2連対率':waku4rentai2,
                            '4枠3連対率':waku4rentai3,
                            '5枠1着率':waku5rentai1,
                            '5枠2連対率':waku5rentai2,
                            '5枠3連対率':waku5rentai3,
                            '6枠1着率':waku6rentai1,
                            '6枠2連対率':waku6rentai2,
                            '6枠3連対率':waku6rentai3,
                            '平均ST順位':avest_all,
                            '1枠ST順位':avest1,
                            '2枠ST順位':avest2,
                            '3枠ST順位':avest3,
                            '4枠ST順位':avest4,
                            '5枠ST順位':avest5,
                            '6枠ST順位':avest6,
                            '平均ST':lis,
                            '1枠ST':lis1,
                            '2枠ST':lis2,
                            '3枠ST':lis3,
                            '4枠ST':lis4,
                            '5枠ST':lis5,
                            '6枠ST':lis6})
    st_data.to_csv('/Users/tom/boat_pred/data_csv/personal_data.csv',index=False)
make_csv_personal()

うーむ。。長い。単調。わかりづらい。

悪いコードのお手本のようだ!

簡単に説明すると’csv_rsult_dir’に1ヶ月分のデータが8つ、8ヶ月分。それをdf_resultsとしてデータフレーム化。”#STランク付”でスタート順位をつける。あとは”#艇番STR”で艇番毎にもスタート順位をつけました。”#連対率”のところで枠別の連対率を計算しto_csvで保存します。

これで選手の平均スタート、枠番別の連対率、スタート順位等、元データをより詳しいデータにすることができました。

それにしてももっとスマートにできないだろうか。さすがにごちゃごちゃしすぎてます。連対率のところでtry~exceptを多用しているのは新人選手の内枠データがなかったり、阿波勝哉選手などは1枠データがないためです。

今回のまとめ

ここまでやって気づいたことはやはり機械学習はデータの収集、前処理の方が大変ということ。例外が次々出てくるしデータの欠損値の処置など、『できたーっ!!!』と達成感に満ち溢れた後に、それまでのプロセスの2倍以上時間をかけて修正していきました。

実のところ、収集したデータは全てをレース結果を集めきれたわけではありません。例えば『今日は3レースで打ち切り』となった開催日のレース場データは、実際に実施された3レース分は取得できていません。理由として、ダウンロード元の出走表データは12レース分あるのに対して、レース結果データが3レース分しかなく、エラーが発生した為です。ここからやり直すのかと心折れて妥協、『そういうのは無視無視』と切り捨てることにしました。

それでも必要な量は満たしていると思うので、今回はこれで次に進みたいと思います。

タイトルとURLをコピーしました