더미 변수의 기능 중요도


17

더미 변수로 분류 된 범주 형 변수의 기능 중요성을 얻는 방법을 이해하려고합니다. R 또는 h2o 가하는 방식으로 범주 변수를 처리하지 않는 scikit-learn을 사용하고 있습니다.

범주 형 변수를 더미 변수로 분류하면 해당 변수의 클래스마다 별도의 기능 중요도가 있습니다.

내 질문은, 더미 변수의 중요도를 단순히 범주화하여 범주 변수의 중요도 값으로 재결합하는 것이 합리적입니까?

통계 학습의 요소 368 페이지에서 :

변수 엑스 의 제곱 상대 중요도 는 분할 변수로 선택된 모든 내부 노드에 대한 제곱 개선의 합입니다.

따라서 변수가 선택된 각 노드에서 메트릭을 합산하여 중요도 값을 이미 생성 했으므로 더미 변수의 변수 중요도 값을 결합하여 범주 형 변수의 중요도를 "복구"할 수 있어야합니다. 물론 나는 그것이 정확하다고 기대하지는 않지만,이 값들은 무작위 프로세스를 통해 발견되므로 어쨌든 정확한 값입니다.

조사를 위해 다음 파이썬 코드 (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. 's와 같은보다 엄격한 접근 방식 : " 임의의 숲과 다변량 기능성 데이터 분석에 대한 응용 프로그램으로 그룹화 된 변수 중요도". Chakraborty & Pal의 Connectionist Framework에서 유용한 기능 그룹 선택 은 다중 계층 퍼셉트론의 맥락에서이 작업을 검토합니다. Gregorutti 등으로 돌아가서 그 방법론은 모든 종류의 분류 / 회귀 알고리즘에 직접 적용 할 수 있습니다. 요컨대, 우리는 훈련 중에 사용되는 각 가방 외부 샘플에서 무작위로 순열 된 버전을 사용합니다.

위에서 언급 한 것처럼 순열 테스트는 궁극적으로 휴리스틱이지만 과거에 정확하게 해결 된 것은 정규화 된 회귀 컨텍스트 내에서 더미 변수에 대한 처벌입니다. 이 질문에 대한 답은 Group-LASSO , Group-LARSGroup-Garotte 입니다. 그 작업에 관한 논문은 Yuan and Lin 's : " 그룹화 된 변수를 이용한 회귀에서의 모형 선택 및 추정 "(2006) 및 Meier et al .: " logistic regression을위한 그룹 올가미 "(2008). 이 방법론을 통해 다음과 같은 상황에서 작업 할 수 있습니다. " 각 요소는 여러 수준을 가질 수 있으며 더미 변수 그룹을 통해 표현 될 수 있습니다 "(Y & L 2006). 효과는 "1케이제이제이={1,,제이}제이pyglmnet그룹화 된 올가미 정규화 .]

대체로 개별 더미 변수에서 변수 중요도를 단순히 "추가"하는 것은 의미가 없으므로 잠재적으로 의미없는 결과를 초래할뿐만 아니라 변수 간의 연관성을 포착하지 않기 때문입니다. 즉, 그룹 처벌 방법과 순열 변수 중요도 방법은 일관성 있고 (특히 순열 ​​중요도 절차의 경우) 일반적으로 적용 가능한 프레임 워크를 제공합니다.

마지막으로 명백한 사실을 밝히려면 연속 데이터를 비우지 마십시오 . 나쁜 습관 입니다. 여기 (그리고 여기 ) 에이 문제에 대한 훌륭한 실이 있습니다 . 연속 변수의 불연속 화 후에 가짜 결과를 관찰한다는 사실 age은 놀라운 일이 아닙니다. Frank Harrell은 또한 연속 변수를 분류하여 발생하는 문제에 대해 광범위하게 작성했습니다 .


R의 랜덤 포리스트 분류에서 예측 변수 집합의 상대적 중요성을 연결 하면 R 이 질문에 직접 대답합니다. 나머지 부분이 직접적으로 관련이 없으며 링크에서 쉽게 링크를 잃을 수 있다고 생각하지 않기 때문에 해당 링크에 대한 참조를 처음으로 이동하면 기꺼이 동의합니다.
Dan

문제 없어요. 관련 편집을했습니다. 본문에서 언급했듯이 정규화 회귀 개념을 무시하지 마십시오. 정규화 접근 방식은 기능 중요도 / 순위에 대한 완벽한 대안을 제공합니다.
usεr11852는

정규화 된 회귀는이 질문에 대한 답이 아니며, 다른 질문에 대답 할 수 있습니다. 즉, 기능 중요도에 대한 대안이지만이 질문은 기능 중요도 그림 내에서 오에 기능을 단일 범주 기능으로 집계하는 것에 관한 것입니다. 실제로 질문에 실제로 대답하는 링크를 처음으로 이동해야한다고 생각합니다.
Dan

2

질문은 ~이야:

더미 변수의 중요도를 범주 변수의 중요도 값으로 간단히 합산하여 재조합하는 것이 합리적입니까?

짧은 대답 :

나는미디엄영형아르 자형이자형(엑스)=나는
(나는)2==1제이1나는2나는(V()=)
나는==1제이1나는2나는(V()=)

길고 실용적인 답변

위험이 있기 때문에 더미 변수에 대한 개별 변수 중요도 값을 간단히 합할 수 없습니다

상관 관계가 높은 다른 사람에 의한 중요한 변수의 마스킹. (368 페이지)

가능한 다중 공선 성과 같은 문제는 변수 중요도 값과 순위를 왜곡 할 수 있습니다.

실제로 다중 공선 성과 같은 문제가 변수의 중요성에 미치는 영향을 이해하는 것은 매우 흥미로운 문제입니다. 다양한 상관 관계 및 분포 조건 하에서 다중 회귀 분석에서 예측 변수의 중요성 결정 논문 은 다양한 중요도 계산을위한 다양한 방법을 설명하고 일반적인 통계적 가정을 위반하는 데이터의 성능을 비교합니다. 저자들은

다중 공선 성은 상대적인 중요도 방법의 성능에 영향을 주었지만, 다변량 비정규 성은 그렇지 않았습니다. (휘 타커 p366)


나는 당신의 두 번째 인용이 적절하다고 생각하지 않습니다. 이들은 상관 관계가 높은 변수가 아니며 동일한 변수이며 의사 결정 트리를 올바르게 구현하면 OHE가 필요하지 않지만 단일 변수로 취급합니다. 다공 선성은 OHE에 의해 인위적으로 도입됩니다.
Dan

첫 번째 요점에 관해서는 Breiman이 제안한 상대 중요도 값이 제곱 값인 것처럼 나에게 상처를줍니다. 그래서 나는 당신이 제안한 것처럼 sklearn이 먼저 제곱근을 취한다고 확신하지 않습니다. 또한, 그렇다면 먼저 값을 제곱하고 값을 더한 다음 합을 제곱하지 않아야합니까? 제곱근을 먼저 취하겠다는 당신의 제안을 이해하지 못했습니다.
Dan

@ecedavis 교과서의 의미는 무엇입니까? 당신은 링크 또는 더 완전한 인용을 제공 할 수 있습니까?
12시 06 분 24

안녕하세요, 비평가와 새로운 회원으로서의 첫 번째 공감에 감사드립니다. 귀하의 의견은 개정에서 다룰 구체적인 세부 사항을 지적하지만 답변의 전반적인 품질에 대한 귀하의 의견을 가질 수 있습니까? 이것은 나의 첫 번째 글이며 정기적 인 기고자가 될 계획입니다. 최소한 내 답변이 일반적으로 도움이되고 좋은 스타일이기를 바랍니다. 당신의 생각은 무엇입니까?
ecedavis

답변 스타일은 좋지만 일부 정보와 내용이 완전히 정확하지 않은 것 같습니다. 당신이 연결하는 논문은 다중 회귀 분석에서 예측 변수의 중요성에 관한 것이며 질문은 임의의 숲에서의 중요성에 관한 것입니다. 또한 전체 문장이 "또한 수축 (10.12.1 절) 때문에 다른 변수들이 서로 밀접하게 관련되어있는 중요한 변수를 마스킹하는 것은 문제가 훨씬 적기 때문에 인용문을 추출하는 데 문제가 있습니다." 그것은 매우 다른 의미를 가지고 있습니다.
see24
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.