エンジニア データサイエンティスト

Python機械学習「ホームラン数予測④」モデル作成・モデル評価編!

2020年12月20日

Python機械学習

 

「機械学習させてAIを作る!」ってなんだか難しそう。。
自分のレベルでもできるのかな。。

 

こんにちは、古賀です!

 

本記事は、

はてな

「Python機械学習でホームラン数を予測する」のモデル作成・モデル評価編

です!

 

データ分析をして、ホームランを予測するための材料を選んだら、

機械学習をして「モデル」を作成します。

モデルを作成した後は、

「どれだけ予測精度が高いか?」

モデルを評価する必要があります。

 

一見難しそうに聞こえますが、

Pythonに用意されているライブラリを使うことで、

簡単にモデルを作成することができます!

 

機械学習のメイン部分「モデル作成」と「モデル評価」の基本を学びましょう!

 

前回の続きになりますので、

前回の記事を読まれていない方はこちらをご覧ください!

Python機械学習
Python機械学習「ホームラン数予測③」データ分析編!

  ホームラン数を予測できるように機械学習させたいけど、 どんな情報を渡せば良いんだろう。。 片っ端から渡して色々と試せばいいんだろうか。。   こんにちは、古賀です! &nbsp ...

続きを見る

自己紹介が遅れましたが、

わたしは大学卒業後、上場IT企業に就職し、プログラマー、システムエンジニアとして

約10年間働いておりまして、その後は様々な活動をしております。

プロフィールの詳細はこちらです。

野球
プロフィール

こんにちは、古賀正雄です。現在36歳です。 簡単ではありますが、こちらのページで自己紹介とこのブログについてお話します。 高校時代 学生時代は主に野球をしていました。 進学先の高校も野球で選びました。 ...

続きを見る

※YouTubeに同内容を公開しております。

Python機械学習「モデル作成・モデル評価」の概要

アルゴリズム

前回の記事で、ホームラン数と関連性が高い項目を「相関係数」を使って調べて、

ホームラン数を予測するための材料「説明変数(特徴量)」と、

予測対象であるホームラン数「目的変数」に分けました。

 

今回はその「説明変数(特徴量)」「目的変数」の2つを使って、

ホームラン数を予測するための機械「モデル」を作成します。

 

「モデル」はPythonのライブラリを使って作成するので、難しいことはありません。

ただし、課題に対して万能なライブラリは存在しないので、

課題に合ったライブラリを選ぶ必要があります。

 

今回の課題は「ホームラン数」という「実数」を予測することです。

おさらいになりますが、「実数」を予測するための課題のことを「回帰問題」と呼びます。

その「回帰問題」に強いライブラリを使用してモデルを作成します。

今回は「scikit-learn」ライブラリの「LinearRegression」を使います。

「LinearRegression」は「重回帰モデル」を作成してくれます。

「重回帰モデル」を詳しく説明すると、話がややこしくなってしまうので、

簡単に説明すると、

「複数の要素から目的の値を予測するモデル」

のことです。

複数の要素とは、前回選んだ「打点数」や「塁打数」、「三振」といった要素「説明変数」のことを指しています。

本当は「グラフ」や「数式」を使って説明していきたいですが、今回は割愛します!

 

モデルを作った後すぐに、

今回の目的である「巨人の選手のホームラン数を予測してみよう!」としてもいいのですが、

ビジネスの場であれば、作成したモデルを予測精度が分からないままぶっつけ本番で使うことはできません。

 

なのでモデルを作った後に、

「モデルがどれくらいの精度で予測ができているのか?」

モデルを評価する必要があります。

モデルを評価するため関数を「評価関数」と呼びますが、これもPythonで用意されています。

先程のモデル作成と同じで、課題に合った「評価関数」を選ぶことが大事です。

 

今回は「RMSE」という評価関数を使います。

「RMSE」は「二乗平均平方根誤差」のことですが、

この説明をしてしまうと、先程と同様に難しくなってきてしまうので、

簡単に言い換えます!

「RMSE」は、

「予測値と本来の結果との誤差を表した数値で、0に近い程精度が高い」

と言えます。

「この値が0に近ければ良い予測ができているんだな」

と思ってくれれば大丈夫です!

 

「評価関数」を使ってモデルの精度を確かめるためには、

「教師データ」を2つに分けておく必要があります。

今回で言うと、11球団のデータを「学習用」と「評価用」に2分割します。

 

「学習用」のデータを使ってモデルを作成して、

「評価用」のデータを使って「RMSE」を算出して精度を確かめます。

もし、精度が悪かった場合は「説明変数」を見直したりして、モデルを改善したいと思います。

 

長くなりましたが、今回の手順は、

  1. 11球団のデータを「学習用」と「評価用」に分ける
  2. 「学習用」データと「LinearRegression」を使ってモデルを作成する
  3. 「評価用」データを使って作成したモデルの予測精度を確かめる
  4. 予測精度が悪かったら「説明変数」を見直してみる

です!

Python機械学習「モデル作成・モデル評価」をしてみる!

機械学習

