Magicode logo
Magicode
0
14 min read

数行のコードで機械学習ができる PyCaret のチュートリアルを試してみた 回帰分析 その2

前回の記事に引き続き、 PyCaret のチュートリアルを試してみたいと思います。 今回は回帰分析の Regression Tutorial (REG102) - Level Intermediate に沿って試してみたいと思います。

回帰チュートリアル(REG101) - Level Beginnerの続きですので、こちらを実施前の方は前回の記事など参考に内容を確認ください。

日本語版もありましたので、こちらから引用しつつ実行していきたいと思います。
※ magicode で実行していきたかったですが、 from pycaret.regression import * の箇所でエラーが発生するようになり解決できなかったため、今回は colab での実行結果を upload したものになります。

PyCaret とは

PyCaret is an open-source, low-code machine learning library in Python that automates machine learning workflows.

https://pycaret.org/

と公式に記載あるように、わずかなコード量で実装できる Python の機械学習のライブラリです。

回帰分析のチュートリアル

このチュートリアルで学ぶこと

このチュートリアルでは、pycaret.regressionモジュールを使って、以下のことを学びます。

  • Normalization: データセットを正規化し、スケーリングする方法 Transformation: データを線形かつ近似的に正規化するための変換を適用する方法
  • Target Transformation: ターゲット変数に変換を適用する方法
  • Combine Rare Levels:* Bin Numeric Variables: 数値変数をビンに入れ、「sturges」ルールを使用して数値特徴をカテゴリーに変換する方法
  • Model Ensembling and Stacking:** Bagging、Boosting、Voting、Generalized Stackingなどのアンサンブル技術を使用して、モデルのパフォーマンスを向上させる方法。
  • Experiment Logging: MLFlowバックエンドを使ったPyCaretでの実験ログの取り方

この記事では MLFlow の部分は省略します。

PyCaret のインストール

