概要
PyCaretのLassoとLightGBMで学習したモデルの重みを用いて、特徴量選択を実施した。
実装
実行環境は以下の通り
- Python 3.9.0
- PyCaret 2.3.0
前準備
データは、pycaretに用意されているサンプルデータのinsuarance
を利用する。
Build and deploy your first machine learning web app - PyCaret Official
このデータは、保険会社が顧客の保険料を決める際に、貸し倒れしないような保険料を設定すべく、患者がWebに入力したフォームの内容から、将来の疾患や起こりうる健康リスクを予測し、患者ごとの適切な料金を設定するというタスクを解くために用意されたもの。
データの中身を見ると、顧客の性別や年齢、喫煙の有無といった情報が格納されている。
from pycaret.datasets import get_data
insurance = get_data('insurance')
age sex bmi children smoker region charges
0 19 female 27.900 0 yes southwest 16884.92400
1 18 male 33.770 1 no southeast 1725.55230
2 28 male 33.000 3 no southeast 4449.46200
3 33 male 22.705 0 no northwest 21984.47061
4 32 male 28.880 0 no northwest 3866.85520
データを読み込み後setup
を実行し、データをPycaretのパイプラインに載せる。silent=True
とすることで、setup実行時に「このデータで問題ない?」のYes/Noの入力の手間が省ける。
from pycaret.regression import *
exp_name = setup(data = insurance, target = 'charges', silent = True)
後の可視化に利用するので、カラム名を取得する。setup処理で、子供の人数(children
)や喫煙の有無(smoker_yes
)がワンホットベクトルとして作成されたことが確認できる。
columns = get_config("X").columns
print(columns)
Index(['age', 'bmi', 'sex_male', 'children_0', 'children_1', 'children_2',
'children_3', 'children_4', 'children_5', 'smoker_yes',
'region_northeast', 'region_northwest', 'region_southeast',
'region_southwest'],
dtype='object')
全モデルで探索を実行すると、以下の出力を得られる。gbrのR2の最大値が0.8613なので、後の特徴量選択でどのように変化するか確認する。
compare_models()
Lassoによる特徴量の重要度の確認
Lassoのモデルの作成と、作成したモデルのチューニングをおこなう。
lasso = create_model('lasso')
tuned_lasso = tune_model(lasso)
作成されたlasso
、tuned_lasso
の型を出力すると、sklearn.linear_model._coordinate_descent.Lasso
であることが確認できる。
type(tuned_lasso)
sklearn.linear_model._coordinate_descent.Lasso
つまり作成されたモデルに対して、以下のscikit-learnのlassoと同じ処理が行える。
sklearn.linear_model.Lasso — scikit-learn 1.0.2 documentation
sklearn.linear_model._coordinate_descent.Lasso
は、coef_
のメンバ変数に各特徴量の重みが格納されている。なのでcoef_
を利用して、各特徴量が予測結果にどれだけ影響を与えているかを確認する。
feature_imp = pd.DataFrame(sorted(zip(tuned_lasso.coef_, columns)), columns=['Value','Feature'])
feature_imp.plot.barh(x='Feature',)
結果からsmoker_yes
の喫煙者である、という要素が保険料の増額に大きな影響を与えることが確認できる。直感的にも喫煙=健康に悪いという点から、喫煙者であることが保険料を値上げする要因であることは納得できる。値を見ると年額$23,000程度値上がりするようなので、禁煙は健康にも金銭的にもお勧めできる。
次に重み=0
の推論に全く利用されていない特徴量を確認するとchildren_1
、children_5
の2つであることが確認できた。
print(columns[tuned_lasso.coef_ == 0 ])
Index(['children_1', 'children_5'], dtype='object')
LightGBMによる特徴量の重要度の確認
Lassoの場合と同様に、モデルの作成とチューニングを実施する。
lightgbm = create_model('lightgbm')
tuned_lightgbm = tune_model(lightgbm)
モデルの型を出力すると、lightgbm.sklearn.LGBMRegressor
であることが確認できた。
type(tuned_lightgbm)
lightgbm.sklearn.LGBMRegressor
lightgbm.sklearn.LGBMRegressor
は、feature_importances_
に各特徴量の重要度が格納されているので、Lassoと同じ手順で特徴量の重要度を確認する。
feature_imp = pd.DataFrame(sorted(zip(tuned_lightgbm.feature_importances_, columns)), columns=['Value','Feature'])
feature_imp.plot.barh(x='Feature',)
こちらもfeature_importances_
が0の特徴量を出力すると、children_4
, children_5
の2つを得られた。
print(columns[tuned_lightgbm.feature_importances_ == 0 ])
Index(['children_4', 'children_5'], dtype='object')
選択した特徴量で再学習
LassoとLightGMBで利用されなかった特徴量を取り除いて、再度学習を行う。Pycaretのパイプラインからデータを取り出す場合はget_config
を利用する。
drop_columns = ['children_1', 'children_4', 'children_5']
# PycaretのXを取得し、不要なカラムを削除
pycaret_X = get_config('X')
feature_selected_X = pycaret_X.drop(drop_columns, axis=1)
print(feature_selected_X.columns)
Index(['age', 'bmi', 'sex_male', 'children_0', 'children_2', 'children_3',
'smoker_yes', 'region_northeast', 'region_northwest',
'region_southeast', 'region_southwest'],
dtype='object')
その後set_config
を利用し、作成したデータをパイプラインにセットする。
set_config('X', feature_selected_X)
その後、再び学習を実行する。
compare_models()
出力結果を見るとgbrのR2のスコアが最初の0.8613
から0.8347
に下がってしまった。今回は特徴量が13と少ないデータだったため、削減する必要もなかったのかも。
Kaggleなどの実際のデータで特徴量が大量の場合に利用すると効果的かもしれない。