sklearn-fab

データ準備

まず、学習用のデータを確認します。

本ノートブックでは、中古車の販売価格を示すデータを使用します。

データの詳細については、以下をご覧ください。

Automobile Data Set

[1]:
import pandas as pd

train_data = pd.read_csv('../data/train_data.csv')
train_data.head()
[1]:
price symboling normalized-losses num-of-doors wheel-base length width height
0 12964 3 145.0 two 95.9 173.2 66.3 50.2
1 10198 0 89.0 four 97.0 173.5 65.4 53.0
2 11245 0 115.0 four 98.8 177.8 66.5 55.5
3 14399 0 108.0 four 100.4 184.6 66.5 56.1
4 25552 -1 93.0 four 110.0 190.9 70.3 56.5

上記のデータについて、以下の前処理を実施します。

  • num-of-doorsはカテゴリ変数のため、二値展開

  • num-of-doorsを除く変数は数値データであるため、標準化

二値展開

[2]:
def binary_expand(data):
    binary_data = pd.get_dummies(data.select_dtypes(include=[object]))
    numerical_data = data.select_dtypes(exclude=[object])
    data = numerical_data.join(binary_data)

    return data

train_data = binary_expand(train_data)
train_data.head()
[2]:
price symboling normalized-losses wheel-base length width height num-of-doors_four num-of-doors_two
0 12964 3 145.0 95.9 173.2 66.3 50.2 0 1
1 10198 0 89.0 97.0 173.5 65.4 53.0 1 0
2 11245 0 115.0 98.8 177.8 66.5 55.5 1 0
3 14399 0 108.0 100.4 184.6 66.5 56.1 1 0
4 25552 -1 93.0 110.0 190.9 70.3 56.5 1 0

標準化

[3]:
from sklearn.preprocessing import StandardScaler

std_list = ['price', 'symboling', 'normalized-losses', 'wheel-base', 'length', 'width', 'height']
scaler = StandardScaler()
train_data.loc[:, std_list] = pd.DataFrame(scaler.fit_transform(train_data.loc[:, std_list]),
                                           columns=train_data.loc[:, std_list].columns.values)
train_data.head()
[3]:
price symboling normalized-losses wheel-base length width height num-of-doors_four num-of-doors_two
0 0.284679 1.811656 0.618145 -0.436458 0.083628 0.350742 -1.512881 0 1
1 -0.203075 -0.625845 -0.924055 -0.221660 0.110246 -0.109542 -0.336858 1 0
2 -0.018448 -0.625845 -0.208033 0.129829 0.491759 0.453028 0.713163 1 0
3 0.537726 -0.625845 -0.400808 0.442264 1.095083 0.453028 0.965168 1 0
4 2.504436 -1.438345 -0.813897 2.316871 1.654045 2.396452 1.133171 1 0

次に、予測用データを読み込み、学習用データと同様に前処理を実施します。

[4]:
predict_data = pd.read_csv('../data/predict_data.csv')
predict_data = binary_expand(predict_data)
predict_data.loc[:, std_list] = pd.DataFrame(scaler.transform(predict_data.loc[:, std_list]),
                                             columns=predict_data.loc[:, std_list].columns.values)
predict_data.head()
[4]:
price symboling normalized-losses wheel-base length width height num-of-doors_four num-of-doors_two
0 -0.883744 0.186655 -0.979133 -0.475513 -1.202871 -1.030111 0.293154 0 1
1 1.199174 1.811656 0.755842 0.188411 1.272531 0.453028 0.965168 0 1
2 1.114355 0.999156 0.315213 0.051721 0.349801 -0.007257 -0.336858 0 1
3 0.035159 0.999156 0.315213 0.051721 0.349801 -0.007257 -0.756866 0 1
4 3.685556 -0.625845 0.618145 2.902686 2.425944 2.038453 -0.420860 1 0

学習用および予測用の説明変数をそれぞれX_train, X_predict、目的変数をそれぞれy_train, y_predictとして定義しておきます。

