0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Learn Python In Seminars〜モデル学習の基本〜

Posted at

概要

今回はモデル学習の一通りの流れを実施します。
メモ的なものとしてみていただければと思います。

モデル学習の準備

インポート

import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error as MSE
from sklearn.linear_model import LinearRegression as LR

データの分割

scikit-learnライブラリのtrain_test_split関数

X_train, X_test, y_train, y_test = train_test_split(説明変数、目的変数, random_state=num, test_size=sizeNum)

random_state:毎回同じように分割(過学習を防止)
test_size:分割割合を指定(0.2の場合、全データのうち、80%を学習用データ、20%を評価用データ)
学習データ75%、評価データ25%となるように分割

評価関数の定義

RMSE(Root Mean Squared Error)

MSEは予測誤差の絶対値をとるが、RMSEでは予測誤差を2乗する。そのため、MSEよりも解釈が難しいが、大きな予測誤差を出さないモデル傾向となる

1.numpyのみライブラリでの実装

# データの生成
actual = np.array([4,6,8]) # 実績値
pred = np.array([2,8,10]) # 予測値

# numpyのarray型同士を引き算すると各要素ごとに引き算が実行
a = actual - pred
print(a) # [ 2 -2 -2] 

# 累乗はnp.power関数を使用。引数にはn乗のnの値
b = np.power(a, 2)
print(b) # [ 8 -8 -8]

# 要素同士の足し算にはnp.sum関数を使用
c = np.sum(b)
print(c) # -8

# cの値をデータのサイズで割り算
d = c / 3
print('d',d) # -4.0

# np.sqrt関数で平方根を取る
e = np.sqrt(d)

# 計算結果の表示
print(e) # 2.0

↓ 1行で記述すると

RMSE = np.sqrt(np.mean(np.power(actual-pred,2)))
  1. scikit-learnライブラリでの実装

scikit-learnにはRMSEが未実装のため、RMSEの平方根を取る前の値であるMSE(Mean Squared Error)を利用し、RMSEを算出

np.sqrt(MSE(実績値, 予測値))

モデルの学習

線形回帰モデル

  1. 単回帰モデル:y = ax + b、aが傾き、bが切片
  2. 重回帰モデル:y = a1x1 + a2x2 + … + b、 aが各説明変数の係数、bは切片

重回帰モデルの作成

scikit-learnライブラリのLinearRegressionで重回帰モデルの作成が可能

# データの分割
X_train, X_test, y_train, y_test = train_test_split(X(説明変数), y(被説明変数), random_state=32)

# モデルの生成
lr = LR()

# モデルの学習
lr.fit(X_train, y_train)

モデルの精度評価

予測値の取得

skleanライブラリのpredictで予測値を取得可能

y_pred_train = lr.predict(X_train)

↓ 結果の例

# numpyの配列を表すndarray型で返ってくる
[25.22182295 22.71044791 33.42986757 23.12417403 21.86445237 20.96844498 

 27.32922    25.61715159 15.64848023 18.74273426 26.67452757 25.33549792]

RMSE

学習データのRMSE

# MSEの算出
mse = MSE(y_train(実績値), y_pred_train(予測値))

# RMSEの算出
rmse_train = np.sqrt(mse)

7.777777777777777

汎用化性能の検証

評価データへの予測値

# X_testに対する予測値を算出
y_pred_test = lr.predict(X_test)

過学習の検証

過学習が発生している場合、学習データへの予測精度は高いが、評価データへの予測精度が著しく低い

<正常>
学習データのRMSE = 0.64
評価データのRMSE = 0.55

<過学習>
学習データのRMSE = 0.00
評価データのRMSE = 0.91

*RMSEは値が小さいほど誤差が小さい

評価データのRSME

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

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

予測精度の可視化

具体的な予測値の傾向として、予測値が小さい時に外しやすいのか、大きい時に外しやすいのかを把握することができれば、予測モデルを改良するアプローチを検討するためのヒントとなる。その可視化方法として、縦軸を予測値、横軸を実測値とした散布図を利用。

