ダミー変数による機能の重要性


17

ダミー変数に分解されたカテゴリー変数の機能の重要性をどのように取得できるかを理解しようとしています。Rまたはh2oのようにカテゴリ変数を処理しないscikit-learnを使用しています。

カテゴリ変数をダミー変数に分解すると、その変数のクラスごとに個別の機能の重要性が得られます。

私の質問は、それらを単純に合計することによって、それらのダミー変数の重要度をカテゴリー変数の重要度値に再結合することは理にかなっていますか?

統計学習の要素の368ページから:

変数相対的な重要度の2乗は、それが分割変数として選択されたすべての内部ノードに対する改善の2乗の合計です。バツ

これにより、変数が選択された各ノードでメトリックを合計することで重要度値がすでに作成されているため、ダミー変数の変数重要度値を組み合わせてカテゴリ変数の重要度を「回復」できるはずです。もちろん、正確に正しいとは思いませんが、これらの値はランダムなプロセスで検出されるため、とにかく本当に正確な値です。

調査として、次のPythonコード(jupyterで)を作成しました。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import animation, rc
from sklearn.datasets import load_diabetes
from sklearn.ensemble import RandomForestClassifier
import re

#%matplotlib inline
from IPython.display import HTML
from IPython.display import set_matplotlib_formats

plt.rcParams['figure.autolayout'] = False
plt.rcParams['figure.figsize'] = 10, 6
plt.rcParams['axes.labelsize'] = 18
plt.rcParams['axes.titlesize'] = 20
plt.rcParams['font.size'] = 14
plt.rcParams['lines.linewidth'] = 2.0
plt.rcParams['lines.markersize'] = 8
plt.rcParams['legend.fontsize'] = 14

# Get some data, I could not easily find a free data set with actual categorical variables, so I just created some from continuous variables
data = load_diabetes()
df = pd.DataFrame(data.data, columns=[data.feature_names])
df = df.assign(target=pd.Series(data.target))

# Functions to plot the variable importances
def autolabel(rects, ax):
    """
    Attach a text label above each bar displaying its height
    """
    for rect in rects:
        height = rect.get_height()
        ax.text(rect.get_x() + rect.get_width()/2.,
                1.05*height,
                f'{round(height,3)}',
                ha='center',
                va='bottom')

def plot_feature_importance(X,y,dummy_prefixes=None, ax=None, feats_to_highlight=None):

    # Find the feature importances by fitting a random forest
    forest = RandomForestClassifier(n_estimators=100)
    forest.fit(X,y)
    importances_dummy = forest.feature_importances_

    # If there are specified dummy variables, combing them into a single categorical 
    # variable by summing the importances. This code assumes the dummy variables were
    # created using pandas get_dummies() method names the dummy variables as
    # featurename_categoryvalue
    if dummy_prefixes is None:
        importances_categorical = importances_dummy
        labels = X.columns
    else:
        dummy_idx = np.repeat(False,len(X.columns))
        importances_categorical = []
        labels = []

        for feat in dummy_prefixes:
            feat_idx = np.array([re.match(f'^{feat}_', col) is not None for col in X.columns])
            importances_categorical = np.append(importances_categorical,
                                                sum(importances_dummy[feat_idx]))
            labels = np.append(labels,feat)
            dummy_idx = dummy_idx | feat_idx
        importances_categorical = np.concatenate((importances_dummy[~dummy_idx],
                                                  importances_categorical))
        labels = np.concatenate((X.columns[~dummy_idx], labels))

    importances_categorical /= max(importances_categorical)
    indices = np.argsort(importances_categorical)[::-1]

    # Plotting

    if ax is None:
        fig, ax = plt.subplots()

    plt.title("Feature importances")
    rects = ax.bar(range(len(importances_categorical)),
                   importances_categorical[indices],
                   tick_label=labels[indices],
                   align="center")
    autolabel(rects, ax)

    if feats_to_highlight is not None:
        highlight = [feat in feats_to_highlight for feat in labels[indices]]
        rects2 = ax.bar(range(len(importances_categorical)),
                       importances_categorical[indices]*highlight,
                       tick_label=labels[indices],
                       color='r',
                       align="center")
        rects = [rects,rects2]
    plt.xlim([-0.6, len(importances_categorical)-0.4])
    ax.set_ylim((0, 1.125))
    return rects

# Create importance plots leaving everything as categorical variables. I'm highlighting bmi and age as I will convert those into categorical variables later
X = df.drop('target',axis=1)
y = df['target'] > 140.5