[5]:
X_train = train_data.iloc[:, 1:]
y_train = train_data.iloc[:, 0]
X_predict = predict_data.iloc[:, 1:]
y_predict = predict_data.iloc[:, 0]

分析手順の設計

目的変数priceは連続値であるため、回帰用のestimatorである「SklearnFABBernGateLinearRegressor」を選択します。

学習を行う際に、以下のパラメーターを指定します。

random_seed

  • estimatorで使用される乱数シードです。

tree_depth

  • 門木の深さを設定するパラメーターです。

shrink_threshold

  • 門木の枝刈りの閾値を設定するパラメーターです。

random_seed, tree_depth, shrink_thresholdの詳細は、「sklearn-fab Reference v1.1.0」をご覧ください。

[6]:
from sklearn_fab import SklearnFABBernGateLinearRegressor

random_seed = 0
tree_depth = 3
shrink_threshold = 2.0

estimatorインスタンスを作成します。

[7]:
estimator = SklearnFABBernGateLinearRegressor(random_seed=random_seed,
                                              tree_depth=tree_depth,
                                              shrink_threshold=shrink_threshold)

学習、予測

学習を実行します。

[8]:
estimator.fit(X_train, y_train)
[8]:
SklearnFABBernGateLinearRegressor(base_model_dict=None,
                                  comp_backward_step=False,
                                  comp_bias_max_scale=0.75,
                                  comp_bias_min_scale=0.25,
                                  comp_foba_skip='power_of_two',
                                  comp_foba_skip_max_interval=25,
                                  comp_l2_regularize=0.0, comp_opt_mode='opt',
                                  comp_two_stage_opt=False,
                                  comp_variance_max_scale=0.25,
                                  comp_variance_min_scale=0.1,
                                  comp_weights_max_scale=0.5,
                                  comp_we...
                                  gate_opt_mode='opt',
                                  max_comp_foba_iterations=100,
                                  max_comp_relevant_features=100,
                                  max_fab_iterations=100,
                                  num_acceleration_steps=0, num_threads_comps=1,
                                  num_threads_gate_features=1,
                                  num_threads_gates=1, projection_estep=False,
                                  random_seed=0, repeat_until_convergence=False,
                                  shrink_threshold=2.0, start_from_mstep=False,
                                  tree_depth=3,
                                  with_comp_scaled_l0_regularize=True)

予測を実行します。

[9]:
predict_value = estimator.predict(X_predict)

モデルバリデーション

予測精度の確認

作成したモデルを評価するため、予測精度を確認します。

評価指標として、RMSEを選定します。

[10]:
from sklearn.metrics import mean_squared_error

test_rmse = mean_squared_error(y_predict, predict_value, squared=False)
test_rmse
[10]:
0.6509250433352727

門木の可視化

モデルがもつ門木を可視化します。

[11]:
from IPython.display import display, Image
from sklearn_fab.utils import export_gate_tree_dot

dot = export_gate_tree_dot(estimator, X=X_train)
display(Image(dot.create_png()))
../../_images/section_3_sklearn_fab_sklearn_fab_29_0.png

予測式の可視化

モデルがもつ予測式情報にアクセスし、可視化します。

[12]:
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

# 可視化のために、DataFrame形式で予測式を表現
columns = np.append(estimator.feature_names_, ['bias', 'variance'])
prediction_formulas = [np.append(comp.weights, [comp.bias, comp.variance])
                       for comp in estimator.comps_]
pf_df = pd.DataFrame(prediction_formulas, columns=columns,
                     index=['component #' + str(i) for i in estimator.comp_ids_])

# 係数が0ではない説明変数のみを抽出し、表示
relevant_feature_indices = pf_df.sum(axis=0) != 0
pf_df = pf_df.T[relevant_feature_indices]
pf_df.plot(kind='barh', figsize=(8, 4), stacked=True)
plt.show()
../../_images/section_3_sklearn_fab_sklearn_fab_32_0.png