手順

  1. グラフのサイズを指定して、グラフの大きさを正方形になるように設定
  2. 横軸を実測値、縦軸を予測値として、散布図を描画
  3. y_test、y_pred_testの両方を見た上での最小値と最大値を算出
  4. 最小値と最大値を使い、x軸およびy軸の値域を指定し、揃える
  5. 対角線を描画

正方形の散布図

matplotlibライブラリのplt.figure関数でグラフのサイズを指定、plt.scatter関数で散布図を描画

# サイズ指定
plt.figure(figsize=(横幅, 縦幅))

# 散布図
plt.scatter(y_test(X軸), y_pred_test(Y軸))

# 可視化
plt.show()

最大値と最小値

numpyのnp.max関数とnp.min関数、np.maximum関数とnp.minimum関数で算出可能

# y_testの最小値・最大値を算出
test_min = np.min(y_test)
test_max = np.max(y_test)

# y_pred_testの最小値・最大値を算出
pred_min = np.min(y_pred_test)
pred_max = np.max(y_pred_test)

# 値を比較し、最終的な最小値・最大値を算出
min_value = np.minimum(test_min, pred_min)
max_value = np.maximum(test_max, pred_max)

最大値と最小値を適用

matplotlibライブラリのplt.xlim関数でx軸、plt.ylim関数でy軸の指定

# 今回は正方形を作成するので、xlimとylimの値は同じ

# plt.xlim([xmin, xmax])
plt.xlim([min_value, max_value])

# plt.ylim([ymin, ymax])
plt.ylim([min_value, max_value])

対角線の描画

matplotlibライブラリのplt.plot関数

# plt.plot([x1,x2],[y1,y2])
plt.plot([min_value, max_value],[min_value, max_value])

最終的なイメージ

下記のようなグラフから実績値が小さいもの時に比べて、実績値が大きい時に予測誤差が大きい傾向があることがわかり、予測モデルの改善に繋げることが可能

予測精度の改善

ダミー変数

  • 質的データを量的データに変換

Pandasのpd.get_dummies関数でダミー変数を生成可能

sample = pd.DataFrame({'index':[0,1,2],'果物':['みかん','いちご','メロン'],'個数':[100,200,300]})
dummy = pd.get_dummies(sample)

↓ One-Hot表現:1カラムだけを「1」としてデータを表す方法

# 自動的に質的データのみをダミー変数化
   index   個数  果物_いちご  果物_みかん  果物_メロン 

0      0  100       0       1       0 

1      1  200       1       0       0 

2      2  300       0       0       1 

RSMEを再度算出して、再検証可能となる

対数化

  • ある値を対数変換
  • 指数関数に線形回帰モデルが当てはめることができないため、指数関数を対数化し、直線にする

numpyライブラリのlog関数で対数化

# DataFrameにはないカラム名を指定して値を代入した場合、新しいカラムとしてDataFrameに追加
DataFrame['新たなカラム名'] = np.log(DataFrame['対数化するカラム名'])

RSMEを再度算出して、再検証可能となる

コードのまとめ

# ライブラリのimport
import pandas as pd
import numpy as np
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

# データの読み込み
data = pd.read_csv('data.tsv', sep='\t')

# idの削除
data = data.drop(columns=['id'])

# 欠損値を含む行の削除
data = data.dropna() 

# 対数化
data['new_column']= np.log(data['column'])

# 目的変数及び説明変数を表す変数の準備
y = data['obj_column'] # 目的変数
X = data[['sbj_column1','sbj_column2']] # 説明変数
X = pd.get_dummies(X) # 各説明変数のダミー変数化

# データの分割
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_train = lr.predict(X_train)
y_pred_test = lr.predict(X_test)

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

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

最後に

今回は予測モデルの基本的な作成手順・方法についてのメモとして書きました。
こちらでは、実際のデータを用いて予測モデルを作成し、SIGNATEに提出するところまで行っていますので、合わせてご覧いただけると良いかと思います。


- Miyata Koki - O:inc.でAmplify×React×React Nativeを使用して開発しています。大学のゼミでは統計学をPythonで行っています。 インターンやゼミで学んだ情報を発信していくので、フォロバもしますのでぜひこちらのアカウントのフォローお願いします!
0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?