自動投票の作り方【伍ノ型】

プログラミング

競馬予想プログラミングに関する記事を「投稿まとめ」で一覧にしてます。この記事は「自動投票」の一覧に含まれてます。一覧の順に読むとステップごとで分かりやすいです。

【伍ノ型】自動投票で条件ごとに異なる機械学習モデルを使う

【伍ノ型】は【肆ノ型】の派生になります。したがって【伍ノ型】を習得するには、【肆ノ型】を先に習得してください。

【肆ノ型】で伝授した方法だけでは、自動投票の機械学習モデルは、常に同じモデルを使うしかありませんでした。この記事では、何らかの条件ごとに異なるモデルを使う方法を説明します。

【伍ノ型】はモデルのファイルを指定する「モデル読み込み」の部分の予測用ソースコードを修正するだけなので、二値分類とかランキング学習とか、データの分析方法は関係なく全て共通です。

競馬場ごとに異なるモデルを使う

競馬場ごとに異なるモデルを使いたい場合は、ファイル名である引数のレースID(※1)に含まれる競馬場コードを使います。これは予測用ソースコードを修正すれば実現できます。

(※1)レースID年月日場R
yyyymmddjjrr(12桁)

予測用ソースコード修正前

# モデル読み込み
bst = lgb.Booster(model_file='lambdarank_model.txt')

予測用ソースコード修正後

# 競馬場コード取得
jj = fname[8:10]
# モデル読み込み
bst = lgb.Booster(model_file='lambdarank_model_' + jj + '.txt')

見ての通り、引数のレースID(fname)から競馬場コードを取得して、ファイル名を変数で設定して、競馬場ごとのモデルが指定できるようにすればOK。もちろん、競馬場ごとのモデルを先に準備しておく必要があります。上記のソースコードだと、競馬場ごとのモデルのファイル名は以下のようにしておきます。

  • 札幌モデル → lambdarank_model_01.txt
  • 函館モデル → lambdarank_model_02.txt
  • (…省略)
  • 阪神モデル → lambdarank_model_09.txt
  • 小倉モデル → lambdarank_model_10.txt

ちなみに、競馬場ごとのモデルを作るときは学習用ソースコードで指定しているファイル名を毎回修正するのではなく、出力されたファイル名を修正したほうが効率的です。今回の例ではファイル名を、”lambdarank_model_” + 競馬場コード + “.txt” としてますが、ユーザーの好みで決めてもOKです。

競走条件ごとに異なるモデルを使う

PythonでPostgreSQLに接続する

競馬場コードは引数のレースID(※1)から簡単に取得できます。しかし他の情報、例えばトラックコードや競走条件コードなどが必要な場合は、PostgreSQLに接続して「レース詳細」テーブルから目的の情報を取得する必要があります。

PythonでPostgreSQLに接続するには、事前に「ドライバ」と呼ばれる部品をインストールする必要があります。

psycopg2のインストール

Python用のPostgreSQLドライバはいくつかありますが、ここでは最も多くダウンロードされている「psycopg2」を紹介します。インストールは「LightGBMによるAI競馬予想(準備編)」の記事で紹介している方法と同じです。コマンドプロンプトに、以下のコマンドを入力して実行してください。

py -m pip install psycopg2

これでPythonでPostgreSQLに接続する準備ができました。

競走条件ごとに異なるモデルを使う

次は、競走条件ごとに異なるモデルを使う方法を説明します。モデルを、

  1. 新馬戦
  2. 未勝利戦
  3. 上記以外の条件戦

で、3つ作った場合とします。まず、予測用ソースコードの一番上にimportの宣言を追記します。

import psycopg2

次に、予測用ソースコードを以下のように修正します。検索結果の取得には、既存のサンプルのソースコードで使ってる「pandas」の「read_sql」メソッドを使ってます。

予測用ソースコード修正前

# モデル読み込み
bst = lgb.Booster(model_file='lambdarank_model.txt')

予測用ソースコード修正後

# データベースに接続します
config = {
    'host': '127.0.0.1',
    'port': '5432',
    'database': 'pckeiba',
    'user': 'postgres',
    'password': 'postgres'
}

con = psycopg2.connect(**config)

# SQLを作成します
yyyy = fname[0:4]
mmdd = fname[4:8]
jj = fname[8:10]
rr = fname[10:12]

where = ''
where += ' WHERE 1 = 1'
where += f' AND ra.kaisai_nen = \'{yyyy}\''
where += f' AND ra.kaisai_tsukihi = \'{mmdd}\''
where += f' AND ra.keibajo_code = \'{jj}\''
where += f' AND ra.race_bango = \'{rr}\''

sql = ''
sql += ' SELECT * FROM jvd_ra ra'
sql += where
sql += ' UNION ALL'
sql += ' SELECT * FROM nvd_ra ra'
sql += where

# SQLを実行します
df = pd.read_sql(sql=sql, con=con)

# データベース接続を閉じます
con.close()

# 行インデックス, 列名 で任意の値を取得します
value = df.loc[0, 'kyoso_joken_code']

if value == '701':
    # 新馬戦
    model_file = 'lambdarank_model_701.txt'
elif value == '703':
    # 未勝利戦
    model_file = 'lambdarank_model_703.txt'
else:
    # 上記以外の条件戦
    model_file = 'lambdarank_model_999.txt'

# モデル読み込み
bst = lgb.Booster(model_file=model_file)

PostgreSQLから任意の値を取得したら、あとはPythonでIF文を使って競走条件ごとにモデルのファイル名を指定すればOK。あるいはSQLのCASE式でコードを編集しておいて、前章の競馬場コードようにファイル名を変数で設定してもOK。

条件分岐をPythonでやるか、SQLでやるか、どちらが良いかは状況次第ですが、判断基準の1つとしてステップ数(ソースコードの行数)の少なさを優先すれば良いと思います。理由は、ステップ数の少ないほうがバグが出る可能性が低いからです。

予測テーブルは同じテーブルを使う

異なる条件ごとに異なるモデルを使う場合に注意すべきことは、予測テーブルのテーブル定義は統一する必要があるということです。学習データとモデルをそのように設計してください。例えば「LightGBMによるAI競馬予想(準備編)」の記事にある学習データのサンプルを使うとすれば、以下のような感じになります。

説明変数条件戦
xxxxxxxx
未勝利戦
xxxxxxxx
新馬戦
xxxxxxxx
JRA-VANタイム型DM
馬体重
1〜2走前 確定着順
1〜2走前 4角順位
1〜2走前 単勝人気順
1〜2走前 後半3F順位
1〜2走前 タイム差
【目的変数】確定着順
※ヘッダの’x’はレイアウト調整が目的の文字です

条件戦と未勝利戦では過去走データが重要である一方、新馬戦にはそのデータが存在しません。この場合、新馬戦のモデルにも過去走データの項目を追加し、数値の”0″とかテキトーな初期値を設定した学習データでモデルを作ってください。◯は設定、▲にはテキトーな初期値です。

あるいは、新馬戦は購入の対象外にするという方法も検討してください。

自動投票のテストを実行する

自動投票を実行する(テスト)」の記事を参考に、テストを実施します。

「自動投票実行(本番)」は「自動投票実行(テスト)」をバッチリ行ってから実行してください。

以上で【伍ノ型】の伝授は終わりです。

「投稿まとめ」にもどる