web-dev-qa-db-ja.com

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

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

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

109
user2244670

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

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

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

(どちらのアルゴリズムもrandomForest Rパッケージで利用できることに注意してください。)

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

137
Gilles Louppe

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

  1. サイズfeature_importancesですべてゼロの配列n_featuresを初期化します。

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

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

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

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

52

これは、トレーニングセット内のサンプルの総数に対する、アンサンブルのツリーのいずれかのフィーチャを含む決定ノードにルーティングされるサンプルの数の比率です。

決定木の最上位ノードに含まれる特徴は、より多くのサンプルを見る傾向があるため、より重要性が高い可能性があります。

編集:この説明は部分的にのみ正しい:GillesとPeterの答えは正しい答えです。

11
ogrisel

@GillesLouppeが上記で指摘したように、scikit-learnは現在、機能の重要性に関する「平均不純物の減少」メトリックを実装しています。個人的には、2番目のメトリックが少しおもしろいと思います。各フィーチャの値を1つずつランダムに並べ替えて、アウトオブバッグのパフォーマンスがどれほど悪いかを確認します。

機能の重要性を追求するのは、各機能がモデル全体の予測パフォーマンスにどれだけ貢献するかであるため、2番目のメトリックは実際にこれを直接測定しますが、「平均不純物の減少」は単なる適切なプロキシです。

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

https://github.com/pjh2011/rf_perm_feat_import

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

10
Peter

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

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

decision_treeプロット:
ここに画像の説明を入力
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
tengfei li

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

RandomForestClassifierでは、estimators_属性はDecisionTreeClassifierのリストです( documentation で説明されています)。 RandomForestClassifierのfeature_importances_を計算するために、 scikit-learnのソースコード で、アンサンブルのすべてのエスティメータ(すべてのDecisionTreeClassifer)のfeature_importances_属性の平均を計算します。

DecisionTreeClassiferの documentation では、「機能の重要度は、その機能によってもたらされる基準の(正規化された)合計削減として計算されます。Gini重要度[1]としても知られています。 」

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

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

0
Makan