SPSS Modelerの回帰モデル評価のための精度分析ノードをPythonのscikit-learnとstatsmodelsで書き換えてみます。
以下の記事でModelerでの使い方は解説していますので、この内容をscikitlearnとstatsmodelsで行ってみます。
SPSS Modeler ノードリファレンス 6-4b 精度分析:回帰 - Qiita
pythonで線形回帰のモデルをつくるにはscikit-learnとstatsmodelsの二つのパッケージがありました。
それぞれで作ってみたいと思います。
1m.全データに基づく回帰モデルの精度分析 Modeler
Modelerのノードリファレンスの記事では学習データとテストデータを分けていますが、pythonとの比較を容易にするためにまずは全データで回帰モデルをつくります。
以下のようにロールで説明変数(入力)と目的変数(対象)を定義します。モデル作成は「線形回帰ノード」を接続して実行します。
できたモデルに「精度分析」ノードをつなぎ実行します。
絶対平均誤差や標準偏差(RMSE)などが得られます。各項目の意味はModelerのノードリファレンスの記事の表にまとめています。
また平均絶対パーセント誤差(MAPE)も計算しました。
1sk.全データに基づく回帰モデルの精度分析 scikit-learn
scikit-learnの回帰モデルは、SPSS Modelerの線形回帰ノードを、pythonに書き換えるで解説したように、以下のように作ります。
# 説明変数
X = df[['エンジン']]
# 目的変数
Y = df['馬力']
# 線形回帰のモデルを作成
lr = LinearRegression()
lr.fit(X, Y)
回帰分析の主な指標はsklearn.metricsのモジュールで用意されています。
これらを使うためにはあらかじめ、予測値を計算しておく必要があります。
- 参考
- scikit-learn で回帰モデルの結果を評価する – Python でデータサイエンス
- API Reference — scikit-learn 1.1.2 documentation
しかしながら、Modelerの精度分析ノードで表示される指標には、このモジュールには用意されていない指標もあります。これらの指標を計算するために、残差を計算したpandasのDataFrameを作っておきます。
Y_pred = lr.predict(X) # 学習データに対して目的変数を予測
df_residual = pd.DataFrame(data={'Y': Y, 'Y_pred': Y_pred})
df_residual['残差'] = df_residual['Y']-df_residual['Y_pred']
最小誤差、最大誤差、平均誤差、頻度数は以下のように求めます。
df_residual['残差'].min()
df_residual['残差'].max()
df_residual['残差'].mean()
len(df_residual)
最大誤差についてはsklearn.metricsでも計算できます。
from sklearn.metrics import max_error
max_error(Y, Y_pred)
絶対平均誤差(MAE)はsklearn.metricsで計算できます。
from sklearn.metrics import mean_absolute_error
mean_absolute_error(Y, Y_pred)
二乗平均平方根誤差 (RMSE)については直接は計算できませんが、二乗平均誤差(MSE)まではsklearn.metricsで計算できます。
ですので、その結果の平方根をnp.sqrtでとります。
from sklearn.metrics import mean_squared_error
np.sqrt(mean_squared_error(Y, Y_pred))
線形相関は以下のようにcorrで求めます。
2値の相関係数なのでat['Y', 'Y_pred']で単一の値を求めています。
df_residual[['Y','Y_pred']].corr().at['Y', 'Y_pred']
平均絶対パーセント誤差(MAPE)についてはsklearn.metricsで計算できます。
from sklearn.metrics import mean_absolute_percentage_error
mean_absolute_percentage_error(Y, Y_pred)
上記の各指標を計算する関数を作りました。
#回帰モデルの評価
def analysis_eval(X, Y, lr):
Y_pred = lr.predict(X) # 学習データに対して目的変数を予測
df_residual = pd.DataFrame(data={'Y': Y, 'Y_pred': Y_pred})
df_residual['残差'] = df_residual['Y']-df_residual['Y_pred']
dic_analyis_eval = {}
#最小誤差
#print('最小誤差: ', df_residual['残差'].min())
dic_analyis_eval['最小誤差'] = df_residual['残差'].min()
#最大誤差を出力
from sklearn.metrics import max_error
#print('最大誤差: ', max_error(Y, Y_pred))
#dic_analyis_eval['最大誤差'] = df_residual['残差'].max()
dic_analyis_eval['最大誤差'] = max_error(Y, Y_pred)
#平均誤差
#print('平均誤差: ', df_residual['残差'].mean())
dic_analyis_eval['平均誤差'] = df_residual['残差'].mean()
#絶対平均誤差(MAE)
from sklearn.metrics import mean_absolute_error
#print('絶対平均誤差(MAE): ', mean_absolute_error(Y, Y_pred))
dic_analyis_eval['絶対平均誤差(MAE)'] = mean_absolute_error(Y, Y_pred)
#二乗平均平方根誤差 (RMSE)
from sklearn.metrics import mean_squared_error
import numpy as np
#print('二乗平均平方根誤差 (RMSE): ', np.sqrt(mean_squared_error(Y, Y_pred)))
dic_analyis_eval['二乗平均平方根誤差 (RMSE)'] = np.sqrt(
mean_squared_error(Y, Y_pred))
#線形相関
#print('線形相関: ', df_residual[['Y','Y_pred']].corr().at['Y', 'Y_pred'])
dic_analyis_eval['線形相関'] = df_residual[[
'Y', 'Y_pred']].corr().at['Y', 'Y_pred']
#頻度数
#print('頻度数: ', len(df_residual))
dic_analyis_eval['頻度数'] = len(df_residual)
#平均絶対パーセント誤差(MAPE)
from sklearn.metrics import mean_absolute_percentage_error
#print('平均絶対パーセント誤差(MAPE): ', np.sqrt(mean_absolute_percentage_error(Y, Y_pred)))
dic_analyis_eval['平均絶対パーセント誤差(MAPE)'] = mean_absolute_percentage_error(Y, Y_pred)
return dic_analyis_eval
この関数で指標を算出するとModelerの精度分析ノードと同じものが得られます(一見、平均誤差が違うように見えますが、e-15ですのでほぼゼロであることを意味しています)。
analysis_eval(X,Y,lr)
{'最小誤差': -59.57619761558347,
'最大誤差': 76.01978973370788,
'平均誤差': 8.700523295021635e-15,
'絶対平均誤差(MAE)': 12.932339595462782,
'二乗平均平方根誤差 (RMSE)': 17.852878968271614,
'線形相関': 0.8732150534421105,
'頻度数': 392,
'平均絶対パーセント誤差(MAPE)': 0.13858786059996991}
1st.全データに基づく回帰モデルの精度分析 statsmodels
statsmodelsも回帰モデルを評価するstatsmodels.tools.eval_measuresというモジュールを持っています。
Tools — statsmodels
sklearn.metricsとほぼ同様に最大誤差、絶対平均誤差(MAE)、二乗平均平方根誤差 (RMSE)はこのモジュールで計算可能です(RMSEが直接計算できます)。
最小誤差、平均誤差、頻度数、線形相関、そして平均絶対パーセント誤差(MAPE)はpandasなどで計算の必要があります。
Y_pred = lr.predict(X)
from statsmodels.tools.eval_measures import maxabs
print('最大誤差: ', maxabs(Y, Y_pred))
from statsmodels.tools.eval_measures import meanabs
print('絶対平均誤差(MAE): ', meanabs(Y, Y_pred))
from statsmodels.tools.eval_measures import rmse
print('二乗平均平方根誤差 (RMSE): ', rmse(Y, Y_pred))
最大誤差: 76.01978973370788
絶対平均誤差(MAE): 12.932339595462782
二乗平均平方根誤差 (RMSE): 17.852878968271614
2m.学習データとテストデータに分けた回帰モデルの精度分析 Modeler
Modelerのノードリファレンスの記事と同様に、学習データとテストデータを分けて回帰モデルをつくります。
できたモデルに「精度分析」ノードをつなぎ実行します。
以下のように学習データとテストデータに対する指標がぞれぞれ計算されて表示されます。
平均絶対パーセント誤差(MAPE)は集計ノードなどで計算します。
2sk.学習データとテストデータに分けた回帰モデルの精度分析 sklearn
以下のようにsplitで学習とテストデータに分割してモデル作成します。
X_train, X_test, Y_train, Y_test = train_test_split(
X, Y, test_size=0.5, random_state=1234567
)
# 線形回帰のモデルを作成
lr2 = LinearRegression()
lr2.fit(X_train, Y_train)
先ほど作った関数analysis_eva_trainで学習データとテストデータに対してそれぞれ指標を算出します。
analysis_eva_train=analysis_eval(X_train,Y_train,lr2)
analysis_eva_test=analysis_eval(X_test,Y_test,lr2)
関数analysis_eva_trainの結果は辞書型なので、それをpandas Dataframeに変換して、Tで縦横変換して表示します。
pd.options.display.float_format = '{:.3f}'.format
pd.DataFrame([analysis_eva_train,analysis_eva_test],index=['学習','テスト']).T
学習データとテストデータに対する指標がぞれぞれ表示されます(Modelerの結果とはランダムに学習とテストに分割するデータが異なるため値は異なります)。
3. 参考
2値分類モデル評価のための精度分析ノードのPython書き換えについては以下の記事で紹介しています。
SPSS Modelerの2値分類モデル評価のための精度分析ノードと評価グラフノードをPythonで書き換える。信用リスクの判定モデルの評価 - Qiita
4. サンプル
サンプルは以下に置きました。
ストリーム
notebook
データ
■テスト環境
Modeler 18.4
Windows 10 64bit
Python 3.8.10
pandas 1.4.1
sklearn 1.1.1
statsmodels 0.13.2