RandomForestClassifierのfeature_importancesはどのように決定されますか?


125

データ入力として時系列を使用した分類タスクがあり、各属性(n = 23)は特定の時点を表します。絶対的な分類結果に加えて、どの属性/日付が結果にどの程度貢献しているのかを知りたいです。したがって、私はを使用feature_importances_しています。

ただし、それらがどのように計算され、どのメジャー/アルゴリズムが使用されているかを知りたいです。残念ながら、このトピックに関するドキュメントは見つかりませんでした。


10
1つのSOスレッドで3つのコア開発者がすごい。それはなんらかの記録になるはずです^^
Andreas Mueller

回答:


158

実際、機能の「重要性」を取得するにはいくつかの方法があります。多くの場合、この単語の意味については厳密な合意はありません。

scikit-learnでは、[1]で説明されているように重要性を実装します(よく引用されますが、残念ながらめったに読まれません...)。これは「ジニ重要度」または「平均減少不純物」と呼ばれることもあり、すべてのノードで平均されたノード不純物の合計減少(そのノードに達する確率(そのノードに達するサンプルの割合で概算される)で重み付け)として定義されます。アンサンブルの木。

文献や他のいくつかのパッケージでは、「平均減少精度」として実装された機能の重要性を見つけることもできます。基本的には、その機能の値をランダムに並べ替えたときのOOBデータの精度の低下を測定するという考え方です。減少が少ない場合、機能は重要ではなく、その逆も同様です。

(両方のアルゴリズムがrandomForest Rパッケージで利用可能であることに注意してください。)

[1]:ブライマン、フリードマン、「分類と回帰木」、1984年。


48
この回答が重要度の属性/例のドキュメントで言及されていれば、すばらしいでしょう。しばらくの間も探していました:)
d1337

2
重要度のスコアは相対的な値のようですか?たとえば、すべての機能の重要度スコアの合計は常に1です(ここの例scikit-learn.org/stable/auto_examples/ensemble/…を参照)
RNA

5
@RNA:はい、デフォルトで変数の重要度はscikit-learnで正規化され、合計が1になるようにします。これを回避するには、個々の基本推定値をループしてを呼び出しtree_.compute_feature_importances(normalize=False)ます。
Gilles Louppe、2014

2
@GillesLouppeアウトオブバッグサンプルを使用して、各ツリーの決定木のリグレッサのフォレストのMSEの減少を測定しますか?またはツリーで使用されるすべてのトレーニングデータ?
コークス

1
2つの役立つリソース。(1)blog.datadive.net/…Ando Saabasによるブログは、Gillesが述べたように、「平均の不純さ」と「平均の精度の低下」の両方を実装しています。(2)Gilles Louppeの論文をダウンロードして読んでください。
マークティーズ2018

54

単一ツリーの機能重要度値を計算する通常の方法は次のとおりです。

  1. feature_importancesすべてゼロの配列をsizeで初期化しますn_features

  2. ツリーをトラバースします。機能を分割する各内部ノードについてi、そのノードのエラー削減にノードにルーティングされたサンプル数を掛けて計算し、この量をに追加しfeature_importances[i]ます。

エラー削減は、使用する不純な基準(Gini、Entropy、MSEなど)によって異なります。内部ノードにルーティングされる一連の例の不純物から、分割によって作成された2つのパーティションの不純物の合計を差し引いたもの。

これらの値が特定のデータセット(エラー削減とサンプル数の両方がデータセット固有)に関連していることが重要なので、これらの値を異なるデータセット間で比較することはできません。

私の知る限り、決定木で機能の重要度の値を計算する別の方法があります。上記の方法の簡単な説明は、Trevor Hastie、Robert Tibshirani、Jerome Friedmanによる「統計学習の要素」にあります。


12

これは、学習セット内のサンプルの総数に対する、集団の任意のツリーでその機能を含む決定ノードにルーティングされたサンプルの数の間の比率です。

デシジョンツリーの最上位ノードに含まれる機能は、より多くのサンプルを参照する傾向があるため、より重要度が高くなる可能性があります。

編集:この説明は部分的にしか正しくありません。ジルとピーターの答えは正しい答えです。


1
正確な方法について紙/文書があるかどうか知っていますか?例えば。ブライマン、2001年。方法論について引用できる適切な文書があれば、すばらしいでしょう。
user2244670 2013

@ogriselあなたの応答を「重み付け」の説明として明確にマークできれば素晴らしいでしょう。重み付けだけでは、機能の重要度は決まりません。「不純物メトリック」(「gini-importance」またはRSS)と重みを組み合わせ、ツリー全体で平均すると、機能全体の重要度が決まります。残念ながらscikit-learnのドキュメント:scikit-learn.org/stable/modules/…は正確ではなく、不正確なメトリックとして「深さ」について誤って言及しています。
アリエル

