モデルの精度向上と検証方法¶
目次¶
1. はじめに¶
具体的な達成目標は、以下の通りです。
「テンプレート構文を用いたSPDとSRCの作成ができる」
「パラメーターチューニングとランダムリスタートを理解し、テンプレート構文を活用してSPDとSRCの実装ができる」
「モデルの検証方法を理解した上でモデルの検証を実行し、検証結果として予測精度を確認できる」
2. データの準備¶
本節では、以下のデータ準備の手順について示します。学習・予測の実行と結果確認の2. データの準備と同様ですが、本章ではテンプレート構文を用いるので、CSVとASDはファイル出力は行いません。
分析対象データに _sid (sample ID) を追加
ASD(属性スキーマ)の作成
分析対象データから学習用と予測用を作成
本章では、分析対象データをPandas Dataframeのまま扱うため、カテゴリ型の属性の型はnp.object
またはnp.bool
でなければなりません。 そのため、数値型のカテゴリを持つ属性はnp.object
に変換する必要があり、read_csv()関数を実行する際に、origin
の型をnp.object
として読み込みます。
以下のコードで、自動車の燃料消費量予測の分析対象データを示します。
データは、UCIのオープンデータである Auto MPG Data Set (https://archive.ics.uci.edu/ml/datasets/auto+mpg) を属性名car_name
を削除して、利用しています。
[1]:
import pandas as pd
import numpy as np
input_data = pd.read_csv('./data/auto-mpg.csv', na_values='?', dtype={'origin': np.object})
input_data.dropna(inplace=True)
input_data.insert(0, '_sid', list(range(input_data.shape[0])))
input_data.head()
[1]:
_sid | mpg | cylinders | displacement | horsepower | weight | acceleration | model_year | origin | |
---|---|---|---|---|---|---|---|---|---|
0 | 0 | 18.0 | 8 | 307.0 | 130 | 3504 | 12.0 | 70 | 1 |
1 | 1 | 15.0 | 8 | 350.0 | 165 | 3693 | 11.5 | 70 | 1 |
2 | 2 | 18.0 | 8 | 318.0 | 150 | 3436 | 11.0 | 70 | 1 |
3 | 3 | 16.0 | 8 | 304.0 | 150 | 3433 | 12.0 | 70 | 1 |
4 | 4 | 17.0 | 8 | 302.0 | 140 | 3449 | 10.5 | 70 | 1 |
上記の分析対象データからASDを作成します。
学習・予測の実行と結果確認の2. データの準備で示していますが、ASDのweightを正しいデータ型に修正します。 originは、np.object
としてread_csv()関数で読み込んだのでカテゴリ型として認識されています。
[2]:
from sampotools.api import gen_asd_from_pandas_df
import pandas as pd
import yaml
# ASD作成
asd = gen_asd_from_pandas_df(input_data)
# 修正
asd['weight'] = {'scale': 'REAL'}
# 確認
pd.DataFrame(asd).T[['scale', 'domain']]
[2]:
scale | domain | |
---|---|---|
_sid | INTEGER | NaN |
mpg | REAL | NaN |
cylinders | INTEGER | NaN |
displacement | REAL | NaN |
horsepower | INTEGER | NaN |
weight | REAL | NaN |
acceleration | REAL | NaN |
model_year | INTEGER | NaN |
origin | NOMINAL | [1, 3, 2] |
分析対象データを学習用と予測用に分けます。
以下のコードを実行し、全体の90%にあたる件数を learn_data
、残り10%の件数を predict_data
としてPandas DataFrameに格納します。
[3]:
n_all = len(input_data)
n_predict = n_all // 10
n_learn = n_all - n_predict
learn_data = input_data.iloc[0:n_learn,:]
predict_data = input_data.iloc[n_learn:n_all,:]
本節の具体的な説明は、学習・予測の実行と結果確認の2. データの準備 を参照してください。
3. より精度の高いモデルの作成方法¶
より精度の高いモデルを作成するため、以下について説明します。 - テンプレート構文 - パラメーターサーチ - ランダムリスタート
3.1. テンプレート構文を用いたSPDとSRCの定義¶
本節では、テンプレート構文を用いたSPDとSRCの定義について示します。
テンプレート構文は、{{ <テンプレート変数名> }}
というプレースホルダーを用いることで、SPDまたはSRCのプレースホルダーに動的にPythonコード上の変数の値を入力することが可能です。
テンプレート構文は、次節以降で利用されます。
テンプレート構文を用いるSPDの記述例を以下で示します。 記述例では、tree_depth
の値にテンプレート構文を適用しています。
[4]:
spd_content_templ = '''
dl -> std -> rg
-> bexp -> rg
---
components:
dl:
component: DataLoader
std:
component: StandardizeFDComponent
features: scale == 'real' or scale == 'integer'
bexp:
component: BinaryExpandFDComponent
features: scale == 'nominal'
rg:
component: FABHMEBernGateLinearRgComponent
features: name != 'mpg'
target: name == 'mpg'
standardize_target: True
tree_depth: {{ tree_depth }}
global_settings:
keep_attributes:
- mpg
feature_exclude:
- mpg
'''
テンプレート構文は、gen_spd()関数で生成する時にプレースホルダーに値が入力されます。値はテンプレート変数名をキー値とした辞書で与えます。
[5]:
from sampo.api import gen_spd
spd_param = {'tree_depth': 3}
spd = gen_spd(template=spd_content_templ, params=spd_param)
上記で生成したSPDを出力し、{{ tree_depth }}
の値が入力されていることを確認します。
[6]:
print(spd) #確認
dl -> std -> rg
dl -> bexp -> rg
---
components:
dl:
component: DataLoader
bexp:
component: BinaryExpandFDComponent
features: scale == 'nominal'
std:
component: StandardizeFDComponent
features: scale == 'real' or scale == 'integer'
rg:
component: FABHMEBernGateLinearRgComponent
features: name != 'mpg'
standardize_target: true
target: name == 'mpg'
tree_depth: 3
global_settings:
keep_attributes:
- mpg
feature_exclude:
- mpg
以下に、テンプレート構文を用いるSRCの記述例を示します。 テンプレート構文を学習用と予測用でプロセス名や分析対象データ、ASDの格納先の指定に適用しています。
テンプレート構文を用いることで、Pandas DataFrameのようなPythonオブジェクトもSRCに指定することができます。
[7]:
# 学習用SRC
learn_src_templ = '''
fabhmerg_learn_{{ run_times }}:
type: learn
data_sources:
dl:
df: {{ learn_data }}
attr_schema: {{ asd }}
'''
# 予測用SRC
predict_src_templ = '''
fabhmerg_predict_{{ run_times }}:
type: predict
data_sources:
dl:
df: {{ predict_data }}
attr_schema: {{ asd }}
model_process: fabhmerg_learn_{{ run_times }}
'''
SPDと同様に、SRCをgen_src()関数で生成する時に、src_param
も渡すことでプレースホルダーに値が入力されます。
[8]:
from sampo.api import gen_src
src_param = {'run_times': 0 ,'learn_data':learn_data ,'predict_data':predict_data, 'asd': asd}
learn_src = gen_src(template=learn_src_templ, params=src_param)
predict_src = gen_src(template=predict_src_templ, params=src_param)
値を確認するため、gen_src()関数で生成したSRCをそれぞれ出力します。
[9]:
# 確認
print(learn_src)
fabhmerg_learn_0:
type: learn
data_sources:
dl:
df: _sid mpg cylinders ... acceleration model_year origin
0 0 18.0 8 ... 12.0 70 1
1 1 15.0 8 ... 11.5 70 1
2 2 18.0 8 ... 11.0 70 1
.. ... ... ... ... ... ... ...
350 350 33.7 4 ... 14.4 81 3
351 351 32.4 4 ... 16.8 81 3
352 352 32.9 4 ... 14.8 81 3
[353 rows x 9 columns]
attr_schema:
[('_sid', {'scale': 'INTEGER'}),
('mpg', {'scale': 'REAL'}),
('cylinders', {'scale': 'INTEGER'}),
('displacement', {'scale': 'REAL'}),
('horsepower', {'scale': 'INTEGER'}),
...]
[Displaying 5 out of 9 attributes.]
[10]:
print(predict_src)
fabhmerg_predict_0:
type: predict
data_sources:
dl:
df: _sid mpg cylinders ... acceleration model_year origin
353 353 31.6 4 ... 18.3 81 3
354 354 28.1 4 ... 20.4 81 2
355 355 30.7 6 ... 19.6 81 2
.. ... ... ... ... ... ... ...
389 389 32.0 4 ... 11.6 82 1
390 390 28.0 4 ... 18.6 82 1
391 391 31.0 4 ... 19.4 82 1
[39 rows x 9 columns]
attr_schema:
[('_sid', {'scale': 'INTEGER'}),
('mpg', {'scale': 'REAL'}),
('cylinders', {'scale': 'INTEGER'}),
('displacement', {'scale': 'REAL'}),
('horsepower', {'scale': 'INTEGER'}),
...]
[Displaying 5 out of 9 attributes.]
model_process: fabhmerg_learn_0
3.2. パラメーターチューニングの実行方法¶
tree_depth
とstandardize_target
にテンプレート構文を適用し、グリッドサーチを行います。[11]:
spd_content_para_tuning = '''
dl -> std -> rg
-> bexp -> rg
---
components:
dl:
component: DataLoader
std:
component: StandardizeFDComponent
features: scale == 'real' or scale == 'integer'
bexp:
component: BinaryExpandFDComponent
features: scale == 'nominal'
rg:
component: FABHMEBernGateLinearRgComponent
features: name != 'mpg'
target: name == 'mpg'
standardize_target: {{ standardize_target }}
tree_depth: {{ tree_depth }}
global_settings:
keep_attributes:
- mpg
feature_exclude:
- mpg
'''
下記では、ハイパーパラメーターの各組み合わせをリストで持つspd_params
が作成されます。
[12]:
from sklearn.model_selection import ParameterGrid
spd_param_combination = {
'standardize_target': [True, False],
'tree_depth': [3, 4, 5]
}
spd_params = list(ParameterGrid(spd_param_combination))
SRCの記述例を示します。
[13]:
# 学習用SRC
learn_src_para_tuning = '''
fabhmerg_learn_{{ parameter_pattern }}:
type: learn
data_sources:
dl:
df: {{ learn_data }}
attr_schema: {{ input_asd }}
'''
# 予測用SRC
predict_src_para_tuning = '''
fabhmerg_predict_{{ parameter_pattern }}:
type: predict
data_sources:
dl:
df: {{ predict_data }}
attr_schema: {{ input_asd }}
model_process: fabhmerg_learn_{{ parameter_pattern }}
'''
上記で作成したSPD、spd_params
、SRCを用いて、グリッドサーチを実行します。
[14]:
import logging
from sampo.api import sampo_logging
from sampo.api import gen_spd, gen_src
from sampotools.api import gen_asd_from_pandas_df
sampo_logging.configure(logging.INFO, filename='./fabhmerg_para.log')
process_list = [] # 並列実行するプロセスを保存するリスト
for grid_id, spd_param in enumerate(spd_params):
spd = gen_spd(template=spd_content_para_tuning, params=spd_param)
src_param = {'parameter_pattern': grid_id, 'learn_data': learn_data, 'predict_data': predict_data, 'input_asd': asd}
learn_src = gen_src(template=learn_src_para_tuning, params=src_param)
predict_src = gen_src(template=predict_src_para_tuning, params=src_param)
process_list.append((learn_src, spd)) # 学習用の分析プロセスの追加
process_list.append((predict_src, None)) # 予測用の分析プロセスの追加
[15]:
from sampo.api import process_runner, process_store
pstore_url = './parallel_pstore_tuning'
process_store.create(pstore_url)
#グリッドサーチ実行
process_runner.session_run(process_list, pstore_url=pstore_url, max_workers=3)
[15]:
[('fabhmerg_learn_0.f495addd-ab93-4952-aff5-40a6327812d9', None),
('fabhmerg_learn_2.28b9d7d4-3310-4708-aa7c-76fe9f126979', None),
('fabhmerg_learn_1.5171862b-1406-4df7-a542-e8c8325f34c1', None),
('fabhmerg_learn_3.86f3c015-dc4d-4306-9bf3-7fa3dac69680', None),
('fabhmerg_learn_4.e79f0543-d244-4858-b22a-81c4b66826ed', None),
('fabhmerg_predict_0.a1db32c2-c9b0-4591-a5be-d33d7d90d7d7', None),
('fabhmerg_learn_5.f66267e2-5117-4adc-ad7d-2096ec4d5850', None),
('fabhmerg_predict_1.6decfd04-c14f-4982-bb02-e607dda16f6b', None),
('fabhmerg_predict_3.257d52fd-7069-4b35-a5f2-918bd618d269', None),
('fabhmerg_predict_2.dd03f131-4b9e-4aca-937a-888355b7fa0c', None),
('fabhmerg_predict_4.03063d1d-d030-41f3-8c1d-aa6d4d299895', None),
('fabhmerg_predict_5.362e7401-9426-4ceb-95ee-0601950cb419', None)]
プロセスストアから実行済プロセスを開き、算出された予測精度を表示します。
[16]:
import re
import pandas as pd
from sampo.api import process_store
result = []
predict_proc_names = [src.name for src, _ in process_list if re.match('fabhmerg_predict.*', src.name)]
for predict_proc_name in predict_proc_names:
row = {}
with process_store.open_process(pstore_url, predict_proc_name) as prl:
evaluation = prl.load_comp_output_evaluation('rg')
row['process_name'] = predict_proc_name
row['rmse'] = evaluation['root_mean_squared_error'][0]
result.append(row)
pd.DataFrame(result).sort_values(by='rmse')
[16]:
process_name | rmse | |
---|---|---|
1 | fabhmerg_predict_1 | 3.682181 |
3 | fabhmerg_predict_3 | 3.804716 |
5 | fabhmerg_predict_5 | 3.860132 |
0 | fabhmerg_predict_0 | 3.916196 |
2 | fabhmerg_predict_2 | 4.140845 |
4 | fabhmerg_predict_4 | 4.152079 |
上記の表から、rmseの値が低いプロセス名の番号から、パラメーターの組み合わせを確認します。
[17]:
best_model = result[0]['process_name']
num_best_model = int(best_model[-1:])
spd_params[num_best_model]
[17]:
{'standardize_target': True, 'tree_depth': 3}
3.3. ランダムリスタートの目的と設計・実行方法¶
SAMPO/FABの異種混合学習コンポーネント(FABHMEBernGateLinearRgComponent
)で作成するモデルは、ランダムに決定される初期状態から学習を開始します。 これは同じ分析対象データとハイパーパラメーターで学習を実行しても、実行するたびに異なるモデルが作成されることを示します。
そのため、より精度の高いモデルを選択するために分析プロセスを複数回実行することをランダムリスタートと言います。
ランダムリスタートでは、SRCのプロセス名が一意になるようにテンプレート構文を適用します。
下記のSPDとSRCを用いて、ランダムリスタートの実行例を示します。
[18]:
spd_content_random = '''
dl -> std -> rg
-> bexp -> rg
---
components:
dl:
component: DataLoader
std:
component: StandardizeFDComponent
features: scale == 'real' or scale == 'integer'
bexp:
component: BinaryExpandFDComponent
features: scale == 'nominal'
rg:
component: FABHMEBernGateLinearRgComponent
features: name != 'mpg'
target: name == 'mpg'
standardize_target: True
tree_depth: 3
global_settings:
keep_attributes:
- mpg
feature_exclude:
- mpg
'''
[19]:
# 学習用SRC
learn_src_random = '''
fabhmerg_learn_{{ run_times }}:
type: learn
data_sources:
dl:
df: {{ learn_data }}
attr_schema: {{ asd }}
'''
# 予測用SRC
predict_src_random = '''
fabhmerg_predict_{{ run_times }}:
type: predict
data_sources:
dl:
df: {{ predict_data }}
attr_schema: {{ asd }}
model_process: fabhmerg_learn_{{ run_times }}
'''
SAMPO/FABが読み込めるように、SPDをgen_spd()関数で、学習用SRCをgen_src()関数で生成します。
[20]:
import logging
from sampo.api import sampo_logging
from sampo.api import gen_spd, gen_src
from sampotools.api import gen_asd_from_pandas_df
sampo_logging.configure(logging.INFO, filename='./fabhmerg_randomrestart.log')
process_list = [] # 並列実行するプロセスを保存するリスト
num_random_restarts = 5
for idx in range(num_random_restarts):
src_param = {'run_times': idx , 'learn_data': learn_data, 'predict_data': predict_data, 'asd': asd}
spd = gen_spd(template=spd_content_random)
learn_src = gen_src(template=learn_src_random, params=src_param)
predict_src = gen_src(template=predict_src_random, params=src_param)
process_list.append((learn_src, spd)) # 学習用の分析プロセスの追加
process_list.append((predict_src, None)) # 予測用の分析プロセスの追加
ランダムリスタートを実行します。
[21]:
from sampo.api import process_runner, process_store
pstore_url = './parallel_pstore'
process_store.create(pstore_url)
#ランダムリスタート実行
process_runner.session_run(process_list, pstore_url=pstore_url, max_workers=3)
[21]:
[('fabhmerg_learn_1.0555f2e3-ced0-4ed6-a5f9-0fd87a0d977a', None),
('fabhmerg_learn_0.c061ee34-5bfe-4cf4-a020-4abf274ef9f1', None),
('fabhmerg_learn_2.13a26f3b-bc8a-4bd3-86f9-2eac0384c398', None),
('fabhmerg_learn_3.eb000f49-c8f4-4197-a200-cb40ad2da087', None),
('fabhmerg_learn_4.d219f3dc-c390-4e81-bead-36cd48ad5565', None),
('fabhmerg_predict_1.c2c6c0c2-9366-4db2-ba7e-c5072796b82f', None),
('fabhmerg_predict_0.ace6592c-6b99-434a-b029-e702d46ac270', None),
('fabhmerg_predict_3.ec6dcfc1-e402-4282-bcc2-d27ae10586a1', None),
('fabhmerg_predict_2.ce690cf7-0a84-4ee9-8e12-254887703da3', None),
('fabhmerg_predict_4.ffc42403-a93d-4254-8207-d293e1641f0a', None)]
[22]:
import re
import pandas as pd
from sampo.api import process_store
result = []
predict_proc_names = [src.name for src, _ in process_list if re.match('fabhmerg_predict.*', src.name)]
for predict_proc_name in predict_proc_names:
row = {}
with process_store.open_process(pstore_url, predict_proc_name) as prl:
evaluation = prl.load_comp_output_evaluation('rg')
row['process_name'] = predict_proc_name
row['rmse'] = evaluation['root_mean_squared_error'][0]
result.append(row)
pd.DataFrame(result).sort_values(by='rmse')
[22]:
process_name | rmse | |
---|---|---|
3 | fabhmerg_predict_3 | 3.632642 |
1 | fabhmerg_predict_1 | 3.726962 |
4 | fabhmerg_predict_4 | 3.798683 |
2 | fabhmerg_predict_2 | 3.818484 |
0 | fabhmerg_predict_0 | 4.227888 |
上記の結果から、作成したモデルの中から、RMSEが最小のモデルを選択することができます。
4. モデルの検証方法¶
本節では、複数存在するモデルの検証方法からSAMPO/FABでよく用いられる下記の例を示します。
ホールドアウト検証
交差検証
4.1. ホールドアウト検証¶
ホールドアウト検証は、学習用データでモデルを作成して検証用データでモデルの評価を行う検証方法です。
SPDは、3.2節のパラメーターチューニングの実行方法を流用します。
[23]:
spd_content_ho = '''
dl -> std -> rg
-> bexp -> rg
---
components:
dl:
component: DataLoader
std:
component: StandardizeFDComponent
features: scale == 'real' or scale == 'integer'
bexp:
component: BinaryExpandFDComponent
features: scale == 'nominal'
rg:
component: FABHMEBernGateLinearRgComponent
features: name != 'mpg'
target: name == 'mpg'
standardize_target: {{ standardize_target }}
tree_depth: {{ tree_depth }}
global_settings:
keep_attributes:
- mpg
feature_exclude:
- mpg
'''
SRCは、下記のテンプレート構文を用いた学習用と検証用を使用します。
[24]:
# 学習用SRC
learn_src_ho = '''
fabhmerg_learn_ho{{ run_times }}:
type: learn
data_sources:
dl:
df: {{ input_df }}
attr_schema: {{ asd }}
filters:
- k_split(3, 0, True)
'''
# 検証用SRC
predict_src_ho = '''
fabhmerg_predict_ho{{ run_times }}:
type: predict
data_sources:
dl:
df: {{ input_df }}
attr_schema: {{ asd }}
filters:
- k_split(3, 0, False)
model_process: fabhmerg_learn_ho{{ run_times }}
'''
分析対象データをSRCに記述されているk_split()関数で学習用と検証用に分割します。
k_split()関数は、以下の内容を引数にて指定します。 - 第一引数 : 分析対象データを分割する数 k - 第二引数 : 分割したデータのindex (0 から k-1まで) - 第三引数 : Trueの場合、第二引数で指定したデータ以外を返す
上記のSRCでは、分析対象データを3分割にし、1つ目を検証用、残りを学習用に使用する指定にしています。
k_split()関数の詳細については、Analytics Reference
のSRC (SAMPO Run Configuration) Specification
を参照してください。
[25]:
import logging
from sampo.api import sampo_logging
import pandas as pd
from sampo.api import gen_spd, gen_src
from sampotools.api import gen_asd_from_pandas_df
sampo_logging.configure(logging.INFO, filename='./fabhmerg_ho.log')
process_list = [] # 並列実行するプロセスを保存するリスト
num_random_restarts = 5
for n in range(num_random_restarts):
spd_param = {'tree_depth': 3 , 'standardize_target':True }
src_param = {'run_times': n , 'input_df': input_data , 'asd': asd}
spd = gen_spd(template=spd_content_ho, params=spd_param)
learn_src = gen_src(template=learn_src_ho, params=src_param)
predict_src = gen_src(template=predict_src_ho, params=src_param)
process_list.append((learn_src, spd)) # 学習用の分析プロセスの追加
process_list.append((predict_src, None)) # 予測用の分析プロセスの追加
[26]:
from sampo.api import process_runner, process_store
pstore_url = './parallel_pstore_hold_out'
process_store.create(pstore_url)
#ホールドアウト検証実行
process_runner.session_run(process_list, pstore_url=pstore_url, max_workers=3)
[26]:
[('fabhmerg_learn_ho0.dfd413c1-8d98-45d8-b47e-7bbd1bae63d4', None),
('fabhmerg_learn_ho2.949da768-90da-4eab-b98b-8433f79617aa', None),
('fabhmerg_learn_ho1.841cf70d-95f6-45a9-b7f2-7744bfa0a325', None),
('fabhmerg_predict_ho0.0bd40baa-a5d0-40c6-8e1d-878df3b50512', None),
('fabhmerg_predict_ho2.86d00f75-1c2b-46af-8c44-83cbb2c583c1', None),
('fabhmerg_learn_ho4.6f4da795-8a43-4fdf-855a-984c12e5a6d3', None),
('fabhmerg_learn_ho3.a7c1c0d6-c3c0-470a-939b-64d8b91cd681', None),
('fabhmerg_predict_ho4.bdf53cf5-3b9c-4a85-8eac-730ad73af60a', None),
('fabhmerg_predict_ho1.3cfe4864-e9cf-4c66-a139-d3150c253eae', None),
('fabhmerg_predict_ho3.e7052729-b760-4aad-9c17-bd3eba68e2ca', None)]
[27]:
import re
import pandas as pd
from sampo.api import process_store
result = []
predict_proc_names = [src.name for src, _ in process_list if re.match('fabhmerg_predict.*', src.name)]
for predict_proc_name in predict_proc_names:
row = {}
with process_store.open_process(pstore_url, predict_proc_name) as prl:
evaluation = prl.load_comp_output_evaluation('rg')
row['process_name'] = predict_proc_name
row['rmse'] = evaluation['root_mean_squared_error'][0]
result.append(row)
pd.DataFrame(result).sort_values(by='rmse')
[27]:
process_name | rmse | |
---|---|---|
2 | fabhmerg_predict_ho2 | 3.539923 |
3 | fabhmerg_predict_ho3 | 4.184492 |
1 | fabhmerg_predict_ho1 | 4.382446 |
4 | fabhmerg_predict_ho4 | 4.596399 |
0 | fabhmerg_predict_ho0 | 4.791177 |
上記から、ホールドアウト検証を行った検証結果として予測精度のRMSEが確認できます。
4.2. 交差検証¶
交差検証は、分析対象データを分割し、学習用と検証用の組み合わせを入れ替えながら実行する検証方法です。 ホールドアウト検証と比べて、1度の検証回数が多くなることで実行時間が長くなりますが、全パターンの評価結果の平均値をとるので信頼が高くなります。
交差検証にはいくつか種類があり、以下でK分割交差検証の実行例を示します。
[28]:
spd_content_cv = '''
dl -> std -> rg
-> bexp -> rg
---
components:
dl:
component: DataLoader
std:
component: StandardizeFDComponent
features: scale == 'real' or scale == 'integer'
bexp:
component: BinaryExpandFDComponent
features: scale == 'nominal'
rg:
component: FABHMEBernGateLinearRgComponent
features: name != 'mpg'
target: name == 'mpg'
standardize_target: {{ standardize_target }}
tree_depth: {{ tree_depth }}
global_settings:
keep_attributes:
- mpg
feature_exclude:
- mpg
'''
以下のSRCでは、プロセス名のrrがランダムリスタートの回数、splitが指定したデータのindexを示しています。
[29]:
# 学習用SRC
learn_src_cv = '''
fabhmerg_learn_rr{{ run_times }}_split{{ split_position }}:
type: learn
data_sources:
dl:
df: {{ input_df }}
attr_schema: {{ asd }}
filters:
- k_split({{ k_split }}, {{ split_position }}, True)
'''
# 検証用SRC
predict_src_cv = '''
fabhmerg_predict_rr{{ run_times }}_split{{ split_position }}:
type: predict
data_sources:
dl:
df: {{ input_df }}
attr_schema: {{ asd }}
filters:
- k_split({{ k_split }}, {{ split_position }}, False)
model_process: fabhmerg_learn_rr{{ run_times }}_split{{ split_position }}
'''
上記のSPDとSRCを用いて、3-分割交差検証をランダムリスタートで3回実行します。
[30]:
import logging
from sampo.api import sampo_logging
from sampo.api import gen_spd, gen_src
from sampotools.api import gen_asd_from_pandas_df
sampo_logging.configure(logging.INFO, filename='./fabhmerg_cv.log')
process_list = [] # 並列実行するプロセスを保存するリスト
num_random_restarts = 3
num_split = 3 #分割する数
# 交差検証実行
for rr in range(num_random_restarts):
for k in range(num_split):
spd_param = {'tree_depth': 3, 'standardize_target': True }
src_param = {'run_times': rr , 'input_df': input_data, 'k_split': num_split, 'split_position': k , 'asd': asd}
spd = gen_spd(template=spd_content_cv, params=spd_param)
learn_src = gen_src(template=learn_src_cv, params=src_param)
predict_src = gen_src(template=predict_src_cv, params=src_param)
process_list.append((learn_src, spd)) # 学習用の分析プロセスの追加
process_list.append((predict_src, None)) # 予測用の分析プロセスの追加
[31]:
from sampo.api import process_runner, process_store
pstore_url = './parallel_pstore_cv'
process_store.create(pstore_url)
process_runner.session_run(process_list, pstore_url=pstore_url, max_workers=3)
[31]:
[('fabhmerg_learn_rr0_split2.a6854723-bb24-42c0-a297-5ebfc1a3c9cd', None),
('fabhmerg_learn_rr0_split0.24e3c4b7-8989-49c8-895c-6e35618b788b', None),
('fabhmerg_learn_rr0_split1.7422ae74-82cd-490e-ba56-a632335ed504', None),
('fabhmerg_learn_rr1_split0.92eb3f1a-e732-476f-86fb-62bad71a84c6', None),
('fabhmerg_learn_rr1_split1.16dc4ff2-7b96-4846-94c7-e073bad03486', None),
('fabhmerg_learn_rr1_split2.e5d37eba-5510-4a7b-9c06-7d36feced671', None),
('fabhmerg_learn_rr2_split1.852c4344-5a58-4d37-8aa7-cb1263f5131b', None),
('fabhmerg_learn_rr2_split0.ae895fcd-7b09-4d7f-b89f-1bd6c258c223', None),
('fabhmerg_learn_rr2_split2.e465bcd3-d1f5-4cc3-94bc-06c26e445fa4', None),
('fabhmerg_predict_rr0_split2.eaf65065-8c8c-48e7-b610-0688d492045d', None),
('fabhmerg_predict_rr0_split0.606e8a9e-62df-4356-bc53-0728a5b64ca7', None),
('fabhmerg_predict_rr1_split0.d38f5a79-bc1a-4d3a-a76f-610d836ce545', None),
('fabhmerg_predict_rr1_split1.0719da35-12a7-4767-921e-8297f37f7a6e', None),
('fabhmerg_predict_rr0_split1.6f254508-14a6-48f9-b295-1a189f61c063', None),
('fabhmerg_predict_rr2_split1.3814e0b8-38a7-4db9-8544-6d7a18a29435', None),
('fabhmerg_predict_rr1_split2.356964d1-a644-429f-b82e-e7edfb3da1c0', None),
('fabhmerg_predict_rr2_split0.fb026f46-8192-4321-b1be-f3b54b26bf57', None),
('fabhmerg_predict_rr2_split2.c30218aa-ebdb-4cfa-94d2-a6067938a9ec', None)]
[32]:
import re
import pandas as pd
from sampo.api import process_store
result = []
predict_proc_names = [src.name for src, _ in process_list if re.match('fabhmerg_predict.*', src.name)]
for predict_proc_name in predict_proc_names:
row = {}
with process_store.open_process(pstore_url, predict_proc_name) as prl:
evaluation = prl.load_comp_output_evaluation('rg')
row['process_name'] = predict_proc_name
row['rmse'] = evaluation['root_mean_squared_error'][0]
result.append(row)
pd.DataFrame(result).sort_values('process_name')
[32]:
process_name | rmse | |
---|---|---|
0 | fabhmerg_predict_rr0_split0 | 4.532768 |
1 | fabhmerg_predict_rr0_split1 | 4.638185 |
2 | fabhmerg_predict_rr0_split2 | 5.321502 |
3 | fabhmerg_predict_rr1_split0 | 4.156640 |
4 | fabhmerg_predict_rr1_split1 | 2.355842 |
5 | fabhmerg_predict_rr1_split2 | 5.546513 |
6 | fabhmerg_predict_rr2_split0 | 3.592213 |
7 | fabhmerg_predict_rr2_split1 | 2.406080 |
8 | fabhmerg_predict_rr2_split2 | 5.186844 |
上記から交差検証を行った結果が確認できます。