SPSS Modelerの回帰モデル評価のための精度分析ノードを、pythonに書き換える

SPSS Modelerの回帰モデル評価のための精度分析ノードをPythonのscikit-learnとstatsmodelsで書き換えてみます。


以下の記事でModelerでの使い方は解説していますので、この内容をscikitlearnとstatsmodelsで行ってみます。

SPSS Modeler ノードリファレンス 6-4b 精度分析:回帰 - Qiita 

https://qiita.com/kawada2017/items/bc543f0f1bb401854c0e


pythonで線形回帰のモデルをつくるにはscikit-learnとstatsmodelsの二つのパッケージがありました。
それぞれで作ってみたいと思います。

# 1m．全データに基づく回帰モデルの精度分析　Modeler
[Modelerのノードリファレンスの記事](https://qiita.com/kawada2017/items/bc543f0f1bb401854c0e)では学習データとテストデータを分けていますが、pythonとの比較を容易にするためにまずは全データで回帰モデルをつくります。

以下のようにロールで説明変数(入力)と目的変数（対象）を定義します。モデル作成は「線形回帰ノード」を接続して実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/94cbbcc0-acf4-98c2-e739-53b93121de26.png)

できたモデルに「精度分析」ノードをつなぎ実行します。
絶対平均誤差や標準偏差（RMSE）などが得られます。各項目の意味は[Modelerのノードリファレンスの記事の表](https://qiita.com/kawada2017/items/bc543f0f1bb401854c0e#%E7%B2%BE%E5%BA%A6%E5%88%86%E6%9E%90%E5%9B%9E%E5%B8%B0%E3%81%AE%E6%8C%87%E6%A8%99)にまとめています。

また[平均絶対パーセント誤差(MAPE)](https://qiita.com/kawada2017/items/bc543f0f1bb401854c0e#4tips%E5%B9%B3%E5%9D%87%E7%B5%B6%E5%AF%BE%E3%83%91%E3%83%BC%E3%82%BB%E3%83%B3%E3%83%88%E8%AA%A4%E5%B7%AEmape)も計算しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/8b032627-9a8b-5b78-d5dc-399add0304ab.png)


# 1sk．全データに基づく回帰モデルの精度分析　scikit-learn
scikit-learnの回帰モデルは、[SPSS Modelerの線形回帰ノードを、pythonに書き換える](https://qiita.com/kawada2017/items/a288c0c208b0f1589ea6#1sk%E5%8D%98%E5%9B%9E%E5%B8%B0%E5%88%86%E6%9E%90scikit-learn)で解説したように、以下のように作ります。

```python
# 説明変数
X = df[['エンジン']]
# 目的変数
Y = df['馬力']

# 線形回帰のモデルを作成
lr = LinearRegression()
lr.fit(X, Y)
```

回帰分析の主な指標はsklearn.metricsのモジュールで用意されています。
これらを使うためにはあらかじめ、予測値を計算しておく必要があります。

* 参考　
* scikit-learn で回帰モデルの結果を評価する – Python でデータサイエンス 
 
https://pythondatascience.plavox.info/scikit-learn/%E5%9B%9E%E5%B8%B0%E3%83%A2%E3%83%87%E3%83%AB%E3%81%AE%E8%A9%95%E4%BE%A1

* API Reference — scikit-learn 1.1.2 documentation 
 
https://scikit-learn.org/stable/modules/classes.html#regression-metrics

しかしながら、Modelerの精度分析ノードで表示される指標には、このモジュールには用意されていない指標もあります。これらの指標を計算するために、残差を計算したpandasのDataFrameを作っておきます。

```python:線形回帰モデル作成
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']
```


最小誤差、最大誤差、平均誤差、頻度数は以下のように求めます。

```python:最小誤差、最大誤差、平均誤差、頻度数
df_residual['残差'].min()
df_residual['残差'].max()
df_residual['残差'].mean()
len(df_residual)
```


最大誤差についてはsklearn.metricsでも計算できます。

```python:最大誤差
from sklearn.metrics import max_error
max_error(Y, Y_pred)
```

絶対平均誤差(MAE)はsklearn.metricsで計算できます。

```python:絶対平均誤差(MAE)
from sklearn.metrics import mean_absolute_error
mean_absolute_error(Y, Y_pred)
```

二乗平均平方根誤差 (RMSE)については直接は計算できませんが、二乗平均誤差(MSE)まではsklearn.metricsで計算できます。
ですので、その結果の平方根をnp.sqrtでとります。

```python:二乗平均平方根誤差 (RMSE)
from sklearn.metrics import mean_squared_error
np.sqrt(mean_squared_error(Y, Y_pred))
```

線形相関は以下のようにcorrで求めます。
2値の相関係数なのでat['Y', 'Y_pred']で単一の値を求めています。
```python:線形相関
df_residual[['Y','Y_pred']].corr().at['Y', 'Y_pred']
```

平均絶対パーセント誤差（MAPE）についてはsklearn.metricsで計算できます。

```python:平均絶対パーセント誤差（MAPE）
from sklearn.metrics import mean_absolute_percentage_error
mean_absolute_percentage_error(Y, Y_pred)
```

上記の各指標を計算する関数を作りました。

```python:回帰モデルの評価関数
#回帰モデルの評価
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ですのでほぼゼロであることを意味しています）。
```python:指標算出
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 

https://www.statsmodels.org/dev/tools.html

sklearn.metricsとほぼ同様に最大誤差、絶対平均誤差(MAE)、二乗平均平方根誤差 (RMSE)はこのモジュールで計算可能です（RMSEが直接計算できます）。
最小誤差、平均誤差、頻度数、線形相関、そして平均絶対パーセント誤差（MAPE）はpandasなどで計算の必要があります。

```python:指標算出
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のノードリファレンスの記事](https://qiita.com/kawada2017/items/bc543f0f1bb401854c0e)と同様に、学習データとテストデータを分けて回帰モデルをつくります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/78d25c0c-676e-06dd-ff15-2993e53f82fe.png)


できたモデルに「精度分析」ノードをつなぎ実行します。
以下のように学習データとテストデータに対する指標がぞれぞれ計算されて表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/33da5ecb-7b1a-b408-6e6d-05e9cd76b707.png)

平均絶対パーセント誤差（MAPE）は集計ノードなどで計算します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/e92a64f0-f014-31f8-fe1c-7fdd4c847a89.png)


# 2sk．学習データとテストデータに分けた回帰モデルの精度分析　sklearn

以下のようにsplitで学習とテストデータに分割してモデル作成します。

```python:学習とテストデータに分割してモデル作成
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で学習データとテストデータに対してそれぞれ指標を算出します。

```python:各モデルの評価を算出
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で縦横変換して表示します。

```python:整形して表示
pd.options.display.float_format = '{:.3f}'.format
pd.DataFrame([analysis_eva_train,analysis_eva_test],index=['学習','テスト']).T
```

学習データとテストデータに対する指標がぞれぞれ表示されます（Modelerの結果とはランダムに学習とテストに分割するデータが異なるため値は異なります）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/f47583cf-58ea-a3c3-1535-60dfc15a671f.png)


# 3. 参考

2値分類モデル評価のための精度分析ノードのPython書き換えについては以下の記事で紹介しています。

SPSS Modelerの2値分類モデル評価のための精度分析ノードと評価グラフノードをPythonで書き換える。信用リスクの判定モデルの評価 - Qiita 

https://qiita.com/kawada2017/items/bf60106d08fa84304fd1

# 4. サンプル
サンプルは以下に置きました。

ストリーム

https://github.com/hkwd/200611Modeler2Python/raw/master/AnalysisEvaluationRegression/AnalysisEvaluationRegression2.str

notebook

https://github.com/hkwd/200611Modeler2Python/blob/master/AnalysisEvaluationRegression/AnalysisEvaluationRegression.ipynb

データ

https://raw.githubusercontent.com/yoichiro0903n/blue/main/cars.csv

■テスト環境
Modeler 18.4
Windows 10 64bit
Python 3.8.10
pandas 1.4.1
sklearn 1.1.1
statsmodels 0.13.2