[PYTHON] Sélection de fonctionnalités par importances nulles

introduction

Ceci est un mémorandum parce que j'ai étudié la sélection des fonctionnalités en utilisant une importance nulle. Veuillez indiquer s'il y a quelque chose d'étrange. Référence: Sélection de fonctionnalités avec aucune importance nulle

Aperçu

Ceci est fait pour supprimer la quantité de caractéristiques qui provoque du bruit lors de la sélection de la quantité de caractéristiques et pour extraire la quantité de caractéristiques vraiment importante. L'importance de chaque caractéristique est mesurée à l'aide de données d'apprentissage dans lesquelles la variable objective est mélangée de manière aléatoire.

procédure

  1. Entraînez le modèle plusieurs fois avec des données de formation mélangées à des variables objectives pour créer une distribution d'importance nulle
  2. Entraînez le modèle avec les données d'entraînement d'origine et obtenez l'importance de chaque fonctionnalité
  3. Calculez le score d’importance réel pour la distribution d’importance nulle
  4. Définissez un seuil approprié et sélectionnez le montant de la fonction

0. Préparation

Importer les bibliothèques requises

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

Préparation des données Cette fois, nous utiliserons les données du tutoriel House Price de kaggle. House Prices: Advanced Regression Techniques

#Lecture des données
data = pd.read_csv("./House_Price/train.csv")
target = data['SalePrice']

#Obtenir des variables catégorielles
cat_features = [
    f for f in data.columns if data[f].dtype == 'object'
]

for feature in cat_features:
    #Convertir des variables catégorielles en nombres
    data[feature], _ = pd.factorize(data[feature])
    #Convertir le type en catégorie
    data[feature] = data[feature].astype('category')

#Pour le moment, la quantité de caractéristiques incluant la valeur manquante est supprimée.
drop_cols = [f for f in data.columns if data[f].isnull().any(axis=0) == True]
# drop_cols.append('SalePrice') #Supprimer la variable objectif
data = data.drop(drop_cols, axis=1)

1. Créez une distribution d'importance nulle

Préparez une fonction qui renvoie l'importance de la quantité de caractéristiques. Cette fois, j'ai utilisé LightGBM comme dans l'article auquel j'ai fait référence.

def get_feature_importances(data, cat_features, shuffle, seed=None):
    #Obtenir la quantité de fonctionnalités
    train_features = [f for f in data if f not in 'SalePrice']
    
    #Mélanger la variable d'objectif si nécessaire
    y = data['SalePrice'].copy()
    if shuffle:
        y = data['SalePrice'].copy().sample(frac=1.0)
    
    #Formation avec 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)

    #Acquérir l'importance de la quantité de caractéristiques
    imp_df = pd.DataFrame()
    imp_df["feature"] = list(train_features)
    imp_df["importance"] = clf.feature_importance()
    
    return imp_df

Créez une distribution d'importance nulle.

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. Obtenez l'importance des fonctionnalités normales

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

3. Calculer le score d'importance

Utiliser l'importance des entités normales divisée par le 75e centile de la distribution d'importance nulle

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. Sélectionnez le montant de la fonction

Définissez un seuil approprié et sélectionnez le montant de la fonctionnalité. Cette fois, j'ai décidé d'utiliser celui avec un score de 0,5 ou plus.

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']

finalement

Il a été utilisé par les meilleurs lauréats du concours auquel j'ai participé l'autre jour, alors je l'ai vérifié. Je pense qu'il existe diverses autres méthodes pour sélectionner les quantités de caractéristiques, je voudrais donc enquêter.

Recommended Posts

Sélection de fonctionnalités par importances nulles
Sélection des fonctionnalités par sklearn.feature_selection
Sélection des caractéristiques par algorithme génétique
Ensembles de données de sélection de fonctionnalités
[Français] scikit-learn 0.18 Guide de l'utilisateur 1.13 Sélection des fonctionnalités
Score de puissance prédictif pour la sélection des fonctionnalités
Prise en charge de la régression vectorielle et de la sélection des fonctionnalités
Génération de fonctionnalités avec pandas group par