機械学習 其の005 ~前処理とデータ表示2~
前回のエントリで、1レース分の着順事のタイムをプロットしてみました。今回はこのデータを更に増やしてみます。
例によってnankankeiba.com/から大井競馬場の8/24~8/28の1200mのレースに絞ってデータを集め表示してみました。
基本的には前回のエントリと同じプログラムでよいのですが、データの一部に落馬等で記録が残っていないデータがあります。このようなデータは着順やタイムに"-"が設定されているためデータ処理の前に除去しておく必要があります。具体的には以下のように配列生成と同時にループで特定条件の要素を除外しています。この辺はpythonだと、とても柔軟に記述できて素晴らしいと思います。
記録なしのデータ除去部分
x = racedata[:,0] # 着順の配列を作成 y = racedata[:,10] # タイムの配列を作成 # 落馬等の原因で着順、タイムの記録が存在しないデータを除去 x = np.array([i for i in x if i != -1 ]) y = np.array([i for i in y if i != "-" ])
実行結果
結果としては、いまいちですね。72秒から73秒前後だとほぼ1~3着に入れそうだということと、77秒代でも1着になるケースもあるということ程度しか分かりません。このままでは全然役に立ちそうにないので、もっと別の評価軸を設定する必要があるのだろうと想像できます。
まぁ、ダメ元で直線で近似(いわゆる最小二乗法)してみます。
前回のサンプルだとベクトルyが文字となっていたので、astypeでfloatのベクトルに変換し、polyfitでモデル関数のパラメータであるfp1を取得します。
次にfp1からpoly1d(1次元なので1d)を使ってモデル(近似)関数f1を作成します。
作成したfp1とf1は次のようになります。fp1が「[ 0.17563257 74.85191064]」でf1(モデル関数)が「0.1756 x + 74.85」です。 fp1からf1が作成されていることがわかると思います。
fp1とf1の内容
[ 0.17563257 74.85191064] 0.1756 x + 74.85
次に作成したf1を描画します。サンプルでは、f1を描画するのにplot関数を使用しています。plot関数の引数は点を描画する座標をx,yでそれぞれ設定します。今回はfxとf1(fx)を与えています。fxは1~16の範囲を16分割した配列をlinspaceで作成したもので今回の場合であれば、着順のリストとなっています。実際fxの内容を表示すると以下のようになっています。
fxの内容
[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16.]
f1(fx)は1着から16着までのタイムを返却する関数となっており、これらで表現される座標にプロットしています。plotの第3引数はプロットする点(あるいは線)に関するプロパティです。サンプルでは「linewidth=4」としていますが、「"ro"」(赤い丸)等を指定すると表示が変わります。
近似関数の描画
# タイムを数値変換 for idx, time in enumerate(y): y[idx] = np.float32(time.split(":")[0])*60+np.float32(time.split(":")[1]) y = y.astype('float') fp1 = sp.polyfit(x, y, 1) # fp1:モデル関数についてのモデルパラメータを取得 f1 = sp.poly1d(fp1) # モデルパラメータからモデル関数を作成 fx = sp.linspace(1, 16, 16) # fxプロット用に1着から16着の範囲で配列を作成(第3パラメータの16はfxのベクトルの要素数) fp = FontProperties(fname=r'C:\WINDOWS\Fonts\msgothic.ttc', size=14) plt.scatter(x, y) plt.plot(fx, f1(fx), linewidth=4) plt.title(u"着順別タイム", fontproperties=fp) plt.xlabel(u"着順", fontproperties=fp) plt.ylabel(u"タイム", fontproperties=fp) plt.xticks([i for i in range(1, 17)], [u"%i着"%i for i in range(1, 17)], fontproperties=fp) # 1着から16着のレンジでx軸を作成 plt.yticks([i for i in range(70, 90)], [u"%i秒"%i for i in range(70, 90)], fontproperties=fp) # 70秒から90秒のレンジでy軸を作成 plt.autoscale(tight=True) plt.grid() plt.show()
実行結果
やはりというか、役に立ちそうにないので、次回は別の評価軸に関する検討をしてみたいと思います。