How to detect irrelevant features with SHAP in Machine Learning
This tutorial shows how to detect irrelevant features in Machine Learning using SHAP, a technique that explains each feature's contribution to predictions. Knowing which features are of low relevance helps simplify models, reduce overfitting and speed up deployment to production.
Prerequisites
- Python 3.8+ and pip
- Libraries: scikit-learn, xgboost, shap, pandas, numpy, matplotlib
- Basic modeling knowledge: train/test split, fitting a model
Step 1: Why use SHAP to detect irrelevant features
SHAP (SHapley Additive exPlanations) assigns each feature a consistent contribution to the prediction. By aggregating SHAP importances per feature, we obtain a robust relevance measure that accounts for interactions and not just simple correlations. This avoids common mistakes like relying only on linear model coefficients or on algorithms' intrinsic importances.
Step 2: Install dependencies
Install the required libraries. This step is straightforward and prevents compatibility issues.
pip install scikit-learn xgboost shap pandas numpy matplotlib
Step 3: Prepare example data
We create a synthetic dataset with relevant and irrelevant features to demonstrate detection. Always keep a train/test split to assess impact.
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)
# adiciona 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)
Step 4: Train a model (example with XGBoost)
Use a powerful model like XGBoost; SHAP works well with tree models and generalizes to other models.
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))
Step 5: Compute SHAP values and aggregate importances
Use the TreeExplainer for tree models. Compute the mean absolute SHAP value per feature to obtain global importance.
import shap
import numpy as np
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X_train)
# para classificação binária em XGBoost, shap_values é uma lista; usa o í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)
Step 6: Identify and remove irrelevant features
Define a simple threshold, for example features with importance below a fraction of the maximum. Remove them and re-train to verify impact.
threshold = shap_importance.max() * 0.05 # 5% of the maximum
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 reduzido:', accuracy_score(y_test, model_reduced.predict(X_test_reduced)))
Step 7: Avoid common mistakes
Frequent mistakes: (1) relying only on model importance without validating performance; (2) removing correlated features without checking multicollinearity; (3) using SHAP with very small samples. Always validate the impact on the test set and consider cross-validation.
Verify the result
You can confirm it went well if: (a) features listed as irrelevant have very low SHAP values; (b) test performance is maintained or improved; (c) the reduced model is simpler (fewer columns) and faster at inference. Also, visualize importances with a plot:
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()
Conclusion
Detecting irrelevant features with SHAP is a practical approach to simplify models and prevent overfitting, because it considers interactions and not only simple correlations. Next steps: try cross-validation, test different thresholds and apply to regression or other models. Tip: what if you remove only a subset and compare performance at each step — which features are truly essential?