plot_feature_importance(X,y, feats_to_highlight=['bmi', 'age'])
plt.title('Feature importance with bmi and age left as continuous variables')

#Create an animation of what happens to variable importance when I split bmi and age into n (n equals 2 - 25) different classes
# %%capture

fig, ax = plt.subplots()

def animate(i):
    ax.clear()

    # Split one of the continuous variables up into a categorical variable with i balanced classes
    X_test = X.copy()
    n_categories = i+2
    X_test['bmi'] = pd.cut(X_test['bmi'],
                           np.percentile(X['bmi'], np.linspace(0,100,n_categories+1)),
                           labels=[chr(num+65) for num in range(n_categories)])
    X_test['age'] = pd.cut(X_test['age'],
                           np.percentile(X['age'], np.linspace(0,100,n_categories+1)),
                           labels=[chr(num+65) for num in range(n_categories)])
    X_test = pd.get_dummies(X_test, drop_first=True)

    # Plot the feature importances
    rects = plot_feature_importance(X_test,y,dummy_prefixes=['bmi', 'age'],ax=ax, feats_to_highlight=['bmi', 'age'])
    plt.title(f'Feature importances for {n_categories} bmi and age categories')
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    ax.spines['bottom'].set_visible(False)
    ax.spines['left'].set_visible(False)

    return [rects,]

anim = animation.FuncAnimation(fig, animate, frames=24, interval=1000)

HTML(anim.to_html5_video())

結果の一部を次に示します。

ここに画像の説明を入力してください

ここに画像の説明を入力してください

変数の重要度はほとんどの場合カテゴリの数に依存しているため、これらのチャートの一般的な有用性を疑問視することができます。特に、age その連続した対応物よりもはるかに高い値に到達することの重要性。

最後に、ダミー変数(bmiのみ)のままにした場合の例:

# Split one of the continuous variables up into a categorical variable with i balanced classes
X_test = X.copy()
n_categories = 5
X_test['bmi'] = pd.cut(X_test['bmi'],
                       np.percentile(X['bmi'], np.linspace(0,100,n_categories+1)),
                       labels=[chr(num+65) for num in range(n_categories)])
X_test = pd.get_dummies(X_test, drop_first=True)

# Plot the feature importances
rects = plot_feature_importance(X_test,y, feats_to_highlight=['bmi_B','bmi_C','bmi_D', 'bmi_E'])
plt.title(f"Feature importances for {n_categories} bmi categories")

ここに画像の説明を入力してください

回答:


8

一般に「機能の重要性」に取り組むとき、ほとんどの場合、正則化アプローチが多くの場合良い代替手段であることを覚えておくと役立ちます。目前の問題に対して自動的に「最も重要な機能を選択」します。さて、正則化の概念(通常は回帰のコンテキスト内)に従わない場合、ランダムフォレスト分類器と置換テストの概念は、変数グループの重要性を特徴付ける解決策を自然に貸し出します。これは、ここ数年前に「Rのランダムフォレスト分類における一連の予測変数の相対的重要性」について実際に尋ねられました。Gregorutti et al。のような、より厳密なアプローチ:「ランダムなフォレストと多変量機能データ分析への応用によるグループ化された変数の重要性「。コネクショニストフレームワークでのチャクラボルティとパルの有用な機能グループ選択は、多層パーセプトロンのコンテキスト内でこのタスクを調査します。要するに、トレーニング中に使用される各out-of-bagsサンプルでランダムに並べ替えられたバージョンを使用します。

上記で述べたように、置換テストは最終的にはヒューリスティックですが、過去に正確に解決されたのは、正規化された回帰のコンテキスト内でのダミー変数のペナルティです。その質問に対する答えは、Group-LASSOGroup-LARS、およびGroup-Garotteです。その研究における独創的な論文は、Yuan and Lin's: " グループ化された変数を用いた回帰におけるモデル選択と推定 "(2006)およびMeier et al。's: " ロジスティック回帰のグループ投げ縄 "(2008)です。この方法により、「各要因には複数のレベルがあり、ダミー変数のグループを通じて表現できる」状況で作業することができます(Y&L 2006)。効果は次のとおりですグループ投げ縄は、因子レベルでスパース性を促進します。「(Y&L 2006)。過度の細部に行かなくて基本的な考え方は、標準ということですペナルティが正定値行列のノルムに置き換えられ、あります私たちが調べグループの数CVは、グループのLassoに関するいくつかの良いスレッドを持っている。ここにここここにあなたがこれをさらにを追求したい場合は、[我々は、特にPythonのに言及ので:。私は、Pythonの使用していないパッケージを含まれるように表示されるグループ化された投げ縄を正則化。]K j j = { 1 J } Jl1Kjj={1J}Jpyglmnet

