どうも、ねへほうもんです。
最近はマスターデュエル一色ですが、何も生産的な活動をしないのは良くないだろうと危機感を感じ、新しい取り組みを始めることにしました。
その名も、
Pythonで競馬予想AI制作
です。
1.経緯とか計画とか
きっかけ:とっさの思い付き
僕が何かを始めるのに、合理的な理由があることの方が珍しいです。
ダラダラ続けるか辞めるかの判断はきちんと考えますが。
週末チビチビ賭けた結果、生涯収支マイナス10万円君に差し掛かりつつある状況に危機感を持ったのか、違うアプローチを試そうと本能的に思ったのかもしれません。
(趣味用の金を競馬に回しているだけで、全然問題ない額なのですが)
職業はプログラミングとは直接関係はしないのですが、最近の「デジタル・トランスフォーメーション」とかいう時代の流れを受けて、弊社でもプログラミングやら処理の自動化やら機械学習(AI)やらを取り入れようという流れになっています。
現状、インプットだけして実践する機会が無い状態になっており、プログラムは読めるけど書けない程度のレベルです。
いつもプログラムを書こうとすると、1文字抜けたり、スペースを入れ忘れたりで回らなくてキレて投げ出してきたので、自分のレベルアップに丁度良いかと思い、始めることとしました。
AIで何かを予想させるというのは仕事で経験があるので、僕にとっては「出来そうなイメージはあるが、実際に自力で完遂できるかは分からない」という難易度の取り組みで、無理ゲーでもヌルゲーでもない丁度良いラインだと思います。
読者の方の大半は知識ゼロだろうという想定で、極力理解しやすく書きますので、宜しければお読みください。
以下の流れを予定しており、現状①の途中まで進みました。
①学習用データを入手
②学習用データを加工(不要な行を消す、データ形式を変える等)
③AIで予想させる
④実際に馬券を購入し、ダメならAIを調整
ここで皆さんに問題です。
上記の①~③の中で、一番手間が掛かるのはどれでしょうか?
実際には「カッタラキマセン」状態になるので④で頭を抱えることになりそうですが、ここは試行錯誤でどの程度手間が掛かるか分からんので無視してください。
僕がAIを学ぶ前は、AIってよく分からんし、③が一番ややこしそうだと思っていました。
しかし実は、
③が圧倒的に簡単
なのです。
詳しくは後日紹介予定ですが、ざっくり以下3行のプログラムを書けば終わります。
①xgb_model = xgb.XGBRegressor()
②xgb_model.fit(x_train, y_train)
③xgb_model.predict(x_test)
ざっくり説明すると、
①xgboost(勾配ブースティング木)というモデルでAIを作成すると宣言
②学習用データを入力してモデルに学習させ、AIを作成(例:競馬で過去の結果を基に将来を予想させる場合、x_trainに過去の出走馬の情報/y_trainに着順を記入)
③作成したAIで週末のレースを予想する(x_testは出走馬の情報)
という感じです。
正しい例えかは怪しいですが、
「教科書と参考書大量に置いておくから、後は〇〇先生が勧める勉強法に沿って学習しといて!!!」
と言ったら子供が勝手に猛勉強してくれるようなものです。
この例えにおける勉強法がAIにとってのモデルで、人間の子供なら「まず教科書読んで、次に基本例題解いて、最後に応用問題を・・・」みたいに手順を指示しないといけないのですが、AIなら「勾配ブースティング木」とか「ランダムフォレスト」とか、難しい名前のモデルで指示を出せば、後は決まった手順で良い感じに学習してくれます。
という訳で、適当にAIに予想させるだけなら、3行書けば済むという話です。
が、予想精度を上げるとなると話は別です。
ここで重要となるのが、
①学習用データを入手
②学習用データを加工(不要な行を消す、データ形式を変える等)
の2つです。
例えば人間の勉強でも、古い教科書とか、難し過ぎる参考書とか、不適切な教材を使ったら勉強が捗りませんよね?
それと同じことで、適切なデータを使って学習させないと、途中でエラーが起こったり、学習精度が落ちたりという問題が生じます。
どういうことか、僕の実際の作業過程を紹介しながらご説明します。
2.スクレイピングによるデータ入手
ここまで何度か、学習用データと書いてきましたが、具体的にはどんなものか、どうやって収集するかをご説明します。
ビジネスの世界では紙のデータしか無く、PCに取り込めねぇよぉと嘆くことも多いですが、この点競馬は恵まれています。
皆大好きNetkeiba様のサイトに大量の情報が落ちています。
こんな感じで、着順に加え、人気・オッズ・騎手名等が載っています。
このデータを使って予想させると、「人気が高く、オッズの低い馬は上位に来やすい」という予想をするAIが出来上がるはずです。
しかし、1レースの結果だけを見て、雑な予想をするだけなら人間でも出来る話です。
大量のデータを処理できるというのがAIの強みなのですから、その強みを活かすためには、以下のような学習用データが求められます。
・1レースの結果のみならず、大量のレースの結果を集める
・Webページではなく、csvのようなデータ処理に適した形式に変換する
そこでプログラミングの出番で、「スクレイピング」という処理を行います。
具体的には、
こんな感じでExcelファイルで表示できるようにデータを集計するのが目標です。
人力でやるなら、WebページをドラッグしてCtrl + C&Vでコピペするのでしょうが、プログラムだとより賢く・効率的に実行する方法があります。
Webページ上でCtrl + Uを押すと、このようにHTML形式で見ることができます。
字が細かくて恐縮ですが、うっすら「ショウナンバービー」という馬名が見えるでしょうか?
該当レースの1着馬です。
一番上の行に、class = "HorseList"と書かれていますが、スクレイピングでは、
「HTML文の中から、HorseListの情報を抜き出してくれ!」
と指示を出すことで、必要な情報を収集することができます。
ちょっと新しい取り組みをしてます。
— ねへほうもん (@nehehomon) February 6, 2022
進捗あればご報告します。 pic.twitter.com/xFVJ3TeKDF
今朝、スクレイピング用のプログラムを書いていた時の投稿です。
外部サイトにプログラムが載っており、まずはそれをコピペして実行、その後プログラムを編集しているのが現状です。
具体的に何を編集しているのか、今後どうしたいのかという話ですが、まず拾ったプラグラムでは、
このように、1レースの情報しか得られません。
そこで、同じ処理を何度も繰り返し、大量のレースデータを収集するためにプログラムを修正しています。
少し修正したのがこちら。
聞いたことがある方も居るかもしれませんが、for文を使って処理を2回に増やしました。
後は、レースデータが大量に縦に並ぶと、どのレースの結果かが分からなくなるため、P列より右にレース情報を追加しました。
例えばP列からは2020年のレースであること、T列からはとある日の1レース目,2レース目であることが分かります。
後ざっくり言えば、この処理を過去の全レースに広げれば、全レースの結果が収集できるという訳です。
ただ、1つ注意点というか、懸念しているのが、スクレイピングをすると特定のWebサイトに大量にアクセスを繰り返すことになるため、サイトに過度な負荷を掛ける可能性があるということです。
サイトにアクセスが集中すると開くのに時間が掛かることがありますが、あれを一人でやりかねないということです。
下手したらサイト運営の方とトラブルになりかねないので、人様に迷惑を掛けぬよう、以下を心がけようと思います。
・間違っても過去30年分の全データを一斉取得するとか無茶はしない。ある程度刻んで取得する。
・土日の午後3時~4時(メインレースの時間帯)はどう考えても混み合うので、平日の夜遅くとか、空いてそうな時間に実行する。
・レース情報の追加とか、プログラムの修正を完全に仕上げた上で実行し、スクレイピングを何度も繰り返さない。
①学習用データを入手
②学習用データを加工(不要な行を消す、データ形式を変える等)
の工程のうち、ここまでが①の話ですが、最後に②、今後の課題をご説明します。
データの加工というと簡単そうですが、実務では「データクレンジング」と呼ばれ、ここが一番面倒だとすら言われます。
例えば上の図でも、
・「取消」「除外」という、走っていない馬の情報は不要なので削除する
・騎手が▲山田など記号が入っている。例えば▲山田と山田のように別表記になると、実際には同一人物でもAIは別人として解釈するため、表現を揃える必要がある
・着差が「アタマ」「1月2日」のように数字以外の表記がある。1月2日はおそらく1/2を2分の1ではなくExcelファイルが日付として読み込んだせいなので問題ないだろうが、アタマは「0.05馬身差」のように数値に変換した方が良さそう。
といった感じで修正箇所が多いです。
後は、馬場状態・血統などの、一般に競馬予想に用いられるデータが含まれていないため、それも追加する必要があります。
④実際に馬券を購入し、ダメならAIを調整
の箇所に関係しますが、
「精度の高い競馬予想AIを作るのにAIの知識は要らない。結局競馬に詳しい人が勝つ。」
ということです。
プログラムを3行書けばAIは作成できます。
精度を上げるには、AI自体ではなく、どうデータを与えるかが重要となるのです。
例えば、「スローペースの展開だと先行馬が勝ちやすい」という傾向を学習させるなら、馬の脚質を入れる必要があります。
脚質情報を上手く応用できれば、単に1着を予想させるだけではなく、「前残りの展開になれば先行馬がまとめて来やすいので、先行馬のワイド馬券を買え」というように、オッズ対比で旨い馬券の買い方まで教えてくれるかもしれません。
他にも調教時計、本数、前走からのレース間隔、出遅れ・前塞がり等のレース内容などなど、競馬で学習させたいデータは大量にあります。
その中から何を選び、csv形式に落とし込むかが腕の見せ所となります。
また、パドックや返し馬の様子のように、数値化困難な要素も存在するため、結局は買い目を決める人間の実力勝負となるのです。
僕の予定では、
①週末の全レースの結果を予想させ、オッズ対比で妙味ある馬をピックアップさせる
②おいしいレースを絞った後は、自分でもデータを集めて分析し、AI予想が信頼に足るかを判断する
という感じで活用する予定です。
素人の作ったAIの精度なんてたかが知れているでしょうし、完全にアテにするつもりはありません。
ただ、勝負レースを絞るとか、気付かなかった穴馬を見つけるといった、人間では労力的に無理な役割は果たせるレベルのAIにしたいな、と思っています。
今回はこんなところで。
細かいプログラムには興味がないでしょうから、次回はAIを完成させ、実際に予想に用いた結果のご報告をさせていただきます。
週末しか作業が進まないでしょうし、早くて再来週ですかね・・・?
では、続報をお待ちください(^^)/