モデル評価のスコアは結構良い感じだったけど、実際はどうだろ?
こんにちは、古賀です!
本記事は、
はてな
「Python機械学習でホームラン数を予測する」の予測編
です!
今回で、この「ホームラン数予測」は最終回です!
機械学習をさせてモデルを作成した後は、
実際にそのモデルを使って、予測させてみましょう!
良いモデルが作成できていれば、良い予測結果が出るはずです!
今回が最後なので、機械学習の一通りの流れは終わりです!
Pythonの機械学習の基本を学んで、次の勉強に活かしましょう!
前回の続きになりますので、
前回の記事を読まれていない方はこちらをご覧ください!
-
Python機械学習「ホームラン数予測④」モデル作成・モデル評価編!
「機械学習させてAIを作る!」ってなんだか難しそう。。 自分のレベルでもできるのかな。。 こんにちは、古賀です! 本記事は、 はてな 「Python機械学習で ...
続きを見る
自己紹介が遅れましたが、
わたしは大学卒業後、上場IT企業に就職し、プログラマー、システムエンジニアとして
約10年間働いておりまして、その後は様々な活動をしております。
プロフィールの詳細はこちらです。
-
プロフィール
こんにちは、古賀正雄です。現在36歳です。 簡単ではありますが、こちらのページで自己紹介とこのブログについてお話します。 高校時代 学生時代は主に野球をしていました。 進学先の高校も野球で選びました。 ...
続きを見る
※YouTubeに同内容を公開しております。
Python機械学習「予測」の概要
前回までの動画で、
- WEBスクレイピングでデータを収集
- データ分析をして「説明変数」と「目的変数」を作成
- 11球団のデータを使用して「モデル作成&モデル評価」
をしてきました。
今回は、今回の目的のゴールである
「作成したモデルを使って、巨人の選手のホームラン数を予測」
します!
前回、評価用データのホームラン数を予測したように、
巨人の選手のデータを渡して、ホームラン数を予測させます。
ですので、コードの内容も前回書いた内容と同じです。
具体的な手順は、
- 巨人のデータの「説明変数」を作成する
- 作成したモデルを使用して、巨人のホームラン数を予測させる
- 予測したホームラン数と実際のホームラン数を比較してみる
です!
Python機械学習「予測」をしてみる!
前回までのコードも含まれていますが、今回のコードは最後の4行分です。
今からこのコードを説明していきます!
# 表形式データを扱うライブラリ import pandas as pd # データ分割 from sklearn.model_selection import train_test_split # モデル作成 from sklearn.linear_model import LinearRegression as LR # 評価関数 from sklearn.metrics import mean_squared_error as MSE # 行列計算ライブラリ(機械学習の結果がnumpyで返却される) import numpy as np # CSVデータ読み込み df = pd.read_csv('playerData.csv', sep = ',') # 巨人以外の11球団データを抽出 df11 = df[df['チーム'] != '巨人'] # 巨人のデータ df_g = df[df['チーム'] == '巨人'] # 本塁打との相関係数をDataFrameとして変数に保存 df_homerun = pd.DataFrame(df11.corr()['本塁打']) # 相関係数「0.7」以上の項目名を抽出 X_columns = df_homerun[df_homerun['本塁打'] >= 0.7].index.tolist() # 本塁打は目的変数のため除外 X_columns.remove('本塁打') # 説明変数と目的変数をセット X = df11[X_columns] y = df11['本塁打'] # データの分割 X_train, X_test, y_train, y_test = train_test_split(X, y, random_state = 1) # モデルの箱の準備および学習 lr = LR() lr.fit(X_train, y_train) # 予測値の算出 y_pred_test = lr.predict(X_test) # MSEの算出 mse_test = MSE(y_test, y_pred_test) # RMSEの算出 rmse_test = np.sqrt(mse_test) # RMSEの表示 print(rmse_test) # 巨人データ(説明変数) X_g = df_g[X_columns] # 予測ホームラン数の算出 y_pred_g = lr.predict(X_g) # 予測本塁打列の追加 df_g['予測本塁打'] = np.round(y_pred_g).astype(np.int32) # 予測値と実際の値との比較結果 print(df_g[['選手名','本塁打','予測本塁打']])
巨人の説明変数を作成する
まずは、ホームラン数を予測するための材料「説明変数」を巨人のデータで作成します。
学習用データの「説明変数」の項目と一致していないと、
予測処理を実行させた時にエラーが発生してしまうので、
学習用データの「説明変数」を作った時と同じように、巨人のデータの「説明変数」も作成します。
# 巨人データ(説明変数) X_g = df_g[X_columns]
「df_g」の変数には、巨人の選手データが格納されています。
※その過程はこちら記事で解説しています。
-
Python機械学習「ホームラン数予測③」データ分析編!
ホームラン数を予測できるように機械学習させたいけど、 どんな情報を渡せば良いんだろう。。 片っ端から渡して色々と試せばいいんだろうか。。 こんにちは、古賀です!   ...
続きを見る
その巨人のデータから「説明変数」の項目名が配列型で格納されている「X_columns」を指定して、
「説明変数」の項目のみ取り出して、「X_g」にセットしています。
これで巨人の選手の「説明変数」の作成が完了です!
中身を確認してみると、
# 巨人の説明変数 print(X_g) # 結果 打席数 打数 得点 安打 二塁打 塁打 打点 四球 三振 併殺打 11 500 440 79 121 26 240 97 55 85 10 16 491 423 63 120 31 234 77 63 101 3 20 479 412 64 119 28 206 65 62 85 9 49 389 354 47 97 16 141 32 30 60 6 64 313 278 42 73 11 103 19 29 71 4 65 312 279 19 83 13 117 29 31 59 11 70 308 274 30 74 10 113 41 30 82 1 75 288 263 26 65 9 110 36 22 47 6 126 159 146 22 36 6 50 14 8 32 6 129 156 141 21 36 7 49 17 11 21 3 132 154 146 14 39 3 56 13 8 35 6 145 114 100 4 18 2 23 7 8 23 3 158 96 90 17 23 5 33 6 6 33 1 167 88 75 9 17 2 25 10 10 24 2 176 78 68 7 18 2 25 6 8 15 0 178 77 63 12 15 1 19 6 9 21 1 210 48 37 30 11 2 13 2 11 12 1 211 48 43 2 13 3 19 5 3 16 4 212 47 45 2 11 1 18 7 2 12 1 238 27 23 5 6 0 11 4 4 6 1 248 21 18 1 1 0 1 0 0 4 0 250 20 18 0 3 0 3 0 2 8 0 274 12 10 1 1 0 1 0 1 2 0 280 11 9 3 2 0 5 4 2 3 0 285 9 7 3 0 0 0 0 1 3 0 286 9 9 0 0 0 0 0 0 2 1 326 1 1 0 0 0 0 0 0 1 0
説明変数の項目だけ取り出せていることが確認できます。
おさらいですが、この項目は「ホームラン数との相関係数が0.7以上」の項目です。
この項目から「ホームラン数」を予測できるように、モデルを作成してきました。
「チーム名」や「選手名」が項目にないので、
巨人のデータかどうか判断が付かないかもしれませんが、
「チーム名」や「選手名」はホームラン数を予測するための材料ではないので、
除外されているのが正解です!
モデルに巨人のホームラン数を予測させる
「説明変数」を作成したら、機械学習モデルに渡して「ホームラン数」を予測してもらいます。
この処理は前回「評価用」データを使って「ホームラン数」を予測した時の処理と同じです。
「predict」関数に「説明変数」を渡すだけです。
# 予測ホームラン数の算出 y_pred_g = lr.predict(X_g)
予測した結果を「y_pred_g」に格納しています。
この「y_pred_g」の中身を確認してみると、
# 巨人の選手の予測ホームラン数 print(y_pred_g) # 結果 [ 3.03649782e+01 2.58365917e+01 1.86877379e+01 7.81516555e+00 4.85751026e+00 6.25010037e+00 8.18228025e+00 1.12004516e+01 2.49942288e+00 1.84167971e+00 4.16257778e+00 8.26275391e-01 1.19097672e+00 1.87673228e+00 1.25447360e+00 7.48982976e-01 1.60781695e-01 1.06783859e+00 1.85258636e+00 1.67598326e+00 -5.88513415e-02 -9.46117004e-02 1.25350398e-03 1.06725505e+00 3.90698297e-02 1.34692065e-01 3.55937892e-02]
こんな感じになっています。
各選手の予測ホームラン数が一覧で表示されています。
「e+01」や「e-01」という表示がありますが、これは「10の何乗」であるかを表しています。
「3.03649782e+01」であれば、「30.36」本ということになります。
ただこれだと、かなり見づらいですね。。
ちょっと見やすくなるように改善してみましょう!
小数点以下を四捨五入してみます。
「Numpyのndarray型」の各要素を四捨五入したい場合は、「np.round」関数を使います。
# 予測ホームラン数を四捨五入 print(np.round(y_pred_g)) # 結果 [30. 26. 19. 8. 5. 6. 8. 11. 2. 2. 4. 1. 1. 2. 1. 1. 0. 1. 2. 2. -0. -0. 0. 1. 0. 0. 0.]
これで大分見やすくなりましたが、「小数点」と「-」が気になるので、
これも消していきましょう。
1つ1つの要素を整数型である「int型」に変換します。
要素に対して変換をする場合は、「astype(変換したいデータ型)」関数を使います。
※「int(変数)」では要素に対して変換が行われないので注意が必要です!
「int(変数)」では、ndarrayをintに変換しようとして、エラーが発生してしまいます。
# 予測ホームラン数を四捨五入してintに変換 print(np.round(y_pred_g).astype(np.int32)) # 結果 [30 26 19 8 5 6 8 11 2 2 4 1 1 2 1 1 0 1 2 2 0 0 0 1 0 0 0]
これでホームラン数が綺麗に確認できるようになりました!
予測したホームラン数と実際のホームラン数を比較
最後に「予測したホームラン数」と「実際のホームラン数」を比較してみましょう。
前回と同じように、評価関数を使って比較しても良いのですが、
評価関数の値を確認してもいまいちピンとこないと思うので、
今回は直接「予測したホームラン数」と「実際のホームラン数」を、
横並びで確認してみたいと思います!
やることは簡単です。
まずは、巨人のデータが格納されている「df_g」に「予測したホームラン数」を追加します。
「Dataframe」の変数「df_g」に列追加したい場合は、
「Dataframe[追加したい項目名]=セットしたい値」
とすれば、新しい列が追加できます。
# 予測本塁打列の追加 df_g['予測本塁打'] = np.round(y_pred_g).astype(np.int32)
セットしたい値は、先程「予測したホームラン数」を綺麗にした値です。
これで巨人の選手データに「予測本塁打」の列が追加されています。
最後に「選手名」、「本塁打」、「予測本塁打」を指定して、データを確認してみましょう!
# 予測値と実際の値との比較結果 print(df_g[['選手名','本塁打','予測本塁打']]) # 結果 選手名 本塁打 予測本塁打 11 岡本 和真 31 30 16 丸 佳浩 27 26 20 坂本 勇人 19 19 49 吉川 尚輝 8 8 64 松原 聖弥 3 5 65 中島 宏之 7 6 70 大城 卓三 9 8 75 ウィーラー 12 11 126 若林 晃弘 2 2 129 亀井 善行 2 2 132 パーラ 4 4 145 炭谷 銀仁朗 1 1 158 重信 慎之介 1 1 167 北村 拓己 2 2 176 田中 俊太 1 1 178 陽 岱鋼 1 1 210 増田 大輝 0 0 211 岸田 行倫 1 1 212 石川 慎吾 2 2 238 立岡 宗一郎 1 2 248 小林 誠司 0 0 250 ウレーニャ 0 0 274 吉川 大幾 0 0 280 モタ 1 1 285 湯浅 大 0 0 286 香月 一也 0 0 326 加藤 脩平 0 0
各選手のホームラン数を見てみると、1、2本の誤差がある選手もいますが、
大体正確に予測ができていると思います!
5回に分けて説明してきましたが、
このようにデータを機械に読み込ませて、機械学習モデルを作成することで、
「説明変数」を渡すだけで、「目的変数」を求めることができるようになります!
最後に今回のコード全体をもう一度見てみましょう!
# 表形式データを扱うライブラリ import pandas as pd # データ分割 from sklearn.model_selection import train_test_split # モデル作成 from sklearn.linear_model import LinearRegression as LR # 評価関数 from sklearn.metrics import mean_squared_error as MSE # 行列計算ライブラリ(機械学習の結果がnumpyで返却される) import numpy as np # CSVデータ読み込み df = pd.read_csv('playerData.csv', sep = ',') # 巨人以外の11球団データを抽出 df11 = df[df['チーム'] != '巨人'] # 巨人のデータ df_g = df[df['チーム'] == '巨人'] # 本塁打との相関係数をDataFrameとして変数に保存 df_homerun = pd.DataFrame(df11.corr()['本塁打']) # 相関係数「0.7」以上の項目名を抽出 X_columns = df_homerun[df_homerun['本塁打'] >= 0.7].index.tolist() # 本塁打は目的変数のため除外 X_columns.remove('本塁打') # 説明変数と目的変数をセット X = df11[X_columns] y = df11['本塁打'] # データの分割 X_train, X_test, y_train, y_test = train_test_split(X, y, random_state = 1) # モデルの箱の準備および学習 lr = LR() lr.fit(X_train, y_train) # 予測値の算出 y_pred_test = lr.predict(X_test) # MSEの算出 mse_test = MSE(y_test, y_pred_test) # RMSEの算出 rmse_test = np.sqrt(mse_test) # RMSEの表示 print(rmse_test) # 巨人データ(説明変数) X_g = df_g[X_columns] # 予測ホームラン数の算出 y_pred_g = lr.predict(X_g) # 予測本塁打列の追加 df_g['予測本塁打'] = np.round(y_pred_g).astype(np.int32) # 予測値と実際の値との比較結果 print(df_g[['選手名','本塁打','予測本塁打']])
おまけ
少しだけおまけです。
今回はホームラン数を相関が強い項目を説明変数として、モデルを作成しました。
野球に詳しい方であれば、お気づきでしょうが、
野球の「塁打」という項目は、
「塁打」=4×「本塁打」+3×「三塁打」+2×「二塁打」+「単打」
という式で求めることができます。
なので、「本塁打」を求めたければ、
相関の強さに関係なく、「塁打」、「三塁打」、「二塁打」、「単打」を渡せば、
正確に「ホームラン数」を求めることができるはずです。
ただ今回データの中に「単打」の項目がないので、代わりに「安打」を渡してみます。
※「単打」はシングルヒット数、「安打」はホームランを含んだ全ヒット数です。
# 「安打、二塁打、三塁打、塁打」を説明変数にする X_columns = ['安打','二塁打','三塁打','塁打']
これで再度機械学習をさせて「ホームラン数」を予測してみると、
# RMSEの表示 print(rmse_test) # 予測値と実際の値との比較結果 print(df_g[['選手名','本塁打','予測本塁打']]) # 結果 4.897912368638467e-15 選手名 本塁打 予測本塁打 11 岡本 和真 31 31 16 丸 佳浩 27 27 20 坂本 勇人 19 19 49 吉川 尚輝 8 8 64 松原 聖弥 3 3 65 中島 宏之 7 7 70 大城 卓三 9 9 75 ウィーラー 12 12 126 若林 晃弘 2 2 129 亀井 善行 2 2 132 パーラ 4 4 145 炭谷 銀仁朗 1 1 158 重信 慎之介 1 1 167 北村 拓己 2 2 176 田中 俊太 1 1 178 陽 岱鋼 1 1 210 増田 大輝 0 0 211 岸田 行倫 1 1 212 石川 慎吾 2 2 238 立岡 宗一郎 1 1 248 小林 誠司 0 0 250 ウレーニャ 0 0 274 吉川 大幾 0 0 280 モタ 1 1 285 湯浅 大 0 0 286 香月 一也 0 0 326 加藤 脩平 0 0
評価関数「RMSE」の値は「4.897912368638467e-15」でほぼ「0」です。
「予測したホームラン数」と「実際のホームラン数」の値も完全一致しています。
このように「Pythonの知識」や「機械学習の知識」、「データ分析力」も必要ですが、
目的の値を正しく予測するためには、「取り組む課題自体の知識」も非常に重要になります!
まとめ:Python機械学習「予測」
ここまでの話をまとめます。
まとめ
今回は作成したモデルを使用して「予測したホームラン数」と「実際のホームラン数」を比較した!
今回やったことは、
- 巨人のデータの「説明変数」を作成した
- 作成したモデルを使用して、巨人のホームラン数を予測させた
- 予測したホームラン数と実際のホームラン数を比較した
1、2本の誤差はあったものの、ホームラン数を精度高く予測することができた!
全5回に分けて「Python機械学習」について、説明してきました。
今回の内容は機械学習の基本的な部分です。
ところどころ何やっているのか、わからなくなってしまった方は、
「概要編」を振り返ってみてください。
-
Python機械学習「ホームラン数予測①」概要編!
PythonってAIや機械学習ができるって言うけど、 誰にでもできるんだろうか。。 やっぱり難しいコードを書いたりするんだろうか。。 イメージを掴みたいな。。 こんにちは、 ...
続きを見る
全体の流れを再確認することで、機械学習の基本的な流れや、
コードの理解も進むと思います。
今回はホームランという「実数」を予測する「回帰問題」であり、
機械学習をさせるためのデータがある「教師あり学習」でした。
機械学習の分野には他にも、分類分けをする「分類問題」であったり、
「教師なし学習」ができる「ディープラーニング」の分野もあります。
まだまだ奥が深いので、
今回の内容を足掛かりにして、お互いに勉強を進めていきましょう!