まず、機械学習といっても種類があります。今回は、各チームの勝敗を予測するということなのでクラス分類(勝/負/分のクラスに分類する)もしくは、回帰分析(2−3などのスコアを算出する)でやっていくのが最適かな?試してみてだめだったら手法を変えるということで一旦はこのどちらかで行こうかと思います。
まず最初に何をする?
上記のどちらかで予想を立てることにしたので、教師が必要になります。クラス分類・回帰分析はともに教師あり学習と呼ばれるものです。
よって、過去のデータをすべて取得することにします。どうやって取得するかですが、手っ取り早くいくにはやはりWEBから仕入れるしかないですよね。
WEBから情報を取得する方法は、スクレイピング(またはクローリング)を用いるのが一般的です。
スクレイピング?
スクレイピングは、ウェブサイトから情報を抽出するコンピュータソフトウェア技術のこと。例えば、サイトから必要なデータのみを取得してデータベースに格納・分析可能な構造化データへ変換したりすることです。
注意点は、人様のサイトから情報を抜き取るわけですから、規約に反しないかどうかを確認しておくことが重要かと思います。今回は、個人的に利用するだけだから大丈夫。。。なのかな?だめだったらこの記事が消えます。
実際にスクレイピングを行うにあたって
実際にWebスクレイピングをする際に一番大事なことを行います。それは、対象のサイトをしっかりみる!です。
何を馬鹿なといった方もいるかも知れませんが、理由は簡単です。サイトのどの部分をどういう形で取得していくかを特定する必要があるからです。
よって、もっと正確に言うとただ普通にサイトを眺めるだけではダメです。スクレイピングで取得する情報は、HTMLのフォーマット(Chromeで言う所の右クリックで出てくる「ページのソースを表示」で出てくるHTMLの情報)から取得します。
例
まずは、toto BIGのサイトを普通に見るとこんな感じ
このサイトを『ページのソースを表示』でみたのがこれ
この中から、一番下の各チームの勝敗情報を取得し抵抗と思いました。
が、ただ日にちとチーム名と勝敗情報だけで次回以降を予測するのは流石にデータ少ないのではないかという疑念がわきました。というのも、約1000回分のでーたがあるとはいっても、機械学習を行うには心もとなすぎる教師の量となってしまいます。入力層が非常に少ないのも気になるところ・・・
ということで、ちょっと考え方を変えます。2006年以降の全ての試合をすべて取得し、選手の情報などもうまく情報に組み込めるといいかなと思います。とするとtotoのサイトでは不十分になってしまうので、Jリーグのデータサイトにお世話になろうと思います。そちらも同じようにソースをみると、下みたいにテーブルとしてデータが連続的に連なっていたので、この部分を取得してみます。
Pythonでプログラムを書いていく
今回は、requestsとBeutifulSoupを使ってスクレイピングを行うことにします。
あとPythonは3系使ってます。2系だとrequestの扱い方が違います。あと、ユニコードとかも気をつける必要があります。
# coding=utf-8 import requests import datetime from bs4 import BeautifulSoup import csv def main(): Year = "2006" day = datetime.datetime.today() thisyear = day.year data = [] while True: target_url = 'https://(パス省略)' resp = requests.get(target_url) soup = BeautifulSoup(resp.text) tables = soup.find_all("table",class_="table-base00 search-table") for table in tables: for tr in table.contents[3].contents: if tr != "\n": row = [t.text for t in tr.contents if t != '\n'] data.append(row) Year += 1 if Year <> thisyear: break with open('test.csv', 'w') as f: writer = csv.writer(f, lineterminator='\n') writer.writerows(data) if __name__ == '__main__': main()
とりあえずこんな感じで書きました。対象パスの中に年度を入れる箇所があったのでwhileで無限ループを作って年度を加算しながら今年まで繰り返すようにしました。
プログラムの各部の簡単な説明
それでは、プログラムの各部分にとんでもなく雑で簡単な説明を入れていきます。
以下の2行でページのHTMLの情報を取得してます。
resp = requests.get(target_url) soup = BeautifulSoup(resp.text)
以下の行で対象のタグ(table)かつクラス(table-base00 search-table)を持つところを抽出しています。
tables = soup.find_all("table",class_="table-base00 search-table")
以下の行で情報をリスト化しています。ここはちょっとPythonぽい書き方ですかね。
row = [t.text for t in tr.contents if t != '\n']
これは下のプログラムを一行で書いた場合の記述です。オライリー本とかその他でも結構いろんなところで出てくるので知ってる方が吉だと思います。単純に短く書けるのもいいですし。
row = [] for t in tr.contents: if t != '\n': row.append(t.text)
完成したリストをそのままdataというリストに追加することで、配列のようにしており、withのブロックでCSVに出力しています。
大体こんな感じですかね。で出力結果がこんな感じで8000レコードぐらいでした。
次は、これにちょいちょい加工を行って教育に入ってみます。
ピンバック: 【機械学習】toto BIGに挑戦(AzureML編) | 趣味で始める機械学習
ピンバック: totoの過去データをCSV化して機械学習の準備をします | YATTE-MIYO なんでもやってみよう やてみよブログ