質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.12%

RandomForest、XGBoosting、LightGBM、各手法における特徴量の重要度についての比較

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 3,877

A.Kobayashi

score 11

 前提・実現したいこと

KaggleのTitanicにおいて、RandomForest、XGBoosting、LightGBMで特徴量の重要度を算出し比較を行ってみたのですが、結果の解釈をどのようにすればいいか悩んでいます。

 発生している問題・エラーメッセージ

下記のように精度的にはXGBoostingとLightGBMのBoostingを用いた手法が若干勝り、Boosting両手法における重要度も近しい値となっているのですが、一方でTitanicでは重要な項目とされる性別の重要度が異常に低く、重要度に関してはRandomForestのほうが納得がいく結果になっているのですが、RandomForestとBoostingにおける特徴量の重要度はそこまで異なるものなのでしょうか?

RandomForest
f1 core:0.833

Pclass    8.4    
Sex    29.5    
Age    23.7    
SibSp    4.8    
Parch    4.5    
Fare    20.0    
Cabin    4.9    
Embarked    4.1    

XGBoosting
f1 score:0.848

Pclass    4.6    
Sex    6.1    
Age    39.9    
SibSp    4.9    
Parch    1.8    
Fare    36.3    
Cabin    3.4    
Embarked    3.0    

LightGBM
f1 score:0.838

Pclass    3.6    
Sex    3.1    
Age    40.9    
SibSp    8.2    
Parch    5.9    
Fare    33.5    
Cabin    2.3    
Embarked    2.6    

### 該当のソースコード

import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix
from sklearn.metrics import f1_score
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import make_scorer
import xgboost as xgb
import lightgbm as lgb

# トレーニングデータ作成
df = pd.read_csv("train.csv")
X_train = df.drop(["y"],axis=1)
y_train = df.y

# スコア検証分割
X_train, X_test, y_train, y_test = train_test_split(X_train, y_train, test_size=0.2, random_state=0)

# スコア方法をF1に設定
f1_scoring = make_scorer(f1_score,  pos_label=1)

# RandomForest
print("RandomForest")
forest_param = {
    'n_estimators': [20,100,500],
    'max_depth': [3,5,7,9],
    'min_samples_leaf': [1, 2, 4]
}

# グリッドサーチで学習
rf = GridSearchCV(RandomForestClassifier(random_state=0, n_jobs=-1), forest_param, scoring=f1_scoring, cv=5)
rf.fit(X_train, y_train)
print('Best parameters: {}'.format(rf.best_params_))
# スコア検証
print('Train score: {:.3f}'.format(rf.score(X_train, y_train)))
print('Confusion matrix:\n{}'.format(confusion_matrix(y_test, rf.predict(X_test))))
print('f1 score: {:.3f}'.format(f1_score(y_test, rf.predict(X_test))))
rf_importances = pd.Series(rf.best_estimator_.feature_importances_, index = X_train.columns)
print(rf_importances)

# XGBoosting
print("XGBoosting")
xgb_param = {
    'learning_rate':[0.1,0.2],
    'n_estimators':[20,100,500],
    'max_depth':[3,5,7,9],
    'min_child_weight':[0.5,1,2],
    'max_delta_step':[5],
    'gamma':[1,3,5],
    'subsample':[0.8],
    'colsample_bytree':[0.8],
    'objective':['binary:logistic'],
    'nthread':[4],
    'scale_pos_weight':[1],
    'seed':[0]
}
# グリッドサーチで学習
xgb = GridSearchCV(xgb.XGBClassifier(
    silent=True, booster='gbtree', reg_alpha=0, reg_lambda=1, base_score=0.5, random_state=0, missing=None),
    xgb_param, scoring=f1_scoring, cv=4)
xgb.fit(X_train, y_train)
print('Best parameters: {}'.format(xgb.best_params_))
# スコア検証
print('Train score: {:.3f}'.format(xgb.score(X_train, y_train)))
print('Confusion matrix:\n{}'.format(confusion_matrix(y_test, xgb.predict(X_test))))
print('f1 score: {:.3f}'.format(f1_score(y_test, xgb.predict(X_test))))
xgb_importances = pd.Series(xgb.best_estimator_.feature_importances_, index = X_train.columns)
print(xgb_importances)

# LightGBM
print("LightGBM")
gbm_param = {
    'learning_rate':[0.1,0.2],
    'n_estimators':[20,100,500],
    'max_depth':[3,5,7,9],
    'min_child_weight':[0.5,1,2],
    'min_child_samples':[5,10,20],
    'subsample':[0.8],
    'colsample_bytree':[0.8],
    'verbose':[-1],
    'num_leaves':[80]
}
# グリッドサーチで学習
gbm = GridSearchCV(lgb.LGBMClassifier(),gbm_param, scoring=f1_scoring, cv=5)
gbm.fit(X_train, y_train)
print('Best parameters: {}'.format(gbm.best_params_))
# スコア検証
print('Train score: {:.3f}'.format(gbm.score(X_train, y_train)))
print('Confusion matrix:\n{}'.format(confusion_matrix(y_test, gbm.predict(X_test))))
print('f1 score: {:.3f}'.format(f1_score(y_test, gbm.predict(X_test))))
gbm_importances = pd.Series(gbm.best_estimator_.feature_importances_, index = X_train.columns)
print(gbm_importances)

 試したこと

https://qiita.com/TomokIshii/items/290adc16e2ca5032ca07
ではパラメータの調整不足が指摘されていたので、グリッドサーチを用いてパラメータの最適化をしてみました。

 補足情報(FW/ツールのバージョンなど)

python3.6
scikit-learn==0.19.1
lightgbm==2.1.0
xgboost==0.7
返信は月曜まで遅れるかもしれません、ご容赦お願いします。
コードについても修正点などあれば指摘してもらえれば幸いです。
よろしくお願いいたします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+3

http://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.RFE.html#sklearn.feature_selection.RFE

削除していく時には、関連性の低い特徴量から消すのが一般的かと思います。

「重要度」は汎用的にアルゴリズム全般に対して定義しにくい量です。

アルゴリズムが異なりますので、重要度も異なるのだと思われます。
Boostingするとややこしくなるのは仕方のないことだと思います。
珍しい項目をもうまく予測するアルゴリズムがBoostingだと思うと、
そのような項目を決定するために大局的な特徴量とは別のものを注目してしまう傾向はあるのだと思います。

選択する際には単純なモデルで行い、精度を出す際に複雑なモデルを用いるのがよい作戦だと思います。


以下英語ですが、参考になる話がいろいろ含まれています。

https://stats.stackexchange.com/questions/279730/why-gradient-boosting-random-forest-generate-unstable-feature-importance

https://stackoverflow.com/questions/15810339/how-are-feature-importances-in-randomforestclassifier-determined

https://www.fabienplisson.com/choosing-right-features/

https://machinelearningmastery.com/feature-importance-and-feature-selection-with-xgboost-in-python/

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/02/03 08:14

    丁寧なご回答ありがとうございます、参考資料も後で読ませていただきます

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.12%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる