Fitur penting dengan variabel dummy


17

Saya mencoba memahami bagaimana saya bisa mendapatkan fitur penting dari variabel kategori yang telah dipecah menjadi variabel dummy. Saya menggunakan scikit-learn yang tidak menangani variabel kategorikal untuk Anda seperti R atau h2o.

Jika saya memecah variabel kategori menjadi variabel dummy, saya mendapatkan fitur penting terpisah per kelas dalam variabel itu.

Pertanyaan saya adalah, apakah masuk akal untuk menggabungkan kembali variabel dummy yang penting menjadi nilai penting untuk variabel kategori dengan hanya menjumlahkannya?

Dari halaman 368 dari The Elements of Statistics Learning:

Kepentingan relatif kuadrat dari variabel X adalah jumlah dari peningkatan kuadrat tersebut atas semua node internal yang dipilih sebagai variabel pemisahan

Ini membuat saya berpikir bahwa karena nilai pentingnya sudah dibuat dengan menjumlahkan metrik pada setiap node variabel dipilih, saya harus dapat menggabungkan nilai-nilai penting variabel dari variabel dummy untuk "memulihkan" kepentingan untuk variabel kategori. Tentu saja saya tidak berharap itu benar, tetapi nilai-nilai ini benar-benar nilai yang pasti karena mereka ditemukan melalui proses acak.

Saya telah menulis kode python berikut (dalam jupyter) sebagai investigasi:

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())

Berikut ini beberapa hasilnya:

masukkan deskripsi gambar di sini

masukkan deskripsi gambar di sini

Kita dapat mengamati bahwa kepentingan variabel sebagian besar tergantung pada jumlah kategori, yang membuat saya mempertanyakan kegunaan grafik ini secara umum. Terutama pentingnya age mencapai nilai yang jauh lebih tinggi daripada rekannya yang berkelanjutan.

