Skip to content

Feature Selection with NMIFeatureSelector

Отбор признаков с помощью NMIFeatureSelector на наборе данных о качестве вина

Этот пример оценивает способность NMIFeatureSelector сохранять информативные признаки и отбрасывать шум, используя набор данных о качестве вина из UCI. Мы: - Загрузим набор данных и предварительно обработаем его. - Добавим синтетические шумовые признаки для имитации неинформативных атрибутов. - Сравним производительность модели с отбором признаков и без него по мере увеличения шума. - Визуализируем результаты.

Шаг 1: Загрузка и предварительная обработка данных

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt
from bn_nmi_feature_selector import NMIFeatureSelector

# Загрузка набора данных о качестве вина (красное вино)
data = pd.read_csv('data/feature_selection/WineQT.csv')
data = data.drop(columns=['Id'])
X = data.drop("quality", axis=1)
y = data["quality"].values

Шаг 2: Определение функции для добавления шума и оценки

def evaluate_performance(X, y, noise_features=0, threshold=0.05):
    # Добавление случайных шумовых признаков
    np.random.seed(42)
    noise = np.random.randn(X.shape[0], noise_features)
    X_combined = np.hstack([X.values, noise])

    # Разделение данных
    X_train, X_test, y_train, y_test = train_test_split(
        X_combined, y, test_size=0.3, random_state=42
    )

    # С отбором признаков
    selector = NMIFeatureSelector(threshold=threshold, n_bins=10)
    X_train_selected = selector.fit_transform(X_train, y_train)
    X_test_selected = selector.transform(X_test)

    # Обучение модели на отобранных признаках
    model = RandomForestClassifier(random_state=42)
    model.fit(X_train_selected, y_train)
    y_pred = model.predict(X_test_selected)
    acc_selected = accuracy_score(y_test, y_pred)

    # Без отбора признаков
    model.fit(X_train, y_train)
    y_pred = model.predict(X_test)
    acc_full = accuracy_score(y_test, y_pred)

    return acc_full, acc_selected, selector.selected_features_.shape[0]

Шаг 3: Запуск эксперимента с увеличением шума

noise_levels = np.arange(0, 50, 10)  # Тестируем от 0 до 40 шумовых признаков
results = []

for noise in noise_levels:
    acc_full, acc_selected, n_selected = evaluate_performance(X, y, noise_features=noise)
    results.append({
        "Noise Features": noise,
        "Accuracy (Full)": acc_full,
        "Accuracy (Selected)": acc_selected,
        "Selected Features": n_selected
    })
    print(f"Noise: {noise:2d} | Full Acc: {acc_full:.3f} | Selected Acc: {acc_selected:.3f} | Features Kept: {n_selected}")

results_df = pd.DataFrame(results)

Шаг 4: Визуализация результатов

plt.figure(figsize=(10, 6))
plt.plot(results_df["Noise Features"], results_df["Accuracy (Full)"], 
         marker="o", label="Without Selection", color="red")
plt.plot(results_df["Noise Features"], results_df["Accuracy (Selected)"], 
         marker="o", label="With Selection", color="green")
plt.xlabel("Number of Noise Features Added")
plt.ylabel("Model Accuracy")
plt.title("Impact of Noise Features on Model Performance")
plt.legend()
plt.grid(True)
plt.show()
output

Заключение

NMIFeatureSelector эффективно: - Идентифицирует информативные признаки в реальном наборе данных. - Фильтрует шум, предотвращая снижение производительности модели. - Работает надежно, даже когда 80% признаков являются неинформативными (40 шумовых + 11 исходных).

Рекомендация: Настройте параметр threshold для баланса между сохранением признаков и удалением шума. Например, более высокий порог (например, 0.1) может дополнительно уменьшить шум, но рискует исключить слабо информативные признаки.