!pip install pycaret==2.3.10 markupsafe==2.0.1 pyyaml==5.4.1 -qq

 |████████████████████████████████| 320 kB 8.8 MB/s  |████████████████████████████████| 636 kB 39.1 MB/s  |████████████████████████████████| 6.8 MB 47.7 MB/s  |████████████████████████████████| 1.3 MB 50.7 MB/s  |████████████████████████████████| 262 kB 58.3 MB/s  |████████████████████████████████| 120 kB 43.9 MB/s  |████████████████████████████████| 17.8 MB 441 kB/s  |████████████████████████████████| 88 kB 6.6 MB/s  |████████████████████████████████| 167 kB 34.5 MB/s  |████████████████████████████████| 2.0 MB 35.1 MB/s  |████████████████████████████████| 56 kB 4.1 MB/s  |████████████████████████████████| 1.7 MB 39.6 MB/s [?25h Installing build dependencies ... [?25l[?25hdone Getting requirements to build wheel ... [?25l[?25hdone Installing backend dependencies ... [?25l[?25hdone Preparing wheel metadata ... [?25l[?25hdone  |████████████████████████████████| 261 kB 47.4 MB/s  |████████████████████████████████| 303 kB 51.3 MB/s  |████████████████████████████████| 11.1 MB 26.9 MB/s  |████████████████████████████████| 3.1 MB 40.2 MB/s  |████████████████████████████████| 63 kB 1.9 MB/s  |████████████████████████████████| 690 kB 52.7 MB/s  |████████████████████████████████| 102 kB 13.0 MB/s  |████████████████████████████████| 812 kB 45.0 MB/s  |████████████████████████████████| 25.9 MB 1.4 MB/s  |████████████████████████████████| 271 kB 65.0 MB/s  |████████████████████████████████| 14.8 MB 51.0 MB/s  |████████████████████████████████| 146 kB 62.6 MB/s  |████████████████████████████████| 210 kB 53.9 MB/s  |████████████████████████████████| 62 kB 760 kB/s  |████████████████████████████████| 181 kB 46.4 MB/s  |████████████████████████████████| 79 kB 6.9 MB/s  |████████████████████████████████| 54 kB 2.4 MB/s  |████████████████████████████████| 63 kB 1.7 MB/s  |████████████████████████████████| 78 kB 7.0 MB/s  |████████████████████████████████| 1.7 MB 37.5 MB/s [?25h Installing build dependencies ... [?25l[?25hdone Getting requirements to build wheel ... [?25l[?25hdone Installing backend dependencies ... [?25l[?25hdone Preparing wheel metadata ... [?25l[?25hdone  |████████████████████████████████| 1.7 MB 49.2 MB/s  |████████████████████████████████| 1.1 MB 45.0 MB/s [?25h Building wheel for htmlmin (setup.py) ... [?25l[?25hdone Building wheel for imagehash (setup.py) ... [?25l[?25hdone Building wheel for databricks-cli (setup.py) ... [?25l[?25hdone Building wheel for pyLDAvis (setup.py) ... [?25l[?25hdone Building wheel for pyod (setup.py) ... [?25l[?25hdone Building wheel for umap-learn (setup.py) ... [?25l[?25hdone Building wheel for pynndescent (setup.py) ... [?25l[?25hdone ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts. tensorflow 2.8.0+zzzcolab20220506162203 requires tf-estimator-nightly==2.8.0.dev2021122109, which is not installed. xarray-einstats 0.2.2 requires numpy>=1.21, but you have numpy 1.19.5 which is incompatible. tensorflow 2.8.0+zzzcolab20220506162203 requires numpy>=1.20, but you have numpy 1.19.5 which is incompatible. google-colab 1.0.0 requires requests~=2.23.0, but you have requests 2.27.1 which is incompatible. datascience 0.10.6 requires folium==0.2.1, but you have folium 0.8.3 which is incompatible. albumentations 0.1.12 requires imgaug<0.2.7,>=0.2.5, but you have imgaug 0.2.9 which is incompatible.
from pycaret.utils import enable_colab
enable_colab()

Colab mode enabled.

今回のチュートリアルで出てくる技術の説明は以下です。

正規化: 正規化/スケーリング(標準化と同じ意味で使われることが多い)は、機械学習に役立つ特性を提供する方法で、数値変数の実際の値を変換するために使用されます。線形回帰、サポートベクターマシン、K Nearest Neighborsなどの多くのアルゴリズムは、すべての特徴がゼロを中心とし、同じレベルのオーダーの分散を持つことを前提としています。データセット内の特定の特徴が、他の特徴よりも大きいオーダーの分散を持っている場合、モデルはすべての特徴を正しく理解していない可能性があり、パフォーマンスが低下する可能性があります。

変換: 正規化が分散の大きさの影響を取り除くためにデータの範囲を変換するのに対し、変換は、変換されたデータが正規または近似正規分布で表現できるように分布の形を変えるという、より根本的な手法です。一般に、正規性やガウス分布を仮定したアルゴリズムを使用する場合は、データを変換する必要があります。このようなモデルの例としては、線形回帰、ラッソ回帰、リッジ回帰などがあります。

Target Transformation: これは上で説明したtransformationテクニックと似ていますが、例外的にこれはターゲット変数にのみ適用されます。

Combine Rare Levels: カテゴリー特徴には、頻度分布では重要でないレベルがあることがあります。このような場合、学習用のサンプルサイズが限られているため、データセットにノイズをもたらす可能性があります。稀なレベルを扱う1つの方法は、それらを新しいクラスに結合することです。

数値変数のビン化: ビン化または離散化は、数値変数をカテゴリー特徴に変換するプロセスです。例えば、この実験では「カラットの重さ」を例に挙げています。これは数値の連続的な分布で、間隔に離散化することができます。ビン化は、データのノイズや非線形性を低減することで、予測モデルの精度を向上させることができます。PyCaretでは、Sturgesルールを用いて、ビンの数とサイズを自動的に決定します。

モデルのアンサンブルとスタッキング: アンサンブルモデリングとは、ある結果を予測するために複数の多様なモデルを作成するプロセスです。これは、多くの異なるモデリングアルゴリズムを使用するか、またはトレーニングデータセットの異なるサンプルを使用することによって達成されます。そして、アンサンブルモデルは、各ベースモデルの予測を集約し、未見のデータに対する最終的な予測を1つにまとめます。アンサンブルモデルを使用はる動機は、予測の汎化誤差を低減することにあります。ベースモデルが多様で独立している限り、アンサンブルアプローチを使用すると、モデルの予測誤差は減少します。アンサンブル学習で最も一般的な手法はBaggingとBoostingです。スタッキングもアンサンブル学習の一種であり、複数のモデルからの予測値を、最終的な結果を予測するメタモデルの入力特徴として使用します。

Tuning Hyperparameters of Ensemblers: 単一の機械学習モデルのハイパーパラメータのチューニングと同様に、アンサンブルモデルのハイパーパラメータのチューニング方法も学びます。

データの取得

get_data() を使いデータを取得します。

前回と同様に、このチュートリアルでは、"Sarah Gets a Diamond "というケーススタディに基づいたデータセットを使います。

from pycaret.datasets import get_data
dataset = get_data('diamond', profile=True)

Summarize dataset: 0%| | 0/5 [00:00<?, ?it/s]
Generate report structure: 0%| | 0/1 [00:00<?, ?it/s]
Render HTML: 0%| | 0/1 [00:00<?, ?it/s]

profile "パラメータが "True "の場合、探索的データ解析のためのデータプロファイルが以下の様に表示されます。

このプロファイルが、データの重要な前処理の選択にどのように役立ったかをまとめてみましょう。

  • Missing Values: データには欠損値がありません。しかし、新しい未見のデータに欠損値がある場合に備えて、パイプラインにはインプータが必要です(今回は該当しません)。setup()関数を実行すると,インピュータが自動的に作成され,パイプラインに保存されます.デフォルトでは,数値に対しては平均インプータを,カテゴリに対しては定数インプータを使用します。これは、setup()のnumeric_imputationとcategorical_imputationのパラメータを使って変更できます。
  • Combine Rare Levels: データセット内の Clarity フィーチャーの分布に注目してください。7つの異なるクラスがありますが、そのうち FL は4回しか現れません。同様に、Cut特徴においても、Fairレベルはトレーニングデータセットの中で2.1%の頻度でしか現れません。ここでは、設定にある「combine_rare_categories」パラメータを使って、レアなレベルを組み合わせることにします。
  • データのスケール/範囲: 「Carat Weight」のスケール/範囲が「Price」の変数と大きく異なることに注目してください。Carat Weightは0.75から2.91の範囲であるのに対し、Priceは2,184から101,561までの範囲となっています。
  • Target Transformation: ターゲット変数 Price は正規分布ではありません。尖り度が高く、右に傾いています。ターゲット変数に線形変換を適用するために、セットアップのtransform_targetパラメータを使用します。
  • 数値特徴の抽出: Carat Weight は唯一の数値特徴です。そのヒストグラムを見ると、分布は自然な切れ目があるように見えます。ビン化することで、カテゴライズされた特徴に変換し、`sturges' ruleを用いていくつかのレベルを作成します。これにより、線形アルゴリズムのノイズを取り除くことができます。

取得したデータセットをモデル作成用( data )と予測用( data_unseen )とに90:10に分けます。

data = dataset.sample(frac=0.9, random_state=786)
data_unseen = dataset.drop(data.index)

data.reset_index(drop=True, inplace=True)
data_unseen.reset_index(drop=True, inplace=True)

print('Data for Modeling: ' + str(data.shape))
print('Unseen Data For Predictions ' + str(data_unseen.shape))

Data for Modeling: (5400, 8) Unseen Data For Predictions (600, 8)

セットアップと前処理

setup() を使ってセットアップと前処理をします。

from pycaret.regression import *

/usr/local/lib/python3.7/dist-packages/distributed/config.py:20: YAMLLoadWarning: calling yaml.load() without Loader=... is deprecated, as the default Loader is unsafe. Please read https://msg.pyyaml.org/load for full details. defaults = yaml.load(f)

前回とは異なり、 normalize = True など前処理のパラメータを有効にしています。

実行すると実行すると、投入したデータの型のチェックを自動で実施してくれます。 問題なければ、カーソルをあわせ、 Enter を押します。

exp_reg102 = setup(data = data, target = 'Price', session_id=123,
                  normalize = True, transformation = True, transform_target = True, 
                  combine_rare_levels = True, rare_level_threshold = 0.05,
                  remove_multicollinearity = True, multicollinearity_threshold = 0.95, 
                  bin_numeric_features = ['Carat Weight'],
                  log_experiment = True, experiment_name = 'diamond1')

Description Value
0 session_id 123
1 Target Price
2 Original Data (5400, 8)
3 Missing Values False
4 Numeric Features 1
5 Categorical Features 6
6 Ordinal Features False
7 High Cardinality Features False
8 High Cardinality Method None
9 Transformed Train Set (3779, 39)
10 Transformed Test Set (1621, 39)
11 Shuffle Train-Test True
12 Stratify Train-Test False
13 Fold Generator KFold
14 Fold Number 10
15 CPU Jobs -1
16 Use GPU False
17 Log Experiment True
18 Experiment Name diamond1
19 USI 68fb
20 Imputation Type simple
21 Iterative Imputation Iteration None
22 Numeric Imputer mean
23 Iterative Imputation Numeric Model None
24 Categorical Imputer constant
25 Iterative Imputation Categorical Model None
26 Unknown Categoricals Handling least_frequent
27 Normalize True
28 Normalize Method zscore
29 Transformation True
30 Transformation Method yeo-johnson
31 PCA False
32 PCA Method None
33 PCA Components None
34 Ignore Low Variance False
35 Combine Rare Levels True
36 Rare Level Threshold 0.05
37 Numeric Binning True
38 Remove Outliers False
39 Outliers Threshold None
40 Remove Multicollinearity True
41 Multicollinearity Threshold 0.95
42 Remove Perfect Collinearity True
43 Clustering False
44 Clustering Iteration None
45 Polynomial Features False
46 Polynomial Degree None
47 Trignometry Features False
48 Polynomial Threshold None
49 Group Features False
50 Feature Selection False
51 Feature Selection Method classic
52 Features Selection Threshold None
53 Feature Interaction False
54 Feature Ratio False
55 Interaction Threshold None
56 Transform Target True
57 Transform Target Method box-cox
2022/05/26 01:37:27 INFO mlflow.tracking.fluent: Experiment with name 'diamond1' does not exist. Creating a new experiment.

モデルの比較

setup の次は compare_models を使い、主要なモデルのパフォーマンスを比較していきます。

"compare_models" の中で "n_select" パラメータを使えば、上位N個のモデルを返すことができます。この例では、compare_models は上位3つのモデルを返しています。

top3 = compare_models(exclude = ['ransac'], n_select = 3)

Model MAE MSE RMSE R2 RMSLE MAPE TT (Sec)
lightgbm Light Gradient Boosting Machine 766.0853 3.116467e+06 1704.0975 0.9704 0.0799 0.0576 0.112
rf Random Forest Regressor 850.1194 3.267554e+06 1770.6698 0.9686 0.0904 0.0657 1.058
huber Huber Regressor 940.6199 3.651906e+06 1891.7125 0.9640 0.0972 0.0708 0.138
ridge Ridge Regression 952.2538 3.846278e+06 1934.6314 0.9624 0.0971 0.0715 0.024
br Bayesian Ridge 956.6502 3.999160e+06 1967.8153 0.9608 0.0972 0.0716 0.030
lr Linear Regression 960.2937 4.046533e+06 1978.6945 0.9604 0.0973 0.0717 0.169
et Extra Trees Regressor 964.4979 4.410739e+06 2062.2772 0.9569 0.1055 0.0759 1.184
dt Decision Tree Regressor 1000.2500 4.685153e+06 2136.9863 0.9539 0.1082 0.0778 0.037
gbr Gradient Boosting Regressor 1107.4885 5.269003e+06 2255.3276 0.9486 0.1100 0.0832 0.275
par Passive Aggressive Regressor 1341.4005 7.149373e+06 2588.2842 0.9288 0.1282 0.0964 0.030
knn K Neighbors Regressor 3331.7180 4.363497e+07 6566.1277 0.5685 0.3986 0.2639 0.137
ada AdaBoost Regressor 3827.7814 5.037255e+07 7060.1303 0.5053 0.3551 0.2721 0.239
omp Orthogonal Matching Pursuit 4047.2509 5.592846e+07 7424.8074 0.4530 0.4824 0.3507 0.026
lasso Lasso Regression 6501.4783 1.138127e+08 10639.8569 -0.1270 0.7148 0.5619 0.026
en Elastic Net 6501.4783 1.138127e+08 10639.8569 -0.1270 0.7148 0.5619 0.022
llar Lasso Least Angle Regression 6501.4777 1.138127e+08 10639.8582 -0.1270 0.7148 0.5618 0.279
dummy Dummy Regressor 6501.4777 1.138127e+08 10639.8582 -0.1270 0.7148 0.5618 0.020
type(top3)

list
print(top3)

[PowerTransformedTargetRegressor(boosting_type='gbdt', class_weight=None, colsample_bytree=1.0, importance_type='split', learning_rate=0.1, max_depth=-1, min_child_samples=20, min_child_weight=0.001, min_split_gain=0.0, n_estimators=100, n_jobs=-1, num_leaves=31, objective=None, power_transformer_method='box-cox', power_transformer_standardize=True, random_state=1... importance_type='split', learning_rate=0.1, max_depth=-1, min_child_samples=20, min_child_weight=0.001, min_split_gain=0.0, n_estimators=100, n_jobs=-1, num_leaves=31, objective=None, random_state=123, reg_alpha=0.0, reg_lambda=0.0, silent='warn', subsample=1.0, subsample_for_bin=200000, subsample_freq=0), silent='warn', subsample=1.0, subsample_for_bin=200000, subsample_freq=0), PowerTransformedTargetRegressor(bootstrap=True, ccp_alpha=0.0, criterion='mse', max_depth=None, max_features='auto', max_leaf_nodes=None, max_samples=None, min_impurity_decrease=0.0, min_impurity_split=None, min_samples_leaf=1, min_samples_split=2, min_weight_fraction_leaf=0.0, n_estimators=100, n_jobs=-1, oob_score=False, power_transformer_method='box-cox', power... regressor=RandomForestRegressor(bootstrap=True, ccp_alpha=0.0, criterion='mse', max_depth=None, max_features='auto', max_leaf_nodes=None, max_samples=None, min_impurity_decrease=0.0, min_impurity_split=None, min_samples_leaf=1, min_samples_split=2, min_weight_fraction_leaf=0.0, n_estimators=100, n_jobs=-1, oob_score=False, random_state=123, verbose=0, warm_start=False), verbose=0, warm_start=False), PowerTransformedTargetRegressor(alpha=0.0001, epsilon=1.35, fit_intercept=True, max_iter=100, power_transformer_method='box-cox', power_transformer_standardize=True, regressor=HuberRegressor(alpha=0.0001, epsilon=1.35, fit_intercept=True, max_iter=100, tol=1e-05, warm_start=False), tol=1e-05, warm_start=False)]

また、今回は前処理を行ったため、前回の前処理を行わなかった場合に比べて以下の様に誤差が改善されています。

比較のために,「RMSLE」スコアを使用します.setup()`でいくつかの前処理を行った後、いくつかのアルゴリズムがどれほど劇的に改善されたかに注目してください。

  • 線形回帰 RMSLE が 0.6690 から 0.0973 に改善
  • リッジ回帰 RMSLE が 0.6689 から 0.0971 に改善
  • Huber 回帰 RMSLE が 0.4333 から 0.0972 に改善

モデルの作成

create_model() 関数を使ってモデルを作成していきます。

ここでは、便利な他のいくつかのパラメータについて学びます。このセクションでは、5フォールドのクロスバリデーションを使用してすべてのモデルを作成します。これを実現するために、create_model()の中でfoldパラメータを渡していることに注目してください。

Create Model (with 5 Fold CV)

dt = create_model('dt', fold = 5)

MAE MSE RMSE R2 RMSLE MAPE
Fold
0 1028.5317 5.336679e+06 2310.1254 0.9518 0.1073 0.0776
1 1002.9714 4.289730e+06 2071.1663 0.9570 0.1067 0.0789
2 1002.9420 6.074744e+06 2464.6996 0.9385 0.1088 0.0783
3 980.6975 3.482257e+06 1866.0808 0.9625 0.1086 0.0790
4 1109.5188 1.074509e+07 3277.9707 0.8962 0.1177 0.0802
Mean 1024.9323 5.985700e+06 2398.0085 0.9412 0.1098 0.0788
Std 44.9230 2.538681e+06 485.0314 0.0239 0.0040 0.0009

Create Model (Metrics rounded to 2 decimals points)

create_model() の中で round パラメータ(=2)を渡すと、評価指標が10進数2桁に丸められます。

rf = create_model('rf', round = 2)

MAE MSE RMSE R2 RMSLE MAPE
Fold
0 827.12 2367714.94 1538.74 0.97 0.09 0.07
1 932.90 6257192.34 2501.44 0.95 0.09 0.06
2 806.48 2358322.19 1535.68 0.98 0.09 0.06
3 829.33 1816996.40 1347.96 0.98 0.09 0.07
4 805.32 2060509.90 1435.45 0.97 0.09 0.07
5 899.30 5529805.07 2351.55 0.95 0.09 0.06
6 898.33 3500090.57 1870.85 0.97 0.09 0.07
7 818.69 2497357.69 1580.30 0.97 0.09 0.07
8 804.13 2966084.29 1722.23 0.97 0.09 0.06
9 879.58 3321466.07 1822.49 0.97 0.10 0.07
Mean 850.12 3267553.94 1770.67 0.97 0.09 0.07
Std 45.21 1414010.93 363.71 0.01 0.00 0.00

Create Model (KNN)

knn = create_model('knn')

MAE MSE RMSE R2 RMSLE MAPE
Fold
0 3254.4923 3.877327e+07 6226.8189 0.5743 0.3749 0.2306
1 3834.1424 6.517155e+07 8072.8896 0.5005 0.4376 0.2928
2 3403.3240 4.831358e+07 6950.7968 0.5569 0.4074 0.2705
3 3350.6552 3.851898e+07 6206.3663 0.5750 0.3888 0.2577
4 3196.6928 3.498237e+07 5914.5893 0.5637 0.4034 0.2820
5 3043.3822 3.923901e+07 6264.1050 0.6651 0.3841 0.2501
6 3573.7008 5.945415e+07 7710.6514 0.4414 0.4151 0.2603
7 3257.3364 3.720500e+07 6099.5905 0.5295 0.4161 0.2676
8 3149.6089 3.485767e+07 5904.0387 0.6577 0.3484 0.2388
9 3253.8450 3.983416e+07 6311.4305 0.6207 0.4107 0.2881
Mean 3331.7180 4.363497e+07 6566.1277 0.5685 0.3986 0.2639
Std 216.4638 1.006376e+07 721.7620 0.0652 0.0239 0.0195
print(knn)

PowerTransformedTargetRegressor(algorithm='auto', leaf_size=30, metric='minkowski', metric_params=None, n_jobs=-1, n_neighbors=5, p=2, power_transformer_method='box-cox', power_transformer_standardize=True, regressor=KNeighborsRegressor(algorithm='auto', leaf_size=30, metric='minkowski', metric_params=None, n_jobs=-1, n_neighbors=5, p=2, weights='uniform'), weights='uniform')

モデルのチューニング

前回のチュートリアル Regression (REG101) - Level Beginner では、あらかじめ定義されたグリッドを使って、モデルのハイパーパラメータを自動的にチューニングする方法を学びました。ここでは、tune_model()のn_iterというパラメータを紹介します。n_iter は,ランダムグリッド探索の反復回数です.反復ごとに,モデルはあらかじめ定義されたハイパーパラメータのグリッドから1つの値をランダムに選択します.デフォルトでは,このパラメータは 10 に設定されています.これは,ハイパーパラメータの最適な値を見つけるために,最大10回の反復を行うことを意味します.この値を大きくするとパフォーマンスが向上しますが,同時にトレーニング時間も長くなります.以下の例をご覧ください。

tuned_knn = tune_model(knn)

MAE MSE RMSE R2 RMSLE MAPE
Fold
0 2147.6416 2.459108e+07 4958.9393 0.7300 0.3007 0.1553
1 2845.0366 4.152765e+07 6444.1950 0.6817 0.3557 0.1988
2 2510.7885 4.191156e+07 6473.9136 0.6156 0.3389 0.1781
3 2642.8821 3.255360e+07 5705.5762 0.6408 0.3395 0.1820
4 2358.5821 2.931050e+07 5413.9174 0.6344 0.3297 0.1848
5 2398.9496 4.033613e+07 6351.0729 0.6557 0.3165 0.1773
6 2597.6844 4.833286e+07 6952.1836 0.5459 0.3329 0.1673
7 2335.7423 2.874308e+07 5361.2572 0.6365 0.3427 0.1759
8 2533.9681 3.366081e+07 5801.7935 0.6694 0.2921 0.1576
9 2446.9586 3.217334e+07 5672.1546 0.6936 0.3270 0.1961
Mean 2481.8234 3.531406e+07 5913.5003 0.6504 0.3276 0.1773
Std 181.9711 7.009039e+06 587.0037 0.0472 0.0185 0.0137
tuned_knn2 = tune_model(knn, n_iter = 50)

MAE MSE RMSE R2 RMSLE MAPE
Fold
0 2108.3491 2.320149e+07 4816.7922 0.7453 0.2893 0.1529
1 2882.1901 4.223230e+07 6498.6381 0.6763 0.3694 0.2075
2 2412.5226 3.998645e+07 6323.4837 0.6333 0.3299 0.1740
3 2644.6452 3.247108e+07 5698.3403 0.6417 0.3415 0.1878
4 2347.7756 2.910277e+07 5394.6986 0.6370 0.3421 0.1921
5 2198.6207 2.788156e+07 5280.2994 0.7620 0.2958 0.1719
6 2605.5384 4.778395e+07 6912.5937 0.5511 0.3354 0.1664
7 2419.6011 2.893196e+07 5378.8439 0.6341 0.3511 0.1854
8 2385.9747 2.856662e+07 5344.7753 0.7195 0.2798 0.1559
9 2445.4325 3.267484e+07 5716.1909 0.6889 0.3329 0.1978
Mean 2445.0650 3.328330e+07 5736.4656 0.6689 0.3267 0.1792
Std 211.0543 7.251174e+06 613.4040 0.0597 0.0275 0.0170

n_iterパラメータに基づいて2つのチューニングされたK個の近傍探索が作成されたことに注目してください。tuned_knnでは、n_iterパラメータはデフォルト値のままで、R2は0.6504となりました。tuned_knn2では,n_iterパラメータを50に設定したところ,R2は0.6689に改善しました.以下に,tuned_knnとtuned_knn2のハイパーパラメータの違いを見てみましょう.

plot_model(tuned_knn, plot = 'parameter')

Parameters
algorithm auto
leaf_size 30
metric minkowski
metric_params None
n_jobs -1
n_neighbors 9
p 2
weights distance
power_transformer_method box-cox
power_transformer_standardize True
regressor KNeighborsRegressor(algorithm='auto', leaf_siz...
plot_model(tuned_knn2, plot = 'parameter')

Parameters
algorithm auto
leaf_size 30
metric euclidean
metric_params None
n_jobs -1
n_neighbors 6
p 2
weights distance
power_transformer_method box-cox
power_transformer_standardize True
regressor KNeighborsRegressor(algorithm='auto', leaf_siz...

アンサンブル

アンサンブルは、モデル(主にツリーベース)のパフォーマンスを向上させるために使用される一般的な機械学習技術です。アンサンブルには様々な手法がありますが、ここではBaggingとBoostingについて説明します。その中にはBaggingやBoosting があります。ここでは、PyCaretのensemble_model()関数を使用します。この関数は、methodパラメータで定義された手法を用いて、学習された基本推定量をアンサンブルします。

# lets create a simple dt
dt = create_model('dt')

MAE MSE RMSE R2 RMSLE MAPE
Fold
0 990.7311 3.452088e+06 1857.9795 0.9621 0.1082 0.0784
1 1003.5928 5.974333e+06 2444.2450 0.9542 0.1006 0.0733
2 1072.0395 5.624100e+06 2371.5185 0.9484 0.1143 0.0821
3 957.9666 3.199437e+06 1788.6969 0.9647 0.1025 0.0770
4 961.1217 4.292576e+06 2071.8532 0.9465 0.1141 0.0790
5 932.6466 5.733572e+06 2394.4879 0.9511 0.0962 0.0709
6 1024.7338 4.130405e+06 2032.3399 0.9612 0.1108 0.0797
7 968.4182 3.470200e+06 1862.8472 0.9561 0.1095 0.0801
8 885.1288 2.911378e+06 1706.2761 0.9714 0.1021 0.0732
9 1206.1210 8.063438e+06 2839.6193 0.9232 0.1233 0.0846
Mean 1000.2500 4.685153e+06 2136.9863 0.9539 0.1082 0.0778
Std 83.9006 1.544916e+06 344.1541 0.0126 0.0076 0.0041

バギング

bootstrap aggregating の略だそうです。
バギングについてのwiki

bagged_dt = ensemble_model(dt)

MAE MSE RMSE R2 RMSLE MAPE
Fold
0 849.4748 3.027622e+06 1740.0062 0.9668 0.0915 0.0672
1 933.2433 6.195361e+06 2489.0483 0.9525 0.0880 0.0644
2 844.0390 3.678395e+06 1917.9142 0.9663 0.0897 0.0651
3 827.7642 1.835711e+06 1354.8843 0.9797 0.0886 0.0683
4 832.9346 2.140130e+06 1462.9184 0.9733 0.0967 0.0697
5 907.7377 5.389385e+06 2321.5050 0.9540 0.0911 0.0654
6 940.6783 4.800963e+06 2191.1100 0.9549 0.0936 0.0667
7 856.0980 2.812959e+06 1677.1879 0.9644 0.0929 0.0673
8 872.8414 3.557087e+06 1886.0241 0.9651 0.0949 0.0667
9 924.5289 3.784941e+06 1945.4924 0.9640 0.1051 0.0730
Mean 878.9340 3.722255e+06 1898.6091 0.9641 0.0932 0.0674
Std 41.2902 1.321508e+06 342.8397 0.0081 0.0047 0.0024
# check the parameter of bagged_dt
print(bagged_dt)

PowerTransformedTargetRegressor(base_estimator=DecisionTreeRegressor(ccp_alpha=0.0, criterion='mse', max_depth=None, max_features=None, max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None, min_samples_leaf=1, min_samples_split=2, min_weight_fraction_leaf=0.0, presort='deprecated', random_state=123, splitter='best'), bootstrap=True, bootstrap_... min_impurity_decrease=0.0, min_impurity_split=None, min_samples_leaf=1, min_samples_split=2, min_weight_fraction_leaf=0.0, presort='deprecated', random_state=123, splitter='best'), bootstrap=True, bootstrap_features=False, max_features=1.0, max_samples=1.0, n_estimators=10, n_jobs=None, oob_score=False, random_state=123, verbose=0, warm_start=False), verbose=0, warm_start=False)

アンサンブルによって,RMSLE が 0.1082 から 0.0938 に改善されたことに注目してください.上の例では,ensemble_model() のデフォルトのパラメータを使用し,Bagging メソッドを使用しました.それでは、ensemble_model()のmethodパラメータを変更してBoostingを試してみましょう。以下の例をご覧ください。

ブースティング

ブースティングについての wiki

boosted_dt = ensemble_model(dt, method = 'Boosting')

MAE MSE RMSE R2 RMSLE MAPE
Fold
0 868.3699 2.499821e+06 1581.0822 0.9726 0.0989 0.0722
1 986.6441 6.014026e+06 2452.3511 0.9539 0.0926 0.0686
2 997.5712 6.325667e+06 2515.0878 0.9420 0.1071 0.0737
3 977.9167 3.384193e+06 1839.6176 0.9627 0.1025 0.0768
4 879.8784 2.351399e+06 1533.4272 0.9707 0.1066 0.0751
5 1006.5525 5.799557e+06 2408.2270 0.9505 0.1013 0.0731
6 1004.5586 4.526875e+06 2127.6453 0.9575 0.1003 0.0720
7 830.6719 2.189836e+06 1479.8095 0.9723 0.0934 0.0692
8 838.6467 2.642303e+06 1625.5163 0.9741 0.0942 0.0680
9 1017.9078 4.750678e+06 2179.6051 0.9548 0.1111 0.0775
Mean 940.8718 4.048436e+06 1974.2369 0.9611 0.1008 0.0726
Std 72.4965 1.548831e+06 388.3608 0.0105 0.0059 0.0032

PyCaretでは、モデルのアンサンブルがとても簡単にできることに注目してください。methodパラメータを変更するだけで、何行ものコードを必要とするBaggingやBoostingを行うことができます。なお、ensemble_model() はデフォルトで 10 個の推定量を構築します。これは n_estimators パラメータで変更することができます。推定量の数を増やすことで,結果が改善されることがあります.以下の例をご覧ください。

bagged_dt2 = ensemble_model(dt, n_estimators=50)

MAE MSE RMSE R2 RMSLE MAPE
Fold
0 828.6424 2.462714e+06 1569.3035 0.9730 0.0897 0.0660
1 922.2578 6.129373e+06 2475.7571 0.9530 0.0875 0.0634
2 812.0619 2.403974e+06 1550.4753 0.9780 0.0863 0.0643
3 838.2974 1.882830e+06 1372.1626 0.9792 0.0888 0.0682
4 812.0100 2.198267e+06 1482.6554 0.9726 0.0936 0.0674
5 895.6672 5.571079e+06 2360.3133 0.9525 0.0898 0.0637
6 918.0721 4.126036e+06 2031.2647 0.9612 0.0910 0.0659
7 819.5798 2.431817e+06 1559.4285 0.9692 0.0898 0.0658
8 812.8457 3.082259e+06 1755.6363 0.9697 0.0910 0.0641
9 885.2110 3.405185e+06 1845.3144 0.9676 0.1034 0.0713
Mean 854.4645 3.369353e+06 1800.2311 0.9676 0.0911 0.0660
Std 43.3157 1.390529e+06 358.4987 0.0089 0.0045 0.0023

n_estimators パラメータを増やすことで、どのように結果が改善されるかに注目してください。デフォルトの 10 推定量の bagged_dt モデルでは、RMSLE は 0.0996 でしたが、n_estimators = 50 の bagged_dt2 では、RMSLE は 0.0911 に改善されました。

ブレンディング

ブレンディングは、PyCaretで使用できるアンサンブルのもう一つの一般的な手法です。複数のモデルを作成し、個々の予測値を平均化して最終的な予測値を形成します。以下に例を挙げてみましょう。

# train individual models to blend
lightgbm = create_model('lightgbm', verbose = False)
dt = create_model('dt', verbose = False)
lr = create_model('lr', verbose = False)

# blend individual models
blender = blend_models(estimator_list = [lightgbm, dt, lr])

MAE MSE RMSE R2 RMSLE MAPE
Fold
0 720.6507 1.539808e+06 1240.8899 0.9831 0.0791 0.0594
1 826.5039 3.809702e+06 1951.8459 0.9708 0.0759 0.0569
2 761.9634 2.948787e+06 1717.2033 0.9730 0.0795 0.0599
3 729.2915 1.478819e+06 1216.0671 0.9837 0.0760 0.0591
4 678.8425 1.540171e+06 1241.0362 0.9808 0.0801 0.0579
5 753.6933 3.676543e+06 1917.4312 0.9686 0.0766 0.0554
6 850.0921 2.695722e+06 1641.8655 0.9747 0.0864 0.0640
7 773.7834 2.209680e+06 1486.4993 0.9721 0.0817 0.0607
8 697.7342 1.709749e+06 1307.5737 0.9832 0.0772 0.0567
9 861.3020 3.358471e+06 1832.6131 0.9680 0.0925 0.0648
Mean 765.3857 2.496745e+06 1555.3025 0.9758 0.0805 0.0595
Std 59.7495 8.758419e+05 278.8894 0.0060 0.0050 0.0029
# blend top3 models from compare_models
blender_top3 = blend_models(top3)

MAE MSE RMSE R2 RMSLE MAPE
Fold
0 680.8011 1.427623e+06 1194.8318 0.9843 0.0769 0.0571
1 829.7327 4.418361e+06 2101.9899 0.9661 0.0752 0.0558
2 700.4376 2.084231e+06 1443.6865 0.9809 0.0753 0.0558
3 707.4990 1.387395e+06 1177.8772 0.9847 0.0743 0.0572
4 644.1772 1.253330e+06 1119.5220 0.9844 0.0765 0.0554
5 755.3631 3.730314e+06 1931.4022 0.9682 0.0768 0.0547
6 833.3162 2.753643e+06 1659.4103 0.9741 0.0829 0.0609
7 731.8809 2.115441e+06 1454.4554 0.9732 0.0781 0.0570
8 704.2782 2.114216e+06 1454.0344 0.9792 0.0774 0.0559
9 751.9018 2.219555e+06 1489.8171 0.9789 0.0877 0.0612
Mean 733.9388 2.350411e+06 1502.7027 0.9774 0.0781 0.0571
Std 57.8102 9.759430e+05 303.8017 0.0064 0.0039 0.0021
print(blender_top3.estimators_)

[LGBMRegressor(boosting_type='gbdt', class_weight=None, colsample_bytree=1.0, importance_type='split', learning_rate=0.1, max_depth=-1, min_child_samples=20, min_child_weight=0.001, min_split_gain=0.0, n_estimators=100, n_jobs=-1, num_leaves=31, objective=None, random_state=123, reg_alpha=0.0, reg_lambda=0.0, silent='warn', subsample=1.0, subsample_for_bin=200000, subsample_freq=0), RandomForestRegressor(bootstrap=True, ccp_alpha=0.0, criterion='mse', max_depth=None, max_features='auto', max_leaf_nodes=None, max_samples=None, min_impurity_decrease=0.0, min_impurity_split=None, min_samples_leaf=1, min_samples_split=2, min_weight_fraction_leaf=0.0, n_estimators=100, n_jobs=-1, oob_score=False, random_state=123, verbose=0, warm_start=False), HuberRegressor(alpha=0.0001, epsilon=1.35, fit_intercept=True, max_iter=100, tol=1e-05, warm_start=False)]

これで blend_models() 関数を使って VotingRegressor を作成することができました。blend_models 関数が返すモデルは、create_model() や tune_model() を使って作成した他のモデルと同じです。このモデルは,他のモデルと同じように,predict_model()を使って,見たことのないデータを予測するのに使うことができます.

スタッキング

アンサンブルの手法としては、スタッキングもよく知られていますが、実用上の難しさから実装されることはあまりありません。スタッキングは、複数のモデルをメタモデルを介して結合するアンサンブル学習の手法です。スタッキングを別の方法で考えると,結果を予測するために複数のモデルが学習され,それらのモデルからの予測値を元の特徴量と一緒に入力として使用するメタモデルが作成されます.stack_models()の実装は、Wolpert, D. H. (1992b).Stacked generalization

以下、compare_modelsで得られた上位3つのモデルを使った例を見てみましょう。

stacker = stack_models(top3)

MAE MSE RMSE R2 RMSLE MAPE
Fold
0 667.5560 1.502384e+06 1225.7176 0.9835 0.0759 0.0555
1 811.1150 3.560661e+06 1886.9715 0.9727 0.0740 0.0556
2 713.3852 2.631901e+06 1622.3135 0.9759 0.0759 0.0556
3 681.8678 1.293207e+06 1137.1927 0.9857 0.0718 0.0554
4 658.1178 1.407224e+06 1186.2646 0.9824 0.0743 0.0545
5 814.9650 1.345368e+07 3667.9252 0.8852 0.0943 0.0536
6 829.2008 2.681051e+06 1637.3914 0.9748 0.0832 0.0612
7 725.0368 2.079500e+06 1442.0472 0.9737 0.0765 0.0563
8 687.8250 1.766239e+06 1328.9993 0.9827 0.0750 0.0550
9 822.6461 4.157904e+06 2039.0939 0.9604 0.1008 0.0626
Mean 741.1716 3.453375e+06 1717.3917 0.9677 0.0802 0.0565
Std 66.6612 3.452225e+06 709.8876 0.0284 0.0092 0.0028

デフォルトでは、メタモデル(予測を生成する最終的なモデル)はLinear Regressionです。メタモデルは、meta_modelパラメータを使って変更できます。以下に例を示します。

xgboost = create_model('xgboost')
stacker2 = stack_models(top3, meta_model = xgboost)

ValueError
ignored
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-28-120978fdac57> in <module>() ----> 1 xgboost = create_model('xgboost') 2 stacker2 = stack_models(top3, meta_model = xgboost)
/usr/local/lib/python3.7/dist-packages/pycaret/regression.py in create_model(estimator, fold, round, cross_validation, fit_kwargs, groups, verbose, return_train_score, **kwargs) 953 verbose=verbose, 954 return_train_score=return_train_score, --> 955 **kwargs, 956 ) 957
/usr/local/lib/python3.7/dist-packages/pycaret/internal/tabular.py in create_model_supervised(estimator, fold, round, cross_validation, predict, fit_kwargs, groups, refit, verbose, system, X_train_data, y_train_data, metrics, experiment_custom_tags, add_to_model_list, probability_threshold, display, return_train_score, **kwargs) 2959 if estimator not in available_estimators: 2960 raise ValueError( -> 2961 f"Estimator {estimator} not available. Please see docstring for list of available estimators." 2962 ) 2963 elif not hasattr(estimator, "fit"):
ValueError: Estimator xgboost not available. Please see docstring for list of available estimators.

今回はエラーになってしまいましたが、 pycaret を full でインストールすると良いらしいです。
https://stackoverflow.com/questions/67068965/estimator-xgboost-not-available-for-pycaret-in-google-colab

このセクションを終える前に、stack_models()には、restackというまだ見たことのないパラメータがあります。このパラメータは、生データをメタモデルに公開するかどうかを制御します。Trueに設定すると、ベースレベルモデルのすべての予測値とともに、生データをメタモデルに公開します。デフォルトでは、Trueに設定されています。以下の例では、restackパラメータをFalseに変更しています。

以上、回帰分析のチューニングのその2でした。
setup() のパラメータを有効にするだけで前処理ができたり、 ensemble_model() などの関数で簡単にアンサンブル学習ができるのは、本当に便利ですね。

Discussion

コメントにはログインが必要です。