Dan akhirnya, sebuah contoh jika saya membiarkan mereka sebagai variabel dummy (hanya 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")

masukkan deskripsi gambar di sini

Jawaban:


8

Ketika mengerjakan "fitur penting" secara umum, akan sangat membantu untuk mengingat bahwa dalam kebanyakan kasus, pendekatan regularisasi seringkali merupakan alternatif yang baik. Secara otomatis akan "memilih fitur yang paling penting" untuk masalah yang dihadapi. Sekarang, jika kita tidak ingin mengikuti gagasan untuk regularisasi (biasanya dalam konteks regresi), pengklasifikasi hutan acak dan gagasan tes permutasi secara alami memberikan solusi untuk menonjolkan pentingnya kelompok variabel. Ini sebenarnya telah ditanyakan sebelumnya di sini: " Kepentingan relatif dari serangkaian prediktor dalam klasifikasi hutan acak di R " beberapa tahun yang lalu. Pendekatan yang lebih ketat seperti Gregorutti et al.: " Kepentingan variabel yang dikelompokkan dengan hutan acak dan aplikasi untuk analisis data fungsional multivarian". Chakraborty & Pal's Memilih Grup Fitur yang Berguna dalam Kerangka Connectionist melihat ke dalam tugas ini dalam konteks Multi-Layer Perceptron. Kembali ke makalah Gregorutti dkk. Metodologi mereka secara langsung berlaku untuk segala jenis klasifikasi / algoritma regresi Singkatnya, kami menggunakan versi yang diijinkan secara acak dalam setiap sampel tas yang digunakan selama pelatihan.

" (2008). Metodologi ini memungkinkan kita untuk bekerja dalam situasi di mana: " setiap faktor dapat memiliki beberapa level dan dapat diekspresikan melalui sekelompok variabel dummy " (Y&L 2006). Efeknya sedemikian rupa sehingga "l1Kjj={1,...,J}J jika Anda ingin mengejar ini lebih lanjut. [Karena kami menyebutkan Python secara khusus: Saya belum menggunakan pyglmnetpaket Python tetapi tampaknya termasuk

Semua dalam semua, tidak masuk akal untuk hanya "menjumlahkan" variabel penting dari variabel dummy individu karena tidak akan menangkap hubungan di antara mereka serta menyebabkan hasil yang berpotensi tidak berarti. Yang mengatakan, kedua metode kelompok-dihukum serta metode kepentingan variabel permutasi memberikan koheren dan (terutama dalam kasus prosedur kepentingan permutasi) kerangka kerja yang berlaku umum untuk melakukannya.

Akhirnya untuk menyatakan yang jelas: jangan bin data kontinu . Ini adalah praktik buruk, ada utas bagus tentang hal ini di sini (dan di sini ). Fakta bahwa kita mengamati hasil palsu setelah diskritisasi variabel kontinu, seperti age, tidak mengejutkan. Frank Harrell juga menulis extensivel pada masalah yang disebabkan oleh pengelompokan variabel kontinu .


Anda menautkan kepentingan relatif dari serangkaian prediktor dalam klasifikasi hutan acak di R yang menjawab pertanyaan secara langsung. Saya akan dengan senang hati menerima jika Anda memindahkan referensi ke tautan itu ke awal karena saya tidak menganggap sisanya relevan secara langsung dan tautan tersebut dapat dengan mudah hilang dalam jawabannya.
Dan

Tidak masalah. Saya melakukan beberapa pengeditan yang relevan. Jangan mengabaikan konsep regresi yang diatur, seperti yang saya sebutkan dalam teks, pendekatan regularisasi menawarkan alternatif yang benar-benar valid untuk fitur pentingnya / peringkat.
usεr11852 mengatakan Reinstate Monic

Regresi yang terregulasi bukan jawaban untuk pertanyaan ini, mungkin menjawab pertanyaan yang berbeda yaitu alternatif untuk fitur-fitur penting tetapi pertanyaan ini adalah tentang menggabungkan fitur menjadi fitur kategorikal tunggal dalam plot kepentingan fitur. Saya pikir Anda harus memindahkan tautan yang benar-benar menjawab pertanyaan sejak awal.
Dan

2

Pertanyaannya adalah:

apakah masuk akal untuk menggabungkan kembali nilai penting variabel dummy menjadi nilai penting untuk variabel kategori hanya dengan menjumlahkannya?

Jawaban singkatnya:

sayamhalHairtSebuahnce(Xl)=saya
(saya)2=t=1J-1saya2saya(v(t)=)
saya=t=1J-1saya2saya(v(t)=)

Semakin lama, jawaban yang lebih praktis ..

Anda tidak bisa begitu saja menjumlahkan nilai-nilai penting variabel individual untuk variabel dummy karena Anda berisiko

masking variabel penting oleh orang lain yang sangat berkorelasi dengannya. (halaman 368)

Masalah seperti kemungkinan multikolinieritas dapat mendistorsi nilai dan peringkat kepentingan variabel.

Sebenarnya ini adalah masalah yang sangat menarik untuk memahami betapa pentingnya variabel dipengaruhi oleh isu-isu seperti multikolinearitas. Makalah Menentukan Pentingnya Prediktor Dalam Regresi Berganda Dalam Berbagai Kondisi Korelasional Dan Distribusi membahas berbagai metode untuk menghitung kepentingan variabel dan membandingkan kinerja untuk data yang melanggar asumsi statistik khas. Para penulis menemukan itu

Meskipun multikolinieritas memang memengaruhi kinerja metode-metode yang relatif penting, nonnormalitas multivariat tidak. (WHITTAKER p366)


Saya rasa kutipan kedua Anda tidak relevan. Ini bukan variabel yang sangat berkorelasi, mereka adalah variabel yang sama dan implementasi yang baik dari pohon keputusan tidak akan memerlukan OHE tetapi memperlakukan ini sebagai variabel tunggal. Jika ada, multikolinearitas secara artifisial diperkenalkan oleh OHE.
Dan

Mengenai poin pertama Anda, saya merasa terluka karena angka kepentingan relatif yang diajukan Breiman adalah nilai kuadrat. Jadi saya tidak yakin sklearn mengambil akar kuadrat dulu seperti yang Anda sarankan. Juga, jika mereka, bukankah seharusnya saya mengkuadratkan nilai-nilai, menambahkannya dan kemudian mengkuadratkan jumlah? Saya tidak yakin saya mengerti saran Anda untuk mengambil akar kuadrat terlebih dahulu.
Dan

@ecedavis Apa yang Anda maksud dengan buku teks? Bisakah Anda memberikan tautan atau kutipan yang lebih lengkap?
see24

Hai, terima kasih atas kritiknya dan untuk upvote pertama saya sebagai anggota baru. Komentar Anda menunjukkan perincian spesifik yang akan saya bahas dalam revisi saya, tetapi bolehkah saya juga memiliki pendapat Anda tentang keseluruhan kualitas jawaban saya? Ini adalah posting pertama saya dan saya berencana untuk menjadi kontributor tetap. Paling tidak, saya berharap jawaban saya umumnya membantu dan dalam gaya yang baik. Apa yang kamu pikirkan?
ecedavis

Gaya jawaban Anda baik tetapi beberapa informasi dan konten tampaknya tidak sepenuhnya benar. Makalah yang Anda tautkan adalah tentang pentingnya prediktor dalam regresi berganda sementara pertanyaannya adalah tentang pentingnya hutan secara acak. Saya juga mendapati bahwa ekstraksi kutipan Anda bermasalah karena kalimat lengkapnya adalah "Juga, karena penyusutan (Bagian 10.12.1) menutupi variabel-variabel penting oleh orang lain yang berkorelasi sangat jauh dari masalah." yang memiliki makna yang sangat berbeda.
see24
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.