前回のコードも含まれていますが、今回のコード全体です。

今からこのコードを1から説明していきます!

# 表形式データを扱うライブラリ
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)

# ↑今回の内容

「学習用」と「評価用」にデータを分割

まずは11球団のデータを「学習用」と「評価用」にデータを分割します。

「分割する!」と言っても、これもライブラリを使うことで簡単にできます。

データ分割関数を使うために、

「scikit-learn」の「train_test_split」をインポートします。

from sklearn.model_selection import train_test_split

そして、前回作成した説明変数「X」と目的変数「y」を「train_test_split」に渡します。

# データの分割
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state = 1)

説明変数「X」を「X_train」、「X_test」に、

目的変数「y」を「y_train」、「y_test」に分割しています。

「_train」が「学習用」データ、「_test」が「評価用」データを表しています。

 

分割する割合を関数の引数に指定することもできますが、今回は何も指定していないので、

学習用が「75%」、評価用が「25%」として分割されています。

 

「random_state = 1」を指定することで、

実行する度に分割結果が変わらないようにすることができます。

実行する度に結果が変わると、検証する時に紛らわしくなってしまうので、

今回は指定しておきます。(「乱数シードを固定する」と言います。)

 

このようにライブラリを使用することで、

たったの1行でデータを分割することができます!

モデルを作成する

データを分割したら「学習用」データを「LinearRegression」に渡して、

モデルを作成してもらいます。

まずはインポートです。

# モデル作成
from sklearn.linear_model import LinearRegression as LR
# 行列計算ライブラリ(機械学習の結果がnumpyで返却される)
import numpy as np

「LinearRegression」と一緒に「numpy」もインポートしています。

「numpy」は行列計算に使うライブラリです。

今回は作成したモデルが予測した結果を返却する時に、「numpy」のデータ型で返却されるので、

ここでインポートしておきます。

「行列って何?」と思われるかもしれませんが、

「配列」と似たようなものと認識しておけば大丈夫です。

 

モデル作成に戻りますが、

# モデルの箱の準備および学習
lr = LR()
lr.fit(X_train, y_train)

これだけでモデル作成が完了です!

変数「lr」に「LinearRegression」の初期化処理をして、

「fit」関数に学習用データの「X_train」、「y_train」を渡しています。

この処理で機械学習をさせているので、

材料である「説明変数」と一緒に、答えである「目的変数」も一緒に渡していることを理解しておきましょう。

材料と答えを渡すことで、「説明変数」を基に「目的変数」を求めることができるようになります。

 

それでは「評価用」データを使って、機械にホームラン数を予測させてみます。

以下の処理で、ホームラン数の予測をしています。

# 予測値の算出
y_pred_test = lr.predict(X_test)

予測するための関数「predict」に評価用説明変数「X_test」を渡して、

その結果を「y_pred_test」に格納しています。

 

この結果が先程インポートした「numpy」の行列を扱う「ndarray」というデータ型で返却されます。

# 予測結果のデータ型
print(type(y_pred_test))

# 結果
<class 'numpy.ndarray'>

中身は、

# 評価用データの予測結果
print(y_pred_test)

# 結果
[-0.17242741 -0.55741228  0.77612256  0.04856052  9.83584546  0.55244578
  1.87025822  7.87182047 -0.5508955   1.26102703 -0.48355978  6.30043621
 -0.4803014   7.63775037  0.19316455  0.58083826 16.29165456  0.40820524
 -0.25931346  9.28189665 13.93553378 -0.4803014   9.34731911  9.73437467
  0.74799635 13.57512648 -0.4803014   1.03910607  0.58466619 -0.33352944
 -0.52865631 -0.41317173 -0.02203358  3.87343107  5.28154538  5.25645991
  0.07136924  2.94753238  0.16746092 -0.32664917 -0.19487265 -0.55741228
 -0.20138943 21.59765611  5.51577292 -0.50274663 -0.51578019 -0.5125218
 17.35593076  0.98821974 13.77491708  4.31137437 -0.21731789 -0.4803014
 -0.50083338  0.56511585 11.29354957  0.46881812 -0.36828126 -0.48355978
 -0.07995762  2.5979777   2.77769704  0.11625972  5.14920073  2.38717704
 18.26802172 -0.50367966  5.75781376  0.27317033 -0.48355978 20.66037085
  1.21246607 -0.81481203  3.8425558  16.07897482]

こんな感じです。

返却結果は「評価用説明変数」で予測した「ホームラン数」だけなので、

ピンとこないかもしれませんが、

この結果の予測がどれくらい正しいかどうかは次の「評価関数」を使って確かめます!

モデルを評価する

作成したモデルの予測精度を、先程お話した「RMSE」という評価関数を使って確かめます。

まずは評価関数のインポートです。

# 評価関数
from sklearn.metrics import mean_squared_error as MSE

実は「scikit-learn」のライブラリでは「RMSE」を直接求める関数は用意されていません。

ただ「mean_squared_error」という関数で「MSE」を求めることができます。

「MSE」は「平均二乗誤差」のことで「RMSE」が二乗された値です。

