本ノートブックでは、異種混合学習の性質と特長を活かすためのsklearn-fabの使用方法を紹介します。
異種混合学習では、作成されるモデルが内部生成のランダム値に依存するため、
モデル作成を複数回実行し、最良なモデルを選択することがよくあります。
また、異種混合学習の大きな特長の一つとして、モデルの解釈性の高さが挙げられます。
そのため、最良なモデルの選択には、評価指標以外にモデルの門木や予測式の内容なども重要となります。
それらの性質と特長を踏まえた使用方法として、以下の3点について説明します。
複数のパラメーターでランダムリスタートし、複数モデルの作成を実施する
2. 複数モデルの作成をご覧ください
解釈性を考慮した複数モデルの評価・比較を実施する
3. 複数モデルの評価をご覧ください
可視化した門木を、より使いやすく加工する
4. 可視化した門木の加工をご覧ください
まず、学習およびテストに使用するデータを確認します。
本ノートブックでは、ワインの品種分類を示すデータを使用します。
データの詳細については、以下をご覧ください(本ハンズオンでは、説明変数が標準化済みのデータを使用します)。
Wine recognition dataset
import pandas as pd
data = pd.read_csv('./data/train_data.csv')
data.head()
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X = pd.DataFrame(scaler.fit_transform(data.iloc[:, 1:]), columns=data.iloc[:, 1:].columns.values)
y = data.iloc[:, 0]
この章では、複数のパラメーターでランダムリスタートし、複数モデルの作成を行います。
estimatorに与えるパラメーターとして、以下の組み合わせを試します。
from sklearn.model_selection import ParameterGrid
estimator_param_grid = {'random_seed': [0, 1], 'tree_depth': [4, 5],
'shrink_threshold': ['1.0%', '2.0%']}
estimator_params = list(ParameterGrid(estimator_param_grid))
estimator_params
上記のパラメーターに加え、より多くのモデルを作成して評価するために、
学習およびテストに使用するデータを、ホールドアウトによって2通りに分割します。
データを学習用、テスト用に分割するため、scikit-learnのKFoldを使用します。
from sklearn.model_selection import KFold
kf = KFold(n_splits=2, shuffle=True, random_state=1)
KFoldによりデータを分割しつつ、estimatorに与えるパラメーターを複数変化させて学習を実行します。
評価指標として、ワインの品種を正しく分類できたことを示す、正解率(accuracy)を採用します。
estimatorは、多値分類を実行するために「SklearnFABBernGateSoftmaxClassifier」を使用します。
※scikit-learnには、複数モデルを作成して評価するGridSearchCVという機能がありますが、
ベストモデル(評価指標が一番高いモデル)のみしか保存されないため、cross_validate()関数を使用します。
from sklearn.model_selection import cross_validate
from sklearn_fab import SklearnFABBernGateSoftmaxClassifier
estimator_score_dict = {}
for i, param in enumerate(estimator_params):
cl = SklearnFABBernGateSoftmaxClassifier(**param)
cv_results = cross_validate(cl, X, y, cv=kf, return_estimator=True)
for j in range(kf.get_n_splits()):
result_as_dict = {'estimator': cv_results['estimator'][j],
'accuracy': cv_results['test_score'][j]}
estimator_score_dict['fold{}_param{}_estimator'.format(j, i)] = result_as_dict
この章では、前章で作成した複数モデルの評価・比較を行います。
まずは、各モデルの正解率を確認します。
for k, v in estimator_score_dict.items():
print('{}: {}'.format(k, v['accuracy']))
これらの全てについて、門木や予測式を確認するのは大きな手間がかかってしまいます。
そこで、正解率が高い上位3つのモデルのみを選択します。
scores = sorted(estimator_score_dict.items(), key=lambda x: x[1]['accuracy'], reverse=True)
good_score_estimators = {name: score for _, (name, score) in zip(range(3), scores)}
good_score_estimators
選択されたモデルを比較するため、それぞれの門木と予測式情報を可視化し、門関数と予測式の詳細を確認します。
estimatorに与えたパラメーターについては、今回指定したものに絞って出力します。
import numpy as np
import matplotlib.pyplot as plt
from IPython.display import display, Image
from sklearn_fab.utils import export_gate_tree_dot
%matplotlib inline
# 門木を可視化する関数を定義
def visualize_gate_tree(estimator):
return display(Image(export_gate_tree_dot(estimator).create_png()))
# 予測式を可視化する関数を定義
def visualize_prediction_formulas(estimator):
columns = np.append(estimator.feature_names_, ['bias'])
multicl_indices = ['component #{}, class[{}]'.format(comp_id, cls_name)
for comp_id in estimator.comp_ids_
for cls_name in estimator.classes_]
prediction_formulas = [np.append(comp.weights[:, cls_idx], comp.bias[cls_idx])
for comp in estimator.comps_
for cls_idx in range(estimator.n_classes_)]
pf_df = pd.DataFrame(prediction_formulas, columns=columns, index=multicl_indices)
relevant_feature_indices = pf_df.sum(axis=0) != 0
pf_df = pf_df.T[relevant_feature_indices]
return pf_df.plot(kind='barh', figsize=(10, 5), stacked=True, xlim=[-15, 10])
# グラフのプロット時におけるWarningを非表示
np.seterr(invalid='ignore')
# 今回、指定したパラメーターのみ抽出
specified_params = estimator_param_grid.keys()
for i, (k, v) in enumerate(good_score_estimators.items()):
est_instance = v['estimator']
full_params = est_instance.get_params()
params_of_estimator = {key: full_params[key] for key in specified_params}
print(k + ': score = {}\n'.format(v['accuracy']) + str(params_of_estimator))
visualize_gate_tree(est_instance)
visualize_prediction_formulas(est_instance)
plt.show()
以下を判断基準として、fold0_param1_estimatorをベストモデルとして選択します。
best_estimator = estimator_score_dict['fold0_param1_estimator']['estimator']
best_estimator
上記に示したように、異種混合学習ではランダムリスタートして複数モデルを作成し、
精度のみならず門木と予測式が妥当で理解できるものかを確認して、モデル選択を行います。
sklearn-fabでも、それらの性質や特長を活かして、分析が実行できることがわかりました。
異種混合学習で学習したモデルの解釈性を更に高めるという目的で、可視化した門木を見やすく加工することがあります。
加工とは、具体的に以下のようなことを示します。
本バージョンでは、門木がdotフォーマットで出力されるため、簡単に編集することができます。
dot = export_gate_tree_dot(best_estimator)
Image(dot.create_png())
上記の図が、dotフォーマットでどのように表現されるかを確認します。
print(dot.to_string())
一例として、以下を実行します。
# labelの数値を逆標準化する関数を定義
def destandardize(estimator, node_id, scaler):
gate = estimator.tree_.get_gate_functions()[node_id]
array = np.zeros((len(estimator.feature_names_)))
array[gate.feature_id] = gate.threshold
destandardized_array = scaler.inverse_transform(array)
return destandardized_array[gate.feature_id]
# 門関数を逆標準化・日本語化にする
node_id = 0
gate_node, = dot.get_node(str(node_id))
destandardized_threshold = round(destandardize(best_estimator, node_id, scaler), 3)
label = 'アルコール濃度が{}%未満'.format(destandardized_threshold)
gate_node.set('label', label)
# 予測式の背景を青色にする
comp_node, = dot.get_node('24')
comp_node.set('fillcolor', '#4169e1')
Image(dot.create_png())
上記のように、門木の内容が変更されました。
可視化APIである「export_gate_tree_dot」は、.dot形式のファイルを出力する機能もあるため、
.dotファイルを直接編集することも可能です。