[PYTHON] Funktionsauswahl durch Null-Wichtigkeiten

Einführung

Dies ist ein Memorandum, da ich die Merkmalsauswahl mit der Wichtigkeit Null untersucht habe. Bitte weisen Sie darauf hin, wenn etwas seltsam ist. Referenz: Funktionsauswahl mit Null-Wichtigkeiten

Überblick

Dies geschieht, um die Merkmalsmenge zu entfernen, die bei der Auswahl der Merkmalsmenge Rauschen verursacht, und um die wirklich wichtige Merkmalsmenge zu extrahieren. Die Wichtigkeit jedes Merkmals wird anhand von Trainingsdaten gemessen, bei denen die Zielvariable zufällig gemischt wird.

Verfahren

  1. Trainieren Sie das Modell mehrmals mit Trainingsdaten, die die Zielvariable mischen, um eine Verteilung von null Wichtigkeit zu erstellen
  2. Trainieren Sie das Modell mit den ursprünglichen Trainingsdaten und ermitteln Sie die Wichtigkeit der einzelnen Funktionen
  3. Berechnen Sie den tatsächlichen Wichtigkeitswert für die Null-Wichtigkeitsverteilung
  4. Stellen Sie einen geeigneten Schwellenwert ein und wählen Sie den Funktionsbetrag aus

0. Vorbereitung

Importieren Sie die erforderlichen Bibliotheken

import pandas as pd
import numpy as np
np.random.seed(123)

from sklearn.metrics import mean_squared_error
from sklearn.model_selection import KFold
import time
import lightgbm as lgb

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import seaborn as sns

import warnings
warnings.simplefilter('ignore', UserWarning)

import gc
gc.enable()

import time

Vorbereiten der Daten. Dieses Mal verwenden wir die Daten aus dem Hauspreis-Tutorial von kaggle. House Prices: Advanced Regression Techniques

#Daten gelesen
data = pd.read_csv("./House_Price/train.csv")
target = data['SalePrice']

#Holen Sie sich kategoriale Variablen
cat_features = [
    f for f in data.columns if data[f].dtype == 'object'
]

for feature in cat_features:
    #Konvertieren Sie kategoriale Variablen in Zahlen
    data[feature], _ = pd.factorize(data[feature])
    #Typ in Kategorie konvertieren
    data[feature] = data[feature].astype('category')

#Die Merkmalsmenge einschließlich des fehlenden Wertes wird vorerst gelöscht.
drop_cols = [f for f in data.columns if data[f].isnull().any(axis=0) == True]
# drop_cols.append('SalePrice') #Löschen Sie die Zielvariable
data = data.drop(drop_cols, axis=1)

1. Erstellen Sie eine Verteilung von null Wichtigkeit

Bereiten Sie eine Funktion vor, die die Wichtigkeit der Feature-Menge zurückgibt. Dieses Mal habe ich LightGBM wie in dem Artikel verwendet, auf den ich mich bezog.

def get_feature_importances(data, cat_features, shuffle, seed=None):
    #Funktionsmenge abrufen
    train_features = [f for f in data if f not in 'SalePrice']
    
    #Mischen Sie ggf. die Zielvariable
    y = data['SalePrice'].copy()
    if shuffle:
        y = data['SalePrice'].copy().sample(frac=1.0)
    
    #Training mit LightGBM
    dtrain = lgb.Dataset(data[train_features], y, free_raw_data=False, silent=True)
    params = {
        'task': 'train',
        'boosting_type': 'gbdt',
        'objective': 'regression',
        'metric': {'l2'},
        'num_leaves': 128,
        'learning_rate': 0.01,
        'num_iterations':100,
        'feature_fraction': 0.38,
        'bagging_fraction': 0.68,
        'bagging_freq': 5,
        'verbose': 0
    }
    clf = lgb.train(params=params, train_set=dtrain, num_boost_round=200, categorical_feature=cat_features)

    #Ermitteln Sie die Wichtigkeit der Merkmalsmenge
    imp_df = pd.DataFrame()
    imp_df["feature"] = list(train_features)
    imp_df["importance"] = clf.feature_importance()
    
    return imp_df

Erstellen Sie eine Verteilung von Null Importance.

null_imp_df = pd.DataFrame()
nb_runs = 80
start = time.time()
for i in range(nb_runs):
    imp_df = get_feature_importances(data=data, cat_features=cat_features, shuffle=True)
    imp_df['run'] = i + 1 
    null_imp_df = pd.concat([null_imp_df, imp_df], axis=0)

2. Holen Sie sich die Wichtigkeit normaler Funktionen

actual_imp_df = get_feature_importances(data=data, cat_features=cat_features, shuffle=False)

3. Berechnen Sie den Wichtigkeitsfaktor

Verwenden Sie die Wichtigkeit normaler Merkmale geteilt durch das 75. Perzentil der Null-Wichtigkeitsverteilung

feature_scores = []
for _f in actual_imp_df['feature'].unique():
    f_null_imps = null_imp_df.loc[null_imp_df['feature'] == _f, 'importance'].values
    f_act_imps = actual_imp_df.loc[actual_imp_df['feature'] == _f, 'importance'].mean()
    imp_score = np.log(1e-10 + f_act_imps / (1 + np.percentile(f_null_imps, 75)))
    feature_scores.append((_f, imp_score))

scores_df = pd.DataFrame(feature_scores, columns=['feature', 'imp_score'])

4. Wählen Sie den Funktionsbetrag aus

Stellen Sie einen geeigneten Schwellenwert ein und wählen Sie den Funktionsumfang aus. Dieses Mal habe ich mich für den Schwellenwert mit einer Punktzahl von 0,5 oder mehr entschieden.

sorted_features = scores_df.sort_values(by=['imp_score'], ascending=False).reset_index(drop=True)
new_features = sorted_features.loc[sorted_features.imp_score >= 0.5, 'feature'].values
print(new_features)

# ['CentralAir' 'GarageCars' 'OverallQual' 'HalfBath' 'OverallCond' 'BsmtFullBath']

Schließlich

Es wurde von den Top-Preisträgern des Wettbewerbs verwendet, an dem ich neulich teilgenommen habe, also habe ich es überprüft. Ich denke, es gibt verschiedene andere Methoden zur Auswahl von Merkmalsmengen, daher möchte ich dies untersuchen.

Recommended Posts

Funktionsauswahl durch Null-Wichtigkeiten
Funktionsauswahl durch sklearn.feature_selection
Merkmalsauswahl durch genetischen Algorithmus
Feature-Auswahldatensätze
[Übersetzung] scikit-learn 0.18 Benutzerhandbuch 1.13 Funktionsauswahl
Predictive Power Score für die Funktionsauswahl
Unterstützung der Vektorregression und Merkmalsauswahl
Feature-Generierung mit Pandas gruppieren nach