PyCaretにはハイパーパラメータのチューニングを自動で行う機能が備わっています。一方、その項目と範囲を手動で設定することも出来ます。本記事では、そのカスタム設定に加えて自動設定した場合とで得られたハイパーパラメータの比較、適合度の比較とその雛形コードを載せました。
import numpy as np
import random
columns_n = train_x_df.shape[1]
val_list = list(range(2, int(columns_n * 0.85), 1))
max_depth_list = random.sample(val_list, int(columns_n*0.5))
params = {
"max_depth": max_depth_list,
"min_samples_leaf": [1, 2, 4],
}
tuned_reg = tune_model(reg2,
custom_grid = params,
n_iter = 20,
optimize = 'MAE',
verbose = False)
■以降、本コードの実施例です。
本コードで分析したデータは、機械学習の回帰分析用でお馴染みのボストンデータセットのcsvファイルを使用した。csvファイルの作成例は次のリンクです。Python scikit-learn付属のボストン市の住宅価格データ(Boston house prices dataset)をcsvファイル化する - PythonとVBAで世の中を便利にする
▼ランダムフォレスト回帰のハイパーパラメータの自動調整(PyCaretのコードによる)
下図左は、ハイパーパラメータを自動で調整した場合で、下図右は調整するハイパーパラメータの項目とその探索範囲を指定して自動調整しました。その結果、両者の調整されたパラメータは異なっていますが、回帰モデルの適合度R2乗は85%を超えています。

▼当てはまりの良さのチェック
生データと予測値を散布図でプロットして、視覚的にも当てはまりの良さのチェックをします。横軸は説明変数のひとつRM(部屋数)で縦軸はボストンの住宅価格です。黒〇は生データで、赤〇はハイパーパラメータ自動調整によって得た回帰モデルによる予測値で、青〇はハイパーパラメータの探索範囲を手動で設定して自動調整によって得た回帰モデルによる予測値です。両者ともに、見た目にもあてはまりは良く、非線形回帰分析による威力です。

▼特徴量の感度順(PyCaretのコードによる)
説明変数(入力因子)を影響度が大きい順に並べてくれます。

▼SHAP Value:シャープレイ値(PyCaretのコードによる)
特徴量について、上記の感度の他にその方向も視覚的に教えてくれる手法です。横軸は目的変数の住宅価格です。例えば、説明変数のひとつRM(部屋数)を見ると、赤色(High)は図中の右寄りに集まっています。この意味は、部屋数が増えると住宅価格は上がる傾向であるということです。一方、CRIMは犯罪率です。赤色が中心より左寄りです。この意味は、犯罪率が高い地域だと住宅価格は下がる傾向にあるということです。

▼行列散布図
上図、ランダムフォレストによって導かれた特徴量の感度の高い順に、行列散布図でプロットした図です。目的変数と説明変数の関係がわかります(全部の説明変数でこれをやると、画像が非常に小さく何が何だかわからない)。また、説明変数間にも依存がみられるものがあり、これを交互作用(相互作用)と呼びます。これは自然の摂理で、何かしら互いに関係があるのは珍しくなく、線形の回帰分析で行うには無理がある理由でもあります。

■本プログラム
本コードは、Jupyter Labで作成したコードを.pyファイルで出力し、コマンドラインで動作するように一部編集したファイルです(PyCaretの主要メソッドにおいて引数verbose=False等)。csvファイルと目的変数を指定すれば汎用的には使えるかと思います。
import matplotlib
matplotlib.use('Agg')
import os
import pandas as pd
file_path = './boston_dataset.csv'
file_name = os.path.splitext(os.path.basename(file_path))[0]
df = pd.read_csv(file_path,
header=0,
encoding='utf-8')
describe_data = df.describe()
describe_data.to_csv(file_name + '_describe.csv',
sep=',',
index=True,
encoding='utf-8')
import matplotlib.pyplot as plt
plt.subplots_adjust(left=0.1, right=0.95, bottom=0.1, top=0.95)
df.hist()
plt.tight_layout()
plt.savefig('03_hist.png')
plt.close()
mytarget = 'PRICE'
feature_name_list = df.columns.values.tolist()
feature_name_list.remove(mytarget)
from pycaret.regression import *
mydata = setup(data = df,
normalize = False,
train_size = 0.7,
session_id = 1,
target = mytarget,
numeric_features = feature_name_list,
silent=True)
train_x_df = mydata[2]
print(train_x_df)
test_x_df = mydata[3]
print(test_x_df)
reg1 = create_model('rf',
verbose = False)
auto_tuned_reg = tune_model(reg1,
fold = 10,
round = 4,
n_iter = 10,
optimize = 'R2',
verbose = False)
plot_model(auto_tuned_reg, plot = 'vc')
plt.savefig('10_auto_tuned_reg_vc.png')
plt.close()
plot_model(auto_tuned_reg, plot = 'error')
plt.savefig('11_auto_tuned_reg_error.png')
plt.close()
plot_model(auto_tuned_reg, plot = 'parameter')
reg2 = create_model('rf',
ensemble = False,
method = None,
fold = 10,
round = 4,
cross_validation = True,
verbose = False)
import numpy as np
import random
columns_n = train_x_df.shape[1]
val_list = list(range(2, int(columns_n * 0.85), 1))
max_depth_list = random.sample(val_list, int(columns_n*0.5))
params = {
"max_depth": max_depth_list,
"min_samples_leaf": [1, 2, 4],
}
tuned_reg = tune_model(reg2,
custom_grid = params,
n_iter = 20,
optimize = 'MAE',
verbose = False)
plot_model(tuned_reg, plot = 'vc')
plt.savefig('14_tuned_reg_vc.png')
plt.close()
plot_model(tuned_reg, plot = 'error')
plt.savefig('15_tuned_reg_error.png')
plt.close()
plot_model(tuned_reg, plot = 'residuals')
plt.savefig('16_tuned_reg_residuals.png')
plt.close()
plot_model(tuned_reg, plot = 'parameter')
plot_model(tuned_reg, plot = 'feature')
plt.savefig('18_tuned_reg_feature.png')
plt.close()
interpret_model(tuned_reg)
plt.savefig('19_tuned_reg_feature_summary.png')
plt.close()
interpret_model(tuned_reg, plot = 'reason', observation = 10)
import seaborn as sns
df2 = df.loc[:, ['RM', 'CRIM', 'LSTAT', 'PTRATIO', 'PRICE']]
sns.set_context('talk')
mypairplot = sns.pairplot(df2,
kind="reg",
markers=".",
diag_kind="kde",
diag_kws=dict(shade=True),)
plt.savefig('21_pairplot.png')
plt.close()
final_reg1 = finalize_model(auto_tuned_reg)
predict_df1 = predict_model(final_reg1, data=test_x_df)
final_reg2 = finalize_model(tuned_reg)
predict_df2 = predict_model(final_reg2, data=test_x_df)
myindex = test_x_df.index
predict_df1.set_index(myindex, inplace=True)
predict_df2.set_index(myindex, inplace=True)
test_xy_df = df.iloc[test_x_df.index]
predict_df1 = predict_df1.rename(columns={'Label': 'PREDICT_by_auto_tuned_model'})
predict_df2 = predict_df2.rename(columns={'Label': 'PREDICT_by_custom_tuned_model'})
DF = pd.concat([test_xy_df,
predict_df1.loc[:, 'PREDICT_by_auto_tuned_model'],
predict_df2.loc[:, 'PREDICT_by_custom_tuned_model']],
axis=1)
x_name = 'RM'
y_name = 'PRICE'
fig = plt.figure(dpi=120)
ax = fig.add_subplot(1,1,1, facecolor='lightyellow')
ax.set_title('test_data', fontsize=14)
ax.set_xlabel(x_name, fontsize=16)
ax.set_ylabel(y_name + '(target)', fontsize=16)
ax.scatter(DF.loc[:,x_name], DF.loc[:,y_name],
facecolors='none', edgecolors='k', label='Raw data')
ax.scatter(DF.loc[:,x_name], DF.loc[:,'PREDICT_by_auto_tuned_model'],
facecolors='none', edgecolors='r', label='auto tuned RandomForest model')
ax.scatter(DF.loc[:,x_name], DF.loc[:,'PREDICT_by_custom_tuned_model'],
facecolors='none', edgecolors='b', label='custom tuned RandomForest model')
ax.legend(loc='best', fontsize=14)
ax.tick_params(labelsize=16)
plt.tight_layout()
plt.subplots_adjust(left=0.1, right=0.95, bottom=0.1, top=0.95)
plt.savefig('23_scatter_raw_vs_pred1_vs_pred2.png')
plt.close()
import datetime
now = datetime.datetime.now()
now = now.strftime("%y%m%d")
save_model(tuned_reg, model_name = 'boston_randomforest_model_' + now)
load_reg_model = load_model('boston_randomforest_model_' + now)
for i, data in enumerate(load_reg_model):
print(i, data)
if 'RandomForestRegressor' in str(data):
element_No = i
load_reg = load_reg_model[element_No]
plot_model(load_reg, plot = 'parameter')
print('finished')
以上
<広告>
リンク