俺だって有馬記念予測する。なんなら,最も少ない労力で。


この記事はrstan Advent Calendarの11日目の記事です。

先に結論から。
有馬記念はレイデオロで決まりでしょう。

・・・レイデオロってどんな馬なのか,知りませんけど。

今回の目的は,いかに労力を使わずに競馬データを分析するか,です。
競馬のデータを分析して,機械学習でもなんでもいいですが,予測ができるようになれば大儲け!ですよね。
でも多分,世界はそんなに簡単ではなくて,楽して大儲けするためには大変な苦労がいると思うのです。

そこで,「楽して儲けたい」という目的の「楽して」の方にウェイトを置いて,「少しくらい外れるのは仕方ない」という方針で,予想してみたいと思います。
ちゃんとやれよー,とツッコミが入りそうですが,そういう人のために分析データはここにおいておきますので,是非ご自身で実践していただいて,空いてるカレンダーの穴を埋めてください!

実は,何かいいデータはないかなあという教育的目的から,スクレイピングして競馬のデータを取ろうということになりまして,いろいろ苦労したんですが,なんとか数十万レコードのデータを作ることには成功したんですね。ところが,これを使ってあーでもない,こーでもないという話をし始めますと(多少,プロジェクトメンバーの目が血走っているような気がしますが),いろいろな数字・変数を考えることができてしまうです。そして痛感したのがドメイン知識の重要さ。「上り」ってのが大事な情報らしいですね。あるいは,調教師が西の人か東の人か,そういうのも大事らしいですね(馬の移動距離に関わるし,それが成績に反映するかも)。

山のようなデータ,変数を手にしても,何が大事か,何と何をどう組み合わせれば良いか,ということを考えるには,かなりの知識,それを取り入れる努力が必要だということが身に染みてわかりました。

そして,わたしは生来だらしない人間ですから,「下手の考えやすむに似たり,じゃないの。」とか思ったりするのです。つまり,とても精緻に組み上げたモデルやコードで的中率99%を目指すなら,ただの単回帰で的中率6割ならその方がいいじゃない,とか思ってしまう。
そういう方針で出た予測がこれ,というわけです。

データはたくさんの変数があるんですが,着順を「上位三位に入るかどうか」という形に変換し(Top3),これを年齢,性別,単勝の倍率でロジスティック回帰することにします。あとはこの関数を使って,事前の(この記事を書いているのは2019/12/07です)予想単勝倍率をデータにして,予測しようということです。幸い,brmsという大変便利なパッケージがありますので,コードはこれだけです。

# 必要なライブラリの読み込み
library(tidyverse)
library(brms)
# 必要なファイルの読み込み
KB <- read_csv(file="RaceDat.csv")
KB %>% 
    # 芝のデータだけに絞ります
    dplyr::filter(Ground=="芝") %>% 
    # 着順データを変形して,トップ3に入るかどうかだけに限定します
    dplyr::mutate(Top3 =if_else(着順>3,0,1)) %>% 
    # 変数を絞り込みます
    dplyr::select(単勝,,,Top3) %>% na.omit() -> RaceDat

# brmsをつかってロジスティック回帰です
res <- brm(Top3 ~ .,
           family = bernoulli(link = "logit"), 
           data = RaceDat)

# 外から有馬記念に出る馬の名前と,性別,年齢,単勝倍率(現段階での予想値)を取り込みます
ARIMA=read_csv("ARIMA2019.csv")
# 予測します。けっかはdata.frame型にして。
pred <- predict(res,newdata = ARIMA) %>% data.frame
# さあ結果の表示です!
bind_cols(ARIMA,pred) %>% arrange(-Estimate)

結果はこうなったのです。

# A tibble: 16 x 8
   馬名               性       齢  単勝 Estimate Est.Error  Q2.5 Q97.5
   <chr>              <chr> <dbl> <dbl>    <dbl>     <dbl> <dbl> <dbl>
 1 レイデオロ         牡        4   2.2  0.430      0.495      0     1
 2 キセキ             牡        4   5.9  0.379      0.485      0     1
 3 ブラストワンピース 牡        3   8.9  0.376      0.485      0     1
 4 オジュウチョウサン 牡        7   9.2  0.336      0.472      0     1
 5 モズカッチャン     牝        4   9.1  0.322      0.467      0     1
 6 サトノダイヤモンド 牡        5  18.1  0.277      0.448      0     1
 7 ミッキーロケット   牡        5  22.5  0.252      0.434      0     1
 8 パフォーマプロミス 牡        6  20.6  0.250      0.433      0     1
 9 シュヴァルグラン   牡        6  22.7  0.238      0.426      0     1
10 ミッキースワロー   牡        4  28.8  0.224      0.417      0     1
11 クリンチャー       牡        4  32.2  0.206      0.404      0     1
12 マカヒキ           牡        5  42.5  0.141      0.348      0     1
13 リッジマン         牡        5 117.   0.011      0.104      0     0
14 サクラアンプルール 牡        7 147    0.00425    0.0651     0     0
15 サウンズオブアース 牡        7 144.   0.0035     0.0591     0     0
16 スマートレイアー   牝        8 197.   0          0          0     0

つまり,レイデオロがトップ3に入る確率が一番高い・・・と。

この遊びを始めて知ったのですが,「競馬上手の馬券下手」という言葉があるそうです。つまり,競馬で勝つことだけを目的にすると,倍率は低いかもしれないけど確実な勝馬投票権を選べば良いわけです。でも,1.1倍とかの倍率で徐々に膨らませていくのが本当に競馬の魅力か,と言われると,多分違うんですよね。

いろいろなデータがあって,いろいろな特徴量を作れること,あるいは大量のデータがあって,効率よくデータを整形すること,そうした練習に競馬データはもってこいの課題ではあります。まずは「データに興味を持つ」「自分で遊んでみる」という遊び心から,データの世界に入っていくというのがいいと思います。

楽しいですよ,分析!モデリング!stan!

Enjoy!