11

@GillesLouppeが上記で指摘したように、scikit-learnは現在、機能の重要度に対して「平均不純化」メトリックを実装しています。私は個人的に、2つ目の指標をもう少し興味深いと思います。この場合、各機能の値を1つずつランダムに並べ替え、out-of-bagのパフォーマンスがどれほど悪いかを確認します。

機能の重要性は、各機能がモデル全体の予測パフォーマンスにどの程度貢献するかということなので、2番目の指標は実際にこれを直接測定するものですが、「平均減少不純物」は単なる適切なプロキシです。

興味があれば、置換重要度メトリックを実装し、scikit-learnランダムフォレストクラスのインスタンスから値を計算するために使用できる小さなパッケージを作成しました。

https://github.com/pjh2011/rf_perm_feat_import

編集:これは3ではなくPython 2.7で機能します


こんにちは@Peterコードを使用すると、次のエラーが発生します。NameError:名前 'xrange'が定義されていません。
Aizzaac 2017年

こんにちは@Aizzaac。申し訳ありませんが、パッケージを作成するのは初めてなので、Python 2.7用に作成したことに注意してください。def xrange(x)を試してください:実行する前にiter(range(x))を返します
Peter

2

質問に答えてみましょう。コード:

iris = datasets.load_iris()  
X = iris.data  
y = iris.target  
clf = DecisionTreeClassifier()  
clf.fit(X, y)  

Decision_tree plot:
ここに画像の説明を入力してください
compute_feature_importance:[0。、0.01333333,0.06405596,0.92261071]
ソースコードを確認:

cpdef compute_feature_importances(self, normalize=True):
    """Computes the importance of each feature (aka variable)."""
    cdef Node* left
    cdef Node* right
    cdef Node* nodes = self.nodes
    cdef Node* node = nodes
    cdef Node* end_node = node + self.node_count

    cdef double normalizer = 0.

    cdef np.ndarray[np.float64_t, ndim=1] importances
    importances = np.zeros((self.n_features,))
    cdef DOUBLE_t* importance_data = <DOUBLE_t*>importances.data

    with nogil:
        while node != end_node:
            if node.left_child != _TREE_LEAF:
                # ... and node.right_child != _TREE_LEAF:
                left = &nodes[node.left_child]
                right = &nodes[node.right_child]

                importance_data[node.feature] += (
                    node.weighted_n_node_samples * node.impurity -
                    left.weighted_n_node_samples * left.impurity -
                    right.weighted_n_node_samples * right.impurity)
            node += 1

    importances /= nodes[0].weighted_n_node_samples

    if normalize:
        normalizer = np.sum(importances)

        if normalizer > 0.0:
            # Avoid dividing by zero (e.g., when root is pure)
            importances /= normalizer

    return importances

機能の重要度を計算してみてください:

print("sepal length (cm)",0)
print("sepal width (cm)",(3*0.444-(0+0)))
print("petal length (cm)",(54* 0.168 - (48*0.041+6*0.444)) +(46*0.043 -(0+3*0.444)) + (3*0.444-(0+0)))
print("petal width (cm)",(150* 0.667 - (0+100*0.5)) +(100*0.5-(54*0.168+46*0.043))+(6*0.444 -(0+3*0.444)) + (48*0.041-(0+0)))

feature_importance:np.array([0,1.332,6.418,92.30])を取得します。
正規化した後、配列([0.、0.01331334、0.06414793、0.92253873])を取得できますclf.feature_importances_。これはと同じです。
すべてのクラスが1つの重みを持つことになっていることに注意してください。


1

このトピックに関するscikit-learnのドキュメントへの参照、または@GillesLouppeによる回答への参照を探している人のために:

RandomForestClassifierでは、estimators_attributeはDecisionTreeClassifierのリストです(ドキュメントで説明されています)。feature_importances_RandomForestClassifierのを計算するために、scikit-learnのソースコードfeature_importances_は、アンサンブル内のすべての推定器(すべてのDecisionTreeClassifer)の属性を平均します。

DecisionTreeClassiferのドキュメントでは、「機能の重要性は、その機能によってもたらされる基準の(正規化された)総削減量として計算されます。Giniの重要性[1]とも呼ばれます。」

以下は、scikit-learnのリファレンスで提供されている、変数とGiniの重要性に関する詳細情報への直接リンクです。

[1] L.ブライマン、およびA.カトラー、「ランダムフォレスト」、http: //www.stat.berkeley.edu/~breiman/RandomForests/cc_home.htm

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.