はじめに
5億円は欲しいけどサッカーの予想なんて難しくてできない〜オフサイドとか知らない〜(><) なんてお困りのみなさん!
web画面をぽちぽちするだけでも簡単に機械学習できちゃうAWS MLを使って、サッカーのサの字も知らないまま試合結果を予想して、僕と一緒に5億円を目指しましょう!
まずは過去のデータ準備
AWS MLに学習させるために、過去の試合結果データをcsv形式で準備する必要があります。
データを探す
公式ページの過去のデータから、適当なものを覗いてみましょう
http://www.toto-dream.com/dci/I/IPB/IPB01.do?op=initLotResultLsttoto
開催日,競技場,No,ホーム,試合結果,アウェイ,くじ結果 と7種類のデータが取得できそうです。
これらのうち最終的に欲しいものは「くじ結果」なんですが、実はこれは試合結果から計算可能で独立したものではありません。
どのデータを学習に使って、どのように結果を出すかあたりはいろいろと考えられるところなんですが、本記事ではMLを使って「試合結果」の方を予想しておいて、それをもとに「くじ結果」を算出してくじを買うことにしようと思うので、一旦「くじ結果」については無視して進めます。
スクレイピングとデータ取得/整形
このWeb上のデータをサクサクっとcsvにしたいので、kimono を使います。
kimonoは簡単にwebページのスクレイピングとAPI化が可能な上、対象ページの指定やデータ切り出しの正規表現、取得後のデータ変換など豊富な機能がついており、最高の一言に尽きるサービスです。
こんな感じでどのデータを取得するか指定して
こんな感じで全ページのデータを取得します
(range機能だと頭の0埋めができなくてseq -f "%04.0f" 198 797 | xargs -I NUM echo -n NUM,
で頑張ってCustomListを作ったり、実はtoto中止回が結構あって穴が空いていたので、一度全部curlしてtotoの結果があるページ番号だけ取り出したりと地味に苦労しました)
URLをもとに第何回のデータなのかを切り出したり、後で読み込みやすいようにCollectionの構造を省略したりします。
なんやかんやの苦労(kimonoのfetchが遅かったり、最大数に上限があったり、totoの結果に抜け漏れがあったり)があって何度もやり直したので、ここまで来るのにすでに3日以上かかってますが、どうにかこんな感じにできました。kimonoは最高ですが、元データを用意する作業は基本的にめんどくさい戦いになるという学びを得ました。。。
できたcsvファイルはここに置いておくので必要な人は好きにもって行ってください
https://dl.dropboxusercontent.com/u/3069264/toto_prize_results.csv
データソースとデータモデルの作成
準備したcsvをS3のどこかに配置したらここからがAWS MLのターンです。
AWS MLでは、二項分類、多項分類、回帰分析の3種類のアルゴリズムが使えます。
同じデータにこれらうち好きなアルゴリズムを適用するというよりも、求めたいデータの種類に応じて自動的に選択される形式のため、求めたい情報に対して適切な形で元データを準備してやる必要があります。
totoの結果を予想する場合だと、ざっと適当に思いつく限りでも、
- 各試合のくじ結果を多項分類で求める
- 各試合の試合結果(点数)を多項分類で求める
- 各試合のホームとアウェイの点数差を回帰分析で求める
みたいなものが考えられそうです。(どういう方法が妥当なのか、もっと良い方法があるのか、どうすれば5億円が手に入るのかについてはどなたか深く研究して教えて下さい。)
この記事では2番目に書いた「各試合の試合結果を多項分類で求める」でやる方針で、AWS MLでデータソースとデータモデルを作成していきます。
元データのcsvに対してschema、ターゲットの設定
下記のようにschemaを設定しました。
dateは自動的にCategoricalに分類されたんですが、カテゴリにすると365種類できてしまうので、手動でTextに修正しています。
そしてscoreをターゲットとして設定します
内容を確認してFinishしたら次はデータモデルの設定とEvaludationですが、特にデフォルトの設定から変えずにポチポチすすんでいきます。
デフォルトの設定だと、元データのうち7割を学習データ、残り3割をテストデータとして扱い、
テストデータでのEvaluationの結果を見ることができます。
Evaludation結果の確認
こんなのが出てきました。
データモデルの良さを測る指標のF1が0.09ということで、予想をバシバシ当てちゃう感じではなさそうですが、そもそも機械学習すれば100%分類して、いつでも自由に5億円手に入るほど世の中は甘くないので、とりあえずこのまま進みましょう。
さあ予想するぞ!
作成したデータモデルを使って、新しいデータに対応する値を予想する方法には batch prediction と real-time prediction の2種類があります。
batch predictionは、一定量のデータを渡してそれに対する予測結果をS3に保存してくれます。real-time predictionでは、作成したMLに対してAPIを通してデータを投げて結果を受け取れるようです。今回のtotoの予想は週に一回しかなくてリアルタイム性はまったく求められてないので、batch predictionでやります。
batchデータの用意
学習データと同じ形式で、予想したい新しいデータを作成します。
試合結果の部分はなんでもいいんですが、とりあえず"x-x"
と埋めておきました。
現在くじ発売中の第800回totoのbatchデータは下記のようになります。
batch predictionを作る
学習データと同様に上記のcsvをS3上に配置したら、あとはデータモデルを選んで、データソースを選んでと順にぽちぽちやっていくだけです。
データソースにcolumn nameが含まれているかどうかのチェックを間違えないようにしましょう。上記csvだと1行目からデータが入っているので、間違えると予想結果が1行少なくなってしまいます(しまいました)。
結果を見る
結果は先ほど出力先として指定したS3のディレクトリの奥にgzipされて保存されます。
ダウンロードして、解凍してスプレッドシートに貼り付けて、ちょっと色などつけてやると下記のようになりました。
指数になっていてやや数字が読みづらいですが、各行の1カラム目が先ほどダミーで指定したデータ、2カラム目以降に、各カテゴリに分類される確率が書かれています。
あとは、各行について一番確率の高い列の1行目を求めてやるためエクセル力を発揮して、下記のような関数を書けば各試合の予想スコアが弾き出せます。
=INDEX($B$1:$AY$1,0,MATCH(MAX(B2:AY2),B2:AY2,0))
この時点で、1-1の時は0、0-3の時は2というように各スコアをくじ結果まで落とし込んでから集計する方法も考えられますが、ちょっとエクセル力が足りなかったため妥協しました。
以上です。ここまでできた人は各自くじを買ってわくわくしながら結果発表を待ちましょう!!
感想とか考察とか
今回試合結果のスコアを多項分類にかけました。とりうる値は、ホーム側の得点が0~10くらい、アウェイ側の得点が0~10くらいで見積もって、100種類は超えないだろうという感じ(実際には46種類)でしたが、データ中のCategoricalの種類が100を越えると、MLがエラーを吐くみたいです。モデルを作る際にはCategoricalの取りうる値の種類に十分気をつけましょう。
また、今回はデータモデル作成はデフォルト設定で走り抜けましたが、カスタム設定をすると各データのグループ化など機械学習の精度を上げるため(?)のデータ変換が行えるようです。
試合のスコアだけをカテゴライズするよりも、homeの得点、awayの得点をそれぞれ別でカテゴライズして、グループ化するのが正しい使い方な気がするので、またそのうち試してみたいです。
TOTOの試合結果をカテゴライズしましたが、出現頻度上位を眺めると、だいたいhomeの方がawayに比べてだいぶ勝ちやすいように見えます。「どんな時にawayが勝つのか?」という切り口でデータ分析してみるのも面白いかもしれません。
結果として出力されるファイルを頑張って、スプレッドシートでこねこねしましたが、どうもあんまり見やすくないです。何かよい眺め方や分析の仕方を知ってる方、情報をください。
お世話になった参考リンク
Amazon Machine Learningを理解するために3つの方法で天気予測をしてみた(まとめ編)
http://recipe.kc-cloud.jp/archives/7793
Amazon Machine Learningのサンプルをちょっとチューニングしてみる
http://qiita.com/tominaga443/items/7c91ab873b2578445614
結果発表!
本記事のデータで予想したtotoの結果と考察は下の記事に書きました。
AWS Machine Learningでtotoが当たらなかったので反省と考察
免責
この記事を読んでtotoを買ったことにより発生したあらゆる損失については、当方では一切の責任を持ちかねます。くじ購入については各自の責任でお願いいたします。