Cómo detectar features irrelevantes con SHAP en Machine Learning
Este tutorial muestra cómo detectar features irrelevantes en Machine Learning usando SHAP, una técnica que explica la contribución de cada feature a las predicciones. Saber qué features son poco relevantes ayuda a simplificar modelos, reducir overfitting y acelerar el despliegue en producción.
Prerequisitos
- Python 3.8+ y pip
- Bibliotecas: scikit-learn, xgboost, shap, pandas, numpy, matplotlib
- Conocimientos básicos de modelado: train/test, fitting de un modelo
Paso 1: Por qué usar SHAP para detectar features irrelevantes
SHAP (SHapley Additive exPlanations) asigna a cada feature una contribución consistente a la predicción. Al agregar las importancias SHAP por feature, obtenemos una medida robusta de relevancia que considera interacciones y no solo correlaciones simples. Esto evita errores comunes como confiar únicamente en coeficientes de modelos lineales o en las importancias intrínsecas del algoritmo.
Paso 2: Instalar dependencias
Instala las bibliotecas necesarias. Este paso es sencillo y evita problemas de compatibilidad.
pip install scikit-learn xgboost shap pandas numpy matplotlib
Paso 3: Preparar datos de ejemplo
Crearemos un conjunto sintético con features relevantes e irrelevantes para demostrar la detección. Mantén siempre un split train/test para evaluar el impacto.
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_classification
X, y = make_classification(n_samples=1000, n_features=10, n_informative=3,
n_redundant=1, n_repeated=0, random_state=42)
# añade features irrelevantes ruidosas
rng = np.random.RandomState(0)
noise = rng.normal(size=(X.shape[0], 3))
X = np.hstack([X, noise])
feature_names = [f'f{i}' for i in range(X.shape[1])]
df = pd.DataFrame(X, columns=feature_names)
X_train, X_test, y_train, y_test = train_test_split(df, y, test_size=0.2, random_state=42)
Paso 4: Entrenar un modelo (ejemplo con XGBoost)
Usa un modelo potente como XGBoost; SHAP funciona bien con modelos de árbol y generaliza a otros modelos.
import xgboost as xgb
from sklearn.metrics import accuracy_score
model = xgb.XGBClassifier(use_label_encoder=False, eval_metric='logloss', random_state=42)
model.fit(X_train, y_train)
preds = model.predict(X_test)
print('Accuracy:', accuracy_score(y_test, preds))
Paso 5: Calcular valores SHAP y agregar importancias
Usa TreeExplainer para modelos de árbol. Calcula el valor medio absoluto del SHAP por feature para obtener la importancia global.
import shap
import numpy as np
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X_train)
# para clasificación binaria en XGBoost, shap_values es una lista; usa el índice 1
sv = shap_values if isinstance(shap_values, np.ndarray) else shap_values[1]
mean_abs_shap = np.mean(np.abs(sv), axis=0)
shap_importance = pd.Series(mean_abs_shap, index=X_train.columns).sort_values(ascending=False)
print(shap_importance)
Paso 6: Identificar y eliminar features irrelevantes
Define un umbral simple, por ejemplo las features con importancia por debajo de una fracción del valor máximo. Elimínalas y reentrena para verificar el impacto.
threshold = shap_importance.max() * 0.05 # 5% del máximo
irrelevant = shap_importance[shap_importance < threshold].index.tolist()
print('Features irrelevantes detectadas:', irrelevant)
X_train_reduced = X_train.drop(columns=irrelevant)
X_test_reduced = X_test.drop(columns=irrelevant)
model_reduced = xgb.XGBClassifier(use_label_encoder=False, eval_metric='logloss', random_state=42)
model_reduced.fit(X_train_reduced, y_train)
print('Accuracy original:', accuracy_score(y_test, preds))
print('Accuracy reducido:', accuracy_score(y_test, model_reduced.predict(X_test_reduced)))
Paso 7: Evitar errores comunes
Errores frecuentes: (1) confiar solo en la importancia del modelo sin validar el rendimiento; (2) eliminar features correlacionadas sin verificar la multicolinealidad; (3) usar SHAP con muestras muy pequeñas. Valida siempre el impacto en el conjunto de test y considera cross-validation.
Verificar el resultado
Confirmas que ha ido bien si: (a) las features listadas como irrelevantes tienen valores SHAP muy bajos; (b) el rendimiento en test se mantiene o mejora; (c) el modelo reducido es más simple (menos columnas) y más rápido en inferencia. Además, visualiza las importancias con un gráfico:
import matplotlib.pyplot as plt
shap_importance.sort_values(ascending=True).plot(kind='barh', figsize=(6,6))
plt.title('SHAP mean abs importance')
plt.show()
Conclusión
Detectar features irrelevantes con SHAP es un enfoque práctico para simplificar modelos y prevenir overfitting, porque considera interacciones y no solo correlaciones simples. Próximos pasos: experimenta con cross-validation, prueba distintos umbrales y aplica a regresión u otros modelos. Consejo: y si eliminas solo un subconjunto y comparas el rendimiento en cada paso — qué features son realmente esenciales?