なので「MSE」の値の平方根を取ることで「RMSE」を求めることができます。

 

まずは「MSE」を求めてみましょう!

# MSEの算出
mse_test = MSE(y_test, y_pred_test)

「MSE」を求める関数に評価用データの答えである「y_test」、

モデルを使って予測した結果の「y_pred_test」を渡しています。

ようは「求めた値」と「答え」を渡して、比較してくれています。

 

比較結果の「mse_test」の平方根を取ります。

# RMSEの算出
rmse_test = np.sqrt(mse_test)

「np.sqrt」に先程の比較結果「mse_test」を渡すことで、「MSE」にルートを付けます。

これで「RMSE」が求まります。

 

「RMSE」は値が0に近いほど、正しい予測ができていることを表します。

結果を確認すると、

# RMSEの表示
print(rmse_test)

# 結果
2.558647009669751

「2.5」という結果が出ました。

まったく予測できていないということではありませんが、もう少し0に近づけたいところです。

「説明変数」の見直し

モデルを改善する方法は、

「学習用」のデータ量を増やしたり、新しい項目を追加したり、方法は色々とありますが、

今回は「説明変数」を選びなおしてみましょう!

 

前回の記事で「説明変数」は、ホームラン数との「相関係数」を調べて、

「相関係数」が「0.8以上」の項目を「説明変数」としました。

「0.8以上」の項目は「塁打」、「打点」、「三振」でしたが、

もう少し「説明変数」の項目を増やすために「0.7以上」の項目を説明変数としてみましょう!

 

前回書いた説明変数を絞り込むコードを修正します。

相関係数が「0.7以上」として、説明変数の項目一覧を確認すると、

# 相関係数「0.7」以上の項目名を抽出
X_columns = df_homerun[df_homerun['本塁打'] >= 0.7].index.tolist()

# 説明変数
print(X_columns)


# 結果
['打席数', '打数', '得点', '安打', '二塁打', '本塁打', '塁打', '打点', '四球', '三振', '併殺打']

項目がかなり増えてました。

これで機械も予測しやすくなったと思うので、再度モデルを学習させて「RMSE」を確認すると、

(※学習のコードは省略)

# RMSEの表示
print(rmse_test)

# 結果
0.5751000885439533

「0,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)

 

これで次回、この作成したモデルを使用して、

今回の目的である「巨人の選手のホームラン数」を予測してみましょう!

まとめ:Python機械学習「モデル作成・モデル評価」

ここまでの話をまとめます。

まとめ

今回は「ホームラン数」を予測するためのモデルを作成して、

作成したモデルの評価を行い、「説明変数(特徴量)」の改善も行った!

今回やったことは、

  1. 11球団のデータを「学習用」と「評価用」に分けた
  2. 「学習用」データと「LinearRegression」を使ってモデルを作成した
  3. 「評価用」データを使って作成したモデルの予測精度を確かめた
  4. 「説明変数」を見直して予測精度を改善させた

ホームラン数を予測するための「精度が高いモデル」を作成することができた!

 

今回は「scikit-learn」の「ライブラリ」の使い方がメインでしたので、

コードとしてはかなり単純だったと思います。

 

ただ今回は説明を割愛しましたが、

「重回帰モデルとは何か?」

「評価関数RMSEとはどんな式で算出されるのか?」

といった内容の理解もとても重要です。

 

与えられた課題によって、

「どのモデル作成関数を使うのか?」

「どの評価関数を使えば良いのか?」

が変わってきます。

 

かなり勉強が必要な箇所なので、

興味があるところは積極的に調べてみましょう!

 

次回は最終回「予測編」です!

巨人の選手のホームラン数が予測できているか確認してみましょう!

 

※次の記事へ

Python機械学習
Python機械学習「ホームラン数予測④」モデル作成・モデル評価編!

  「機械学習させてAIを作る!」ってなんだか難しそう。。 自分のレベルでもできるのかな。。   こんにちは、古賀です!   本記事は、 はてな 「Python機械学習で ...

続きを見る

おすすめ記事

eSportsプラットフォームSPFans 1

  こんにちは、古賀です!   本記事では、わたしが個人開発したWEBサービス はてな eSportsプラットフォーム「SPFans」 の紹介をします。   以前に紹介し ...

成長するエンジニア 2

  エンジニアになったけど、いまいち成長を感じられないなぁ。。 作業スピードも品質も平凡。 この先成長していけるんだろうか。。   こんにちは、古賀です!   エンジニア ...

道のり 3

※本記事は、各記事のまとめ記事です。   こんにちは、古賀です!   本記事では、 「プログラミング未経験者がエンジニアとして働き、 年収1000万に到達するまでの道のり」 をご説 ...

プログラミングスクール 4

  プログラミングを本格的に勉強して仕事に繋げていきたいけど、 プログラミングスクール多すぎる。。 どういう目線で選べばいいんだ。。   こんにちは、古賀です。   プロ ...

-エンジニア, データサイエンティスト
-, ,

Copyright© Koga Masao's LifeBlog , 2024 All Rights Reserved.