全体として、個々のダミー変数から変数の重要度を単純に「加算」することは意味がありません。なぜなら、それらの間の関連付けをキャプチャせず、潜在的に無意味な結果をもたらすからです。ただし、グループペナルティ化されたメソッドと置換変数重要度メソッドの両方が、一貫性のある(特に置換重要度手順の場合)一般的に適用可能なフレームワークを提供します。

最後に、明らかなことを述べます連続データをビンにしないでください。これは悪い習慣です。この問題に関するすばらしいスレッドがここ(およびここ)にあります。のような連続変数の離散化後に偽の結果が観察されるという事実ageは驚くことではありません。フランクハレルは連続変数を分類することによって引き起こされる問題についても広範囲に書いた。


Rのランダムフォレスト分類の一連の予測変数の相対的な重要度をリンクすると、質問に直接答えます。そのリンクへの参照を最初に移動すると、残りは直接関連しているとは思わず、リンクが答えで簡単に失われる可能性があるため、喜んで受け入れます。
ダン

問題ない。関連する編集をいくつか行いました。本文で述べたように、正則化アプローチは機能の重要性/ランク付けに完全に有効な代替手段を提供します。
usεr11852は回復モニック言う

正規化回帰はこの質問に対する答えではありません。別の質問、つまり機能の重要度の代替案に答えることができますが、この質問は機能の重要度プロット内の単一のカテゴリ機能への機能の集約に関するものです。実際に質問に答えるリンクを最初に移動する必要があると思います。
ダン

2

質問は:

それらを単純に合計することにより、それらのダミー変数の重要度をカテゴリー変数の重要度値に再結合することは理にかなっていますか?

短い答え:

mportanceバツl=
2=t=1J12vt=
=t=1J12vt=

より長く、より実用的な答え。

ダミー変数の個々の変数重要度値を単純に合計することはできません

重要な変数が高度に相関している他者によるマスキング。(368ページ)

多重共線性などの問題により、変数の重要度の値とランキングが歪む可能性があります。

実際、変数の重要性が多重共線性などの問題によってどのように影響を受けるかを理解することは非常に興味深い問題です。さまざまな相関および分布条件の下での多重回帰における予測子の重要度の決定に関する論文では、変数の重要度を計算するさまざまな方法について説明し、典型的な統計的仮定に違反するデータのパフォーマンスを比較しています。著者はそれを発見した

多重共線性は相対重要度法のパフォーマンスに影響しましたが、多変量非正規性は影響しませんでした。(ウィッテイカーp366)


2回目の引用は意味がないと思います。これらは高度に相関した変数ではなく、同じ変数であり、決定木の適切な実装にはOHEは必要ありませんが、これらを単一の変数として扱います。どちらかといえば、多重共直線性はOHEによって人為的に導入されます。
ダン

最初の点に関しては、Breimanが提案した相対的な重要度の数値が2乗値であるように思えます。だから、あなたが提案したように、sklearnが最初に平方根を取るとは思いません。また、それらの場合、最初に値を二乗し、それらを加算してから合計を平方根化するべきではありませんか?最初に平方根を取るというあなたの提案を理解したかどうかはわかりません。
ダン

@ecedavis教科書はどういう意味ですか?リンクまたはより完全な引用を提供してください。
18

こんにちは、批評と新しいメンバーとしての私の最初の賛成に感謝します。あなたのコメントは、私の改訂で対処する特定の詳細を指摘していますが、回答の全体的な品質についてもあなたの意見を持っているでしょうか?これは私の最初の投稿であり、定期的に寄稿者になることを計画しています。少なくとも、私の答えが一般に役立つものであり、良いスタイルであることを願っています。あなたの考えは何ですか?
エセダヴィス

回答のスタイルは良いのですが、情報やコンテンツの一部が完全に正しいとは思えません。リンクする論文は重回帰における予測因子の重要性に関するものであり、質問はランダムフォレストにおける重要性に関するものです。また、完全な文は「収縮(10.12.1)のため、重要な変数が高度に相関している他者によるマスキングも問題ではない」ため、引用の抽出には問題があると思います。それは非常に異なる意味を持っています。
18
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.