"""
scikit-regressions.py
概要:
scikit-learnの様々な回帰モデルを使用してデータ分析と予測を行うスクリプト。
詳細説明:
Excelファイルからデータを読み込み、記述子(独立変数)と目的変数(従属変数)を抽出します。
データをトレーニングセットとテストセットに分割し、指定された回帰モデル(線形回帰、リッジ、LASSO、
Elastic Net、多項式回帰、ガウス過程回帰、多層パーセプトロン、ランダムフォレスト、SVR、SGDRegressor)で学習を行います。
学習後、トレーニングデータ、テストデータ、および目的変数が欠損しているデータに対して予測値を計算し、
評価指標(MAE, MSE, RMSE, R^2)を出力します。
予測結果は元のデータフレームに結合され、新しいExcelファイルとして保存されます。
さらに、データの分布、相関、実測値と予測値の比較、各記述子に対する目的変数の変動など、
様々な種類のグラフ(箱ひげ図、ヒートマップ、ペアプロット、散布図)を生成して表示します。
コマンドライン引数を通じて、入力ファイル、回帰手法、分割比率、モデルパラメータ、プロットオプションなどを
柔軟に設定できます。
関連リンク:
:doc:`scikit-regressions_usage`
# sklearnの回帰モデルを片っ端から試す
# https://qiita.com/futakuchi0117/items/72ce4afae9adcccd6e18
"""
import sys
import os
import builtins
import re
import math
import numpy as np
from numpy import sqrt
import openpyxl
import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
from sklearn.model_selection import train_test_split
# sklearnの回帰モデルを片っ端から試す
# https://qiita.com/futakuchi0117/items/72ce4afae9adcccd6e18
from sklearn.linear_model import LinearRegression, Ridge, Lasso, ElasticNet, SGDRegressor
from sklearn.linear_model import PassiveAggressiveRegressor, ARDRegression, RidgeCV
from sklearn.linear_model import TheilSenRegressor, RANSACRegressor, HuberRegressor
from sklearn.neural_network import MLPRegressor
from sklearn.svm import SVR, LinearSVR
from sklearn.neighbors import KNeighborsRegressor
import sklearn.gaussian_process as gp
from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import RandomForestRegressor, AdaBoostRegressor, ExtraTreesRegressor, HistGradientBoostingRegressor
from sklearn.ensemble import BaggingRegressor, GradientBoostingRegressor, VotingRegressor, StackingRegressor
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import Pipeline
from sklearn.cross_decomposition import PLSRegression
import matplotlib.pyplot as plt
import seaborn as sns
from tklib.tkutils import replace_path
from tklib.tkapplication import tkApplication
from tklib.tkgraphic.tkplotevent import tkPlotEvent
#==============================================
# Global variables
#==============================================
prog_name = 'scikit-regressions'
version = [1, 0, 1]
#=======================================
# プログラム開始
#=======================================
infile = 'boston.xlsx'
method = 'rfr'
f_test = 0.3
random_state = ''
alpha = 1.0
l1_ratio = 0.5
nmaxiter = 1000
# for RFR
max_depth = ""
n_estimators = 100
max_features = 'auto'
# for MLP
# Activation: ‘identity’, ‘logistic’, ‘tanh’, ‘relu’
# Solver: ‘lbfgs’, ‘sgd’, ‘adam’
hlsizes = "5, 5, 5, 5"
mlp_solver = 'lbfgs'
mlp_activation = 'relu'
# for sns heatmap
heatmap_colormap = 'coolwarm'
heatmap_center = 0.0
plot_boxplot = 1
plot_heatmap = 1
plot_pairplot = 1
plot_variation = 1
figsize = (6, 6)
fontsize = 16
fontsize_s = 12
#===================================================================================
# Basic functions / classes
#===================================================================================
[ドキュメント]
def pint(s, def_val = None):
"""
概要:
文字列を整数に変換する。
詳細説明:
指定された文字列を整数型に変換して返す。
変換に失敗した場合は、デフォルト値 `def_val` を返す。
:param s: 変換対象の文字列。
:type s: str
:param def_val: 変換失敗時に返すデフォルト値。Noneの場合はNoneを返す。
:type def_val: int or None
:returns: 変換された整数、または `def_val`。
:rtype: int or None
"""
try:
return int(s)
except:
return def_val
[ドキュメント]
class tkObject:
"""
概要:
汎用的なオブジェクト基底クラス。
詳細説明:
オブジェクトの属性の取得、設定、更新、および標準出力へのパラメータ情報表示機能を提供する。
"""
[ドキュメント]
def get(self, key, defval = None):
"""
概要:
オブジェクトの属性値を取得する。
詳細説明:
指定されたキーに対応する属性値を取得する。
キーが存在しない場合はデフォルト値を返す。
:param key: 取得する属性のキー(名前)。
:type key: str
:param defval: キーが存在しない場合に返すデフォルト値。
:type defval: any
:returns: 属性値、または `defval`。
:rtype: any
"""
return self.__dict__.get(key, defval)
[ドキュメント]
def set_attribute(self, key, val):
"""
概要:
オブジェクトの属性値を設定する。
詳細説明:
指定されたキーに値を設定する。
もしキーがすでに存在すれば上書きし、存在しなければ新たに作成する。
:param key: 設定する属性のキー(名前)。
:type key: str
:param val: 設定する値。
:type val: any
:returns: なし
:rtype: None
"""
self.__dict__[key] = val
[ドキュメント]
def update(self, **args):
"""
概要:
複数の属性値を一括で更新する。
詳細説明:
キーワード引数として渡された辞書でオブジェクトの属性を更新する。
既存の属性は上書きされ、新しい属性は追加される。
:param args: 更新する属性のキーと値のペア。
:type args: dict
:returns: なし
:rtype: None
"""
self.__dict__.update(args)
[ドキュメント]
def printinf(self, app):
"""
概要:
オブジェクトのパラメータ情報を標準出力に表示する。
詳細説明:
オブジェクトの内部辞書 (`__dict__`) に含まれるすべてのキーと値のペアを整形して出力する。
:param app: Tkinterアプリケーションインスタンス (未使用)。
:type app: tklib.tkapplication.tkApplication
:returns: なし
:rtype: None
"""
print("Parameters:")
for key in self.__dict__.keys():
print(f" {key}: {self.__dict__[key]}")
[ドキュメント]
class tkParams(tkObject):
"""
概要:
プログラムのパラメータを管理するクラス。
詳細説明:
`tkObject` を継承し、コマンドライン引数を初期化時に保持し、
パラメータを更新する機能を提供する。
プログラムの実行時に指定される様々な設定値を格納するために使用される。
:param parameter_file: パラメータを読み込むファイルパス (現在は未使用)。
:type parameter_file: str or None
:param args: キーワード引数として渡される初期パラメータ。
:type args: dict
"""
def __init__(self, parameter_file = None, **args):
"""
概要:
`tkParams` オブジェクトを初期化する。
詳細説明:
親クラス `tkObject` の初期化を行い、現在のコマンドライン引数を内部変数に格納する。
その後、`**args` で渡されたキーワード引数で属性を更新する。
:param parameter_file: パラメータを読み込むファイルパス (現在は未使用)。
:type parameter_file: str or None
:param args: キーワード引数として渡される初期パラメータ。
:type args: dict
:returns: なし
:rtype: None
"""
super(tkObject, self).__init__(**args) # tkObjectにはinitが明示的に定義されていないため、この行はobjectのinitを呼ぶことになる
self._argv = sys.argv
self.update(**args)
[ドキュメント]
def printinf(self, app):
"""
概要:
オブジェクトのパラメータ情報を標準出力に表示する。
詳細説明:
オブジェクトの内部辞書 (`__dict__`) に含まれるすべてのキーと値のペアを整形して出力する。
このメソッドは `tkObject` の `printinf` と同じ動作をする。
:param app: Tkinterアプリケーションインスタンス (未使用)。
:type app: tklib.tkapplication.tkApplication
:returns: なし
:rtype: None
"""
print("Parameters:")
for key in self.__dict__.keys():
print(f" {key}: {self.__dict__[key]}")
if __name__ == "__main__":
argv = sys.argv
narg = len(argv)
print("narg=", narg)
if narg >= 2:
infile = argv[1]
if narg >= 3:
method = argv[2]
if narg >= 4:
f_test = float(argv[3])
if narg >= 5:
alpha = float(argv[4])
if narg >= 6:
l1_ratio = float(argv[5])
if narg >= 7:
nmaxiter = int(argv[6])
if narg >= 8:
plot_boxplot = int(argv[7])
if narg >= 9:
plot_heatmap = int(argv[8])
if narg >= 10:
plot_pairplot = int(argv[9])
if narg >= 11:
plot_variation = int(argv[10])
if narg >= 12:
hlsizes = argv[11]
if narg >= 13:
mlp_solver = argv[12]
if narg >= 14:
mlp_activation = argv[13]
if narg >= 15:
max_depth = argv[14]
if narg >= 16:
n_estimators = argv[15]
n_estimators = 100 # ここで引数の値が上書きされる可能性がある。
if narg >= 17:
max_features = argv[16]
if narg >= 18:
random_state = argv[17]
[ドキュメント]
def remove_control_tag(s):
"""
概要:
文字列から特定の制御タグを削除する。
詳細説明:
入力文字列が空の場合はそのまま返す。
文字列がハイフン (`-`) で始まる場合は、最初の2文字(例えば `-x` から `x`)を削除する。
または、`t:`, `o:`, `max:`, `min:` などのパターンにマッチした場合、そのタグ部分を削除した文字列を返す。
それ以外の場合は、元の文字列をそのまま返す。
:param s: 制御タグを含む可能性のある入力文字列。
:type s: str
:returns: 制御タグが削除された文字列。
:rtype: str
"""
if s == '':
return s
if s[0] == '-':
return s[2:]
m = re.match(r'\s*(t|o|max|min)(\d*):(.*)\s*$', s)
if m:
return m.groups()[2]
return s
[ドキュメント]
def split_df(df):
"""
概要:
DataFrameを記述子、目的変数、全データ、既存データ、予測対象データに分割する。
詳細説明:
入力DataFrameの列名から、特定のパターン(`-`や`t:`、`o:`、`max:`、`min:`など)に基づいて
記述子(独立変数)と目的変数(従属変数)を識別する。
目的変数が欠損している行は予測対象データ (`predict_data.df`) として分離し、
目的変数がすべて存在する行は既存データ (`exist_data.df`) として扱う。
元の制御タグが付いた列名と、タグが削除されたクリーンな列名 (`labels0`) の両方を管理する。
:param df: 分割対象のPandas DataFrame。
:type df: pandas.DataFrame
:returns:
以下のtkParamsオブジェクトのタプル:
- descriptors: 記述子に関する情報(列名、データフレーム)。
- objectives: 目的変数に関する情報(列名、データフレーム)。
- all: 元のDataFrameに関する情報(全列名、全データフレーム)。
- exist_data: 目的変数がすべて存在する行のデータフレーム。
- predict_data: 目的変数が欠損している行のデータフレーム。
:rtype: tuple[tkParams, tkParams, tkParams, tkParams, tkParams]
"""
all = tkParams()
exist_data = tkParams()
predict_data = tkParams()
objectives = tkParams()
descriptors = tkParams()
all.labels = df.columns.tolist()
objectives.labels = []
descriptors.labels = all.labels.copy()
for l in all.labels:
if l == '' or l[0] == '-':
descriptors.labels.remove(l)
elif re.match(r'\s*(t|o|max|min)(\d*):', l):
objectives.labels.append(l)
if len(objectives.labels) == 0:
objectives.labels.append(all.labels[0])
for o in objectives.labels:
if o in descriptors.labels:
descriptors.labels.remove(o)
# print("all=", all.labels)
# print("descriptors=", descriptors.labels)
# print("objectives=", objectives.labels)
predict_data.df = df
for label in objectives.labels:
predict_data.df = predict_data.df[pd.isnull(predict_data.df[label])]
predict_data.index = predict_data.df.index.tolist()
# print("null_data=", predct_data.df)
exist_data.df = df.copy()
exist_data.df = exist_data.df.dropna(how = 'any', axis = 0)
all.df = df
objectives.df = exist_data.df[objectives.labels]
descriptors.df = exist_data.df[descriptors.labels]
# objectives.df = df[objectives.labels]
# descriptors.df = df[descriptors.labels]
all.labels0 = [remove_control_tag(s) for s in all.labels]
objectives.labels0 = [remove_control_tag(s) for s in objectives.labels]
descriptors.labels0 = [remove_control_tag(s) for s in descriptors.labels]
return descriptors, objectives, all, exist_data, predict_data
[ドキュメント]
def main():
"""
概要:
メイン処理を実行する関数。
詳細説明:
プログラムの開始点であり、コマンドライン引数とグローバル変数からパラメータを読み込む。
Excelファイルを読み込み、`split_df` 関数でデータを記述子と目的変数に分割する。
データをトレーニングセットとテストセットに分割し、指定された回帰モデルで学習・予測を行う。
各種評価指標(MAE, MSE, RMSE, R^2)を計算し、予測結果をExcelファイルに保存する。
最後に、データの分布、相関、実測値と予測値の比較、各記述子に対する目的変数の変動など、
様々な種類のグラフを生成して表示する。
:returns: なし
:rtype: None
"""
global random_state, max_features, max_depth
app = tkApplication()
app.log_path = app.replace_path(infile)
app.redirect(["stdout", app.log_path], "w", redirect_traceback = True, output_traceback = 'stdout', display_type_traceback = 'colored')
outdir = replace_path(infile, '{dirname}')
outfile = replace_path(infile, '{dirname}/{filebody}-predict.xlsx')
outfile = os.path.join(outdir, outfile)
print("")
print("#=============================================")
print("# Regression by scikit-learn functions")
print("#=============================================")
print(f"infile ={infile}")
print(f"outfile={outfile}")
print(f"method={method}")
print(f"Fraction of test data={f_test}")
print(f"Seed of random() for split data={random_state}")
print(f"nmaxiter={nmaxiter}")
print(f"For Ridge/LASSO/Elastic Net:")
print(f" alpha={alpha}")
print(f" l1_ratio={l1_ratio}")
print(f"For Random Forest Regression:")
print(f" max_depth={max_depth}")
print(f" n_estimators={n_estimators}")
print(f" max_features={max_features}")
print(f"For Multilayer Perceptoron Regression:")
print(f" hidden layer sizes={hlsizes}")
print(f" mlp_solver={mlp_solver}")
print(f" mlp_activation={mlp_activation}")
print(f"Plot options:")
print(f" plot_boxplot={plot_boxplot}")
print(f" plot_heatmap={plot_heatmap}")
print(f" plot_pairplot={plot_pairplot}")
if '***' in method:
input("\nError: Choose method\n")
exit()
print("")
print(f"Read [{infile}]")
df = pd.read_excel(infile, engine = 'openpyxl')
# all.df : Excelから読み込んだ全データ
# exist_data.df : all.dfのうち、目的関数が埋まっているデータ
# predict_data.df: all.dfのうち、目的関数が埋まっていないデータ
# descriptors, objectives: exist_data.dfからdescriptorとobjectiveに分別
descriptors, objectives, all, exist_data, predict_data = split_df(df)
# print("descriptors=", descriptors.labels0)
# print("objectives=", objectives.labels0)
labels = all.labels[0]
# 記述子
x_labels = descriptors.labels
x_all = all.df[x_labels]
x = exist_data.df[x_labels]
x_predict = predict_data.df[x_labels]
# x = df[x_labels]
# 目的関数
o_label = objectives.labels[0]
y = exist_data.df[o_label]
# y = df[o_label]
print("")
print("Data check")
print("isnull()", exist_data.df.isnull())
print("isna()", exist_data.df.isna())
ndata = len(exist_data.df.index)
ndescriptors = len(x_labels)
print("ndata=", ndata)
print("ndescriptors=", ndescriptors)
print(" all_labels=", all.labels)
print(" x_labels =", x_labels)
print(" o_label =", o_label)
print("")
print("Split to training and test data")
if random_state == '':
random_state = None
else:
random_state = pint(random_state)
x_train, x_test, y_train, y_test, df_train, df_test, index_train, index_test = \
train_test_split(x, y, exist_data.df, exist_data.df.index, test_size = f_test, random_state = random_state)
# train_test_split(x, y, df, test_size = f_test, random_state = random_state)
print(" Number of training data:", len(x_train))
print(" Number of test data:", len(x_test))
n_train = len(x_train)
n_test = len(x_test)
n_predict = len(x_predict)
#共分散
print("")
print("Covariances of standardized values")
scaler_cov = StandardScaler()
scaler_cov.fit(exist_data.df)
# scaler_cov.fit(all.df)
df_std = scaler_cov.transform(exist_data.df)
# df_std = scaler_cov.transform(all.df)
def covariance(list_list, ddof = 1):
if ddof == 1:
return np.cov(list_list, bias = True)
else:
return np.cov(list_list, bias = False)
n = len(all.labels)
cov = covariance(df_std)
for i in range(n):
for j in range(i+1, n):
v = cov[i, j]
if abs(v) > 0.5:
print(f"++({i:2}, {j:2}) ({all.labels[i]:>10}, {all.labels[j]:>10}): {v:8.4f}")
elif abs(v) > 0.7:
print(f"**({i:2}, {j:2}) ({all.labels[i]:>10}, {all.labels[j]:>10}): {v:8.4f}")
elif abs(v) > 0.9:
print(f"##({i:2}, {j:2}) ({all.labels[i]:>10}, {all.labels[j]:>10}): {v:8.4f}")
else:
print(f" ({i:2}, {j:2}) ({all.labels[i]:>10}, {all.labels[j]:>10}): {v:8.4f}")
print("")
print(f"Execute regression")
print(f"Standaridization")
scaler = StandardScaler()
scaler.fit(x_train)
x_scaled_train = scaler.transform(x_train)
x_scaled_test = scaler.transform(x_test)
x_scaled_all = scaler.transform(x_all)
if n_predict > 0:
x_scaled_predict = scaler.transform(x_predict)
print("Fit")
if method == 'linear':
model = LinearRegression()
elif method == 'ridge':
model = Ridge(alpha = alpha)
elif method == 'lasso':
model = Lasso(alpha = alpha, max_iter = nmaxiter, tol = 1.0e-4)
elif method == 'elnet':
model = ElasticNet(alpha = alpha, l1_ratio = l1_ratio, max_iter = nmaxiter, tol = 1.0e-4)
elif method == 'poly2':
model = Pipeline([('poly', PolynomialFeatures(degree = 2)),('linear', LinearRegression())])
elif method == 'poly3':
model = Pipeline([('poly', PolynomialFeatures(degree = 3)),('linear', LinearRegression())])
elif method == 'poly4':
model = Pipeline([('poly', PolynomialFeatures(degree = 4)),('linear', LinearRegression())])
elif method == 'poly5':
model = Pipeline([('poly', PolynomialFeatures(degree = 5)),('linear', LinearRegression())])
elif method == 'gpr':
model = GaussianProcessRegressor(kernel = gp.kernels.RBF(length_scale = 1.0), alpha = alpha)
elif method == 'mlp':
# Define Neural Neowork model
hidden_layer_sizes = [int(s) for s in hlsizes.split(',')]
model = MLPRegressor(hidden_layer_sizes = hidden_layer_sizes, learning_rate = 'constant', learning_rate_init = 0.001,
momentum = 0.9, max_iter = nmaxiter, tol = 1.0e-7,
nesterovs_momentum = True, power_t = 0.5, random_state = None, shuffle=True,
validation_fraction = 0.1,
solver = mlp_solver, activation = mlp_activation,
alpha = 1.0e-4, batch_size = 'auto', beta_1 = 0.9, beta_2 = 0.999,
verbose = True, warm_start = False, early_stopping = True, n_iter_no_change = 5)
elif method == 'rfr':
if pint(max_depth) is not None:
max_depth = pint(max_depth)
else:
max_depth = None
if pint(max_features) is not None:
max_features = pint(max_features)
else:
max_features = None
model =RandomForestRegressor(bootstrap = True, criterion = 'squared_error',
n_estimators = n_estimators, max_depth = max_depth,
max_features = 'auto', max_leaf_nodes = None,
min_impurity_decrease = 0.0,
min_samples_leaf = 1, min_samples_split = 2,
min_weight_fraction_leaf = 0.0, n_jobs = -1,
oob_score = False, random_state = random_state, verbose = True, warm_start = False)
elif method == 'svr':
model = SVR(kernel = 'rbf', C = 1.0e3, gamma = 0.1, epsilon = 0.1)
elif method == 'sgdr':
model = SGDRegressor()
else:
print("")
print(f"Error: Invalide model [{model}]")
print("")
exit()
model.fit(x_scaled_train, y_train)
print("")
print(f"Calculate predicted values")
y_cal_train = model.predict(x_scaled_train)
y_cal_all = model.predict(x_scaled_all)
if n_predict > 0:
y_cal_predict = model.predict(x_scaled_predict)
if method == 'gpr':
y_cal_test, y_std_test = model.predict(x_scaled_test, return_std = True)
else:
y_cal_test = model.predict(x_scaled_test)
mae_train = mean_absolute_error(y_train, y_cal_train)
mse_train = mean_squared_error(y_train, y_cal_train)
rmse_train = sqrt(mse_train)
r2_train = r2_score(y_train, y_cal_train)
mae_test = mean_absolute_error(y_test, y_cal_test)
mse_test = mean_squared_error(y_test, y_cal_test)
rmse_test = sqrt(mse_test)
r2_test = r2_score(y_test, y_cal_test)
print("")
print("Scores:")
print(f" Mean absolute error (MAE): training {mae_train:10.3g} test: {mae_test:10.3g}")
print(f" Mean squared error (MSE) : training {mse_train:10.3g} test: {mse_test:10.3g}")
print(f" Root MSE (RMSE) : training {rmse_train:10.3g} test: {rmse_test:10.3g}")
print(f" R^2 score : training {r2_train:10.3g} test: {r2_test:10.3g}")
# modelオブジェクトにintercept, coef_があるか確認するため、
# オブジェクトの辞書型変数 __dict__ に直接アクセスし、get()で確認する
# if model.__dict__.get('intercept', None) is not None:
print("")
print("Parameters:")
try:
print(f" intercept: {model.intercept_}")
except:
pass
if model.__dict__.get('coef_', None) is not None:
print( " coefficients")
for iv in range(len(x_labels)):
print(f" {x_labels[iv]:>10}: {model.coef_[iv]:12.4g}")
predict_df = all.df.copy()
predict_df.insert(0, 'predict', y_cal_all)
print("")
print(f"Save predict data to [{outfile}]")
predict_df.to_excel(outfile)
#================================================================
# Plot
#================================================================
# プロット用のx, yの値
print("")
print("plot")
plot_event = tkPlotEvent(plt)
ymin = min(y)
ymax = max(y)
#箱ひげ図
if plot_boxplot:
plt.rcParams['font.size'] = 18
scaler = StandardScaler()
scaler.fit(df.values)
values_std = scaler.transform(df.values)
figures, axises = plt.subplots(figsize = figsize)
axises.boxplot(values_std, vert = False)
# axises.boxplot(df.values, vert = False)
axises.set_yticklabels(df.columns)
plt.xlabel('Values')
plt.pause(0.1)
#相関係数とヒートマップ
if plot_heatmap:
print("")
print("Correlation heatmap")
corr = df.corr()
print(corr)
plt.rcParams['font.size'] = 6
figures, axises = plt.subplots(figsize = figsize)
if heatmap_colormap is None:
sns.heatmap(corr, annot = True, fmt = '.2f', center = heatmap_center, square = True)
else:
sns.heatmap(corr, annot = True, fmt = '.2f', cmap = heatmap_colormap, center = heatmap_center, square = True)
plt.pause(0.1)
#ヒストグラムと散布図
if plot_pairplot:
print("")
print("Correlation pair polot")
sns.pairplot(df, height = 0.8)
plt.pause(0.1)
####################################################
# index - input/predict
####################################################
print("")
print("Plot index - input/prediction")
plt.rcParams['font.size'] = fontsize
fig, axis = plt.subplots(1, 1, figsize = figsize)
train_input_data = axis.scatter(index_train, y_train, label = 'train(input)', marker = 'o', c = 'black')
train_predict_data = axis.scatter(index_train, y_cal_train, label = 'train(predict)', marker = 'x', c = 'black')
test_input_data = axis.scatter(index_test, y_test, label = 'test(input)', marker = 'o', c = 'red')
test_predict_data = axis.scatter(index_test, y_cal_test, label = 'test(predict)', marker = 'x', c = 'red')
# train_input_data = axis.plot(index_train, y_train, label = 'train(input)', linestyle = '',
# marker = 'o', markeredgecolor = 'black', markerfacecolor = 'black', markersize = 5.0)
# train_predict_data = axis.plot(index_train, y_cal_train, label = 'train(predict)', linestyle = '',
# marker = 'x', markeredgecolor = 'black', markerfacecolor = 'black', markersize = 5.0)
# test_input_data = axis.plot(index_test, y_test, label = 'test(input)', linestyle = '',
# marker = 'o', markeredgecolor = 'red', markerfacecolor = 'red', markersize = 5.0)
# test_predict_data = axis.plot(index_test, y_cal_test, label = 'test(predict)', linestyle = '',
# marker = 'x', markeredgecolor = 'red', markerfacecolor = 'red', markersize = 5.0)
x_train_list = x_train.to_numpy().T
x_test_list = x_test.to_numpy().T
index_train_list = index_train.tolist()
index_test_list = index_test.tolist()
y_train_list = y_train.tolist()
y_test_list = y_test.tolist()
y_cal_train_list = y_cal_train.tolist()
y_cal_test_list = y_cal_test.tolist()
plot_event.add_data({"label": "training input", "plot_type": "scatter", "axis": axis, "data": train_input_data,
"x": index_train_list, 'y': y_train_list,
"xlist": [index_train_list, *x_train_list], "xlabels": ["index", *x_labels]})
plot_event.add_data({"label": "training predict", "plot_type": "scatter", "axis": axis, "data": train_predict_data,
"x": index_train_list, 'y': y_cal_train_list,
"xlist": [index_train_list, *x_train_list], "xlabels": ["index", *x_labels]})
plot_event.add_data({"label": "test input", "plot_type": "scatter", "axis": axis, "data": test_input_data,
"x": index_test_list, 'y': y_test_list,
"xlist": [index_test_list, *x_test_list], "xlabels": ["index", *x_labels]})
plot_event.add_data({"label": "test predict", "plot_type": "scatter", "axis": axis, "data": test_predict_data,
"x": index_test_list, 'y': y_cal_test_list,
"xlist": [index_test_list, *x_test_list], "xlabels": ["index", *x_labels]})
plot_event.register_event(fig)
if n_predict > 0:
# idx0 = max([max(index_train), max(index_test)])
# index_predict = range(idx0 + 1, idx0 + 1 + n_predict)
axis.scatter(predict_data.index, y_cal_predict, label = 'predict', marker = 's', c = 'blue')
ylim = axis.get_ylim()
for i in index_train:
axis.plot([i, i], ylim, linestyle = 'dashed', color = 'gray', linewidth = 0.5)
for i in index_test:
axis.plot([i, i], ylim, linestyle = 'dashed', color = 'pink', linewidth = 0.5)
if n_predict > 0:
for i in predict_data.index:
axis.plot([i, i], ylim, linestyle = 'dashed', color = 'cyan', linewidth = 0.5)
axis.set_xlabel('index', fontsize = fontsize)
axis.set_ylabel('predict', fontsize = fontsize)
axis.legend()
plt.pause(0.1)
####################################################
# input - prediction
####################################################
print("")
print("Plot input - prediction")
plt.rcParams['font.size'] = fontsize
fig, axis = plt.subplots(1, 1, figsize = figsize)
train_scatter_data = axis.scatter(y_train, y_cal_train, label = 'train')
test_scatter_data = axis.scatter(y_test, y_cal_test, label = 'test')
# train_scatter_data = axis.plot(y_train, y_cal_train, label = 'train', linestyle = '',
# marker = 'o', markeredgecolor = 'blue', markerfacecolor = 'blue', markersize = 5.0)
# test_scatter_data = axis.plot(y_test, y_cal_test, label = 'test', linestyle = '',
# marker = 'o', markeredgecolor = 'red', markerfacecolor = 'red', markersize = 5.0)
axis.plot([ymin, ymax], [ymin, ymax], linestyle = 'dashed', color = 'red', linewidth = 0.5)
axis.set_xlabel('input', fontsize = fontsize)
axis.set_ylabel('predict', fontsize = fontsize)
axis.legend()
plot_event.add_data({"label": "train", "plot_type": "scatter", "axis": axis, "data": train_scatter_data,
"x": y_train_list, 'y': y_cal_train_list,
"xlist": [index_train_list, *x_train_list], "xlabels": ["index", *x_labels]})
plot_event.add_data({"label": "test", "plot_type": "scatter", "axis": axis, "data": test_scatter_data,
"x": y_test_list, 'y': y_cal_test_list,
"xlist": [index_test_list, *x_test_list], "xlabels": ["index", *x_labels]})
plot_event.register_event(fig)
plt.pause(0.1)
####################################################
#第1列のlabelが '-x' の場合、variation plot (X-Y plot) を描画する
####################################################
if all.labels[0] == '-x':
print("")
plot_label = all.labels[0]
print(f"Plot x-y for x={plot_label}")
fig, axis = plt.subplots(1, 1, figsize = figsize)
axis.scatter(all.df[plot_label], y)
train_y_data = axis.scatter(df_train[plot_label], y_cal_train, s = 3.0)
test_y_data = axis.scatter(df_test[plot_label], y_cal_test, s = 3.0)
plot_event.add_data({"label": "train", "plot_type": "2D", "axis": axis, "data": train_y_data})
plot_event.add_data({"label": "test", "plot_type": "2D", "axis": axis, "data": test_y_data})
plot_event.register_event(fig)
plt.pause(0.1)
####################################################
# 各記述子と目的関数のプロット
####################################################
if plot_variation:
print("")
print("Plot variasns of objective function vs each descriptor")
ncol = int(sqrt(ndescriptors) + 1)
nrow = int(ndescriptors / ncol + 1.0001)
nmesh = 101
print(" ndescriptors=", ndescriptors)
print(" ncol, nrow=", ncol, nrow)
# zero_list = np.zeros(nmesh, dtype = float)
plt.rcParams['font.size'] = fontsize_s
fig, ax = plt.subplots(nrow, ncol, figsize = figsize)
for i in range(ndescriptors):
ix = int(i / ncol)
iy = i % ncol
if nrow == 1:
axis = ax[ix]
else:
axis = ax[ix, iy]
x_label = x_labels[i]
x_list = x[x_label]
x0 = min(all.df[x_label])
x1 = max(all.df[x_label])
xstep = (x1 - x0) / (nmesh - 1)
x_sim_list = [x0 + i * xstep for i in range(nmesh)]
# make descriptor
avg = scaler.mean_[i]
std = scaler.scale_[i]
y_sim = []
for idata in range(nmesh):
x_std = np.zeros(ndescriptors, dtype = float)
# 他の記述子の値を0にする => 標準化を行う
# x_std[i] = x_sim_list[idata]
# x_std = scaler.transform(pd.DataFrame([x_std], columns = x_labels))
# 他の記述子の値を平均値にする (標準化した値を使うと、他の記述子の値は0にできる)
x_std[i] = (x_sim_list[idata] - avg) / std
y_sim.append(model.predict([x_std])[0])
axis.scatter(x_train[x_label], y_train, s = 3.0)
axis.scatter(x_test[x_label], y_test, s = 3.0)
axis.plot(x_sim_list, y_sim, linestyle = '-', color = 'black', linewidth = 0.5)
axis.set_xlabel(x_label, fontsize = fontsize_s)
axis.set_ylabel(objectives.labels0[0], fontsize = fontsize_s)
plt.tight_layout()
plt.pause(0.1)
print("")
print("Press ENTER to terminate")
input()
if __name__ == "__main__":
main()