Важливе значення має фіктивні змінні


18

Я намагаюся зрозуміти, як я можу отримати важливість функції категоричної змінної, яка була розбита на фіктивні змінні. Я використовую scikit-learn, який не обробляє для вас категоричні змінні, як це роблять R або h2o.

Якщо я розбиваю категоричну змінну вниз на манекенні змінні, я отримую окремі імпорти функцій для класу в цій змінній.

Моє запитання: чи є сенс рекомбінувати ці імпортні змінні змінних у важливе значення для категоричної змінної, просто підсумовуючи їх?

З сторінки 368 Елементи статистичного навчання:

Х

Це змушує мене думати, що оскільки значення важливості вже створюється шляхом підсумовування метрики на кожному вузлі, вибрана змінна, я повинен мати можливість поєднувати значення значущості значень фіктивних змінних, щоб "відновити" значення для категоріальної змінної. Звичайно, я не сподіваюсь, що це буде абсолютно правильне, але все-таки ці значення є дійсно точними значеннями, оскільки вони виявляються випадковим процесом.

Я написав наступний код 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 " кілька років тому. Більш жорсткі підходи, такі як Грегорутті та ін.: " Згрупована змінна важливість із випадковими лісами та застосування для багатофакторного аналізу функціональних данихВибір корисних груп функцій Chakraborty & Pal в рамках Connectionist Framework розглядає це завдання в контексті багатошарового перцептора. Повертаючись до статті Gregorutti et al., Їх методологія безпосередньо застосовується до будь-якого алгоритму класифікації / регресії. Коротше кажучи, ми використовуємо випадкову перестановлену версію у кожному зразку поза сумками, який використовується під час тренувань.

Стверджуючи вищесказане, хоча тести на перестановку в кінцевому підсумку є евристичними, то, що в минулому було точно вирішено, - це покарання фіктивних змінних в контексті регульованої регресії. Відповідь на це питання - Group-LASSO , Group-LARS та Group-Garotte . Семінарними роботами в цій роботі є Юан та Лін: " Вибір моделі та оцінка в регресії з групованими змінними " (2006) та Meier et al.: " Груповий ласо для логістичної регресії " (2008). Ця методологія дозволяє нам працювати в ситуації, коли: " кожен фактор може мати декілька рівнів і може бути виражений через групу фіктивних змінних " (Y&L 2006). Ефект такий, що "л1Кjj={1,,J}Jpyglmnetзгрупована регуляризація ласо .]

Загалом, загалом, не має сенсу просто "додавати" змінну важливість з окремих фіктивних змінних, оскільки це не може охопити зв'язок між ними, а також призвести до потенційно безглуздих результатів. З огляду на це, як групові пеналізовані методи, так і методи перемінної важливості перестановки дають цілісну і (особливо у випадку процедур важливості перестановки) загальноприйнятну основу для цього.

Наостанок констатуємо очевидне: не бінь безперервних даних . Це погана практика, туттут ) є чудова нитка з цього питання . Той факт, що ми спостерігаємо помилкові результати після дискретизації суцільної змінної, як age, не дивно. Френк Харрелл також написав обширну інформацію про проблеми, викликані категоризацією безперервних змінних .


Ви пов'язуєте Відносна важливість набору предикторів у випадковій класифікації лісів в R відповідає безпосередньо на питання. Буду радий прийняти, якщо ви перенесите посилання на це посилання на початок, оскільки я не думаю, що решта є настільки безпосередньо актуальною, і посилання легко загубиться у відповіді.
Дан

Без проблем. Я вніс деякі відповідні зміни. Не відкидайте концепцію регульованої регресії, як я вже згадував у тексті, підходи до регуляризації пропонують цілком справедливу альтернативу важливості / ранжируванню.
usεr11852 повідомляє Відновити Монік

Регульована регресія не є відповіддю на це питання, вона може відповісти на інше запитання, тобто альтернативи важливості ознак, але це питання про об'єднання ознак в одну категоричну ознаку в межах сюжетного значення. Я дійсно думаю, що вам слід перенести посилання, яке насправді відповідає на питання до початку.
Дан

2

Питання:

чи є сенс рекомбінувати ці імпортні змінні змінних у значення важливості для категоричної змінної, просто підсумовуючи їх?

Коротка відповідь:

Ямpоrтанcе(Хл)=Я
(Я)2=т=1J-1i2Я(v(т)=)
Я=т=1J-1i2Я(v(т)=)
На закінчення потрібно спочатку взяти квадратний корінь.

Більш довга, практична відповідь ..

Ви не можете просто підсумовувати окремі значення важливих змінних для фіктивних змінних, оскільки ви ризикуєте

маскування важливих змінних іншими, з якими вони дуже корелюються. (стор. 368)

Такі питання, як можлива мультиколінеарність, можуть спотворювати різні значення важливості та рейтинги.

Насправді дуже цікава проблема зрозуміти, наскільки змінна важливість впливає на такі питання, як мультиколінеарність. У статті, що визначає важливість прогноктора в множинній регресії в різних варіантах кореляційних та розподільних умов, розглядаються різні методи обчислення змінної важливості та порівнюється продуктивність для даних, що порушують типові статистичні припущення. Автори виявили це

Хоча мультиколінеарність впливала на ефективність методів відносної важливості, багатовимірність ненормальності не зробила. (WHITTAKER p366)


Я не думаю, що ваша друга пропозиція є доречною. Це не дуже корельовані змінні, вони є однаковою змінною, і для гарної реалізації дерева рішень не потрібно ОГЕ, але трактувати їх як єдину змінну. Якщо що-небудь, то мультиколінарність штучно запроваджується OHE.
Dan

Що стосується Вашого першого пункту, то мені здається, що відносне значення важливості, запропоноване Брейманом, - це значення у квадраті. Тож я не переконаний, що склеарн спочатку бере корінне коріння, як ви запропонували. Крім того, якщо вони є, я не повинен спершу порівнювати значення, додавати їх, а потім укручувати суму? Я не впевнений, що я зрозумів вашу пропозицію спочатку взяти квадратний корінь.
Dan

@ecedavis Що ви розумієте під підручником? Чи можете ви надати посилання або більш повне цитування, будь ласка.
див24 24

Привіт, дякую за критику та за моє перше подання заявки на посаду нового члена. Ваші коментарі вказують на конкретні деталі, до яких я звертатимусь у своїй редакції, але чи можу я також мати вашу думку щодо загальної якості моєї відповіді? Це моя перша посада, і я планую стати постійним дописом. Як мінімум, я сподіваюся, що моя відповідь, як правило, корисна і в хорошому стилі. Які ваші думки?
ecedavis

Стиль вашої відповіді хороший, але частина інформації та вмісту здаються не зовсім коректними. Документ, на який ви посилаєтесь, стосується важливості прогнозів при множинній регресії, тоді як питання про важливість у випадковому Лісі. Я також вважаю, що ваше вилучення цитати є проблематичним, оскільки повне речення є "Крім того, через усадку (Розділ 10.12.1) маскування важливих змінних іншими, з якими вони сильно співвідносяться, є набагато меншою проблемою". що має зовсім інше значення.
див2424
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.