最近よく使用しているXgboostのfeature_importanceについてまとめます。
Qiita初投稿なので見にくさや誤り等ご容赦ください。
#決定木(Decision Tree)・回帰木(Regerssion Tree/CART)
決定木や回帰木は、データセットのジニ係数やエントロピーを最も改善させることのできる変数とその閾値を見つけ、それらをもとに枝分かれさせる、という操作を繰り返すことによって木が生成されていく。
#Tree Ensenble Model
RandomForestやXgboost、LightGBMをはじめとするTree Ensenble Modelは、これらの木を多数作成し、その重み付き多数決や加重平均によって予測値を算出するが、それぞれのアルゴリズムにはその木の作成手順(逐次的or並列的・評価基準・変数決定 など)において様々な工夫が施されている。
たとえばデフォルトのXgboostは以下のようなものがあげられる。
- 木の生成 : ブースティング(逐次的な生成)
- 評価基準 : ジニ係数と正則化項との和
- 変数決定 : histogram-based(変数を定められた数に量子化し、ビンごとに閾値として探索する)の貪欲法
- 重みづけ : 二次近似を行うニュートン法によって最適化
Xgboost の Feature_importance
Tree Ensenble Modelはkaggleなどのコンペで多くの参加者に好まれているが、これらを使う利点としてはその強い予測性能に加え、変数重要度を容易に可視化できる点も大きい。
実際、僕も変数を選択する際、Xgboostのplot_importance_にかなり依存しているため、この重要度の算出にについてちゃんと理解しておく必要がある。
しかし日本語での記事が見当たらないため、Xgboostのドキュメントを読んで理解したので、メモ書き程度だがまとめてみたい。
Xgboostドキュメント(Python)
importance type
Xgboostには変数重要度(=feature_importance)の指標として以下3つ用意されていた。
- weight
- gain
- cover
weight
デフォルトではこのweightが用いられる。
weightは「生成された全ての木の中にその変数がいくつ分岐として存在するか」である。
ポイントとなるのはあくまで「存在する個数」しか見ていないという点。
どれだけ予測に近づける分岐をしているかや、入力に対してどれだけ分岐に使用されるのかという情報はここにはない。
gain
gainとは評価基準をどれだけ改善させたることができる(できた)のかという値である。
各分岐においてこれが最大となる変数とその閾値を見つけるのがTree based Modelであるが、最終的に完成されたモデルにおいて、その変数が平均的にどれだけgainを与えたのかという指標が"gain"というimportance_typeである。
たとえばmax_depth:3・n_estimator:100であればモデル全体で分岐が合計700回起こるので、変数Xがgain=10で10回分岐に採用されたのであれば、Xのfeature_importanceは、100/7000=0.143となる。
cover
coverという値は以下のように定義されている。Xgboost(R ver)
the sum of second order gradient of training data classified to the leaf, if it is square loss, this simply corresponds to the number of instances in that branch. Deeper in the tree a node is, lower this metric will be
そのまま訳すと、「coverとは葉に分類された訓練データの二次勾配の合計値である。誤差関数が二乗誤差であれば単純に分類に登場した回数に対応する。木の中で深い位置にあるほどこの指標は小さくなる。」
一方で、importance_typeの欄に、
“cover” is the average coverage of splits which use the feature
とある。わかりにくいがおそらくこの文に登場するcoverageという値が先の引用でのcoverにあたり、その平均値を変数重要度として用いたのが、"cover"というimportance_typeなのであろう。分類問題における"cover"を理解するには誤差関数の二次勾配について知っておく必要があるが、回帰問題の時にはとても直観的で「一つの入力が何度この変数によって分岐されるか」の平均がfeature_importanceとなる。
##追記 (@Koutaru さんのご指摘をうけて)
デフォルトがgainに変わったそうです。
また、平均ではなく合計をとったtotal_gain,total_coverもできたそうです。
まとめ
- weight : その変数が全ての木の中にいくつ分岐点として存在するか
- gain : その変数が平均的にどれぐらい評価基準を改善しているのか(全分岐点についての平均)
- cover : (回帰問題では)
ある入力に対して平均的に何度分岐に用いられているか(全入力についての平均)
*平均の意味が微妙に異なる点に注意が必要。
以上、大雑把ですがXgboostの変数重要度に関するまとめでした。
直観的にはgainやcoverが本質的な重要度な気がするのですが、なぜweightがデフォルトなのかとても気になります。
その点についても調査できれば今後記事にしたいと思います。