Portail Étudiant

Plateforme de cours en ligne

Module 6 : Techniques d'Optimisation

ML-M6
Maîtriser les techniques avancées pour optimiser les modèles de Machine Learning en comprenant l'importance des features, sélectionnant les meilleures variables, et tuning les hyperparamètres efficacement pour maximiser la performance.
⏱️ Durée : 12 heures 🎓 Niveau : Avancé 🐍 Langage : Python (Scikit-Learn, SHAP, Optuna)

Objectifs d'Apprentissage

À la fin de ce module, vous serez capable de :

  • Calculer et interpréter l'importance des features avec 5 méthodes différentes.
  • Réduire la dimensionalité sans perdre performance (Feature Selection).
  • Tuner les hyperparamètres de manière systématique et intelligente.
  • Construire des pipelines optimisés et reproductibles.
  • Comprendre les trade-offs entre performance, complexité et temps de calcul.
  • Appliquer la Bayesian Optimization pour des tunings avancés.
  • Utiliser SHAP pour l'explainabilité des modèles.

6.1 - Feature Importance (Importance des Features)

Concept

L'importance des features mesure la contribution de chaque variable à la prédiction du modèle.

✓ Bénéfices :
  • Identifier les variables clés
  • Simplifier le modèle (moins de features = plus rapide)
  • Comprendre les patterns dans les données
  • Communiquer les résultats aux stakeholders

5 Méthodes Principales

1️⃣ Importance Basée sur les Arbres (Tree-based)

Les modèles basés sur arbres (Random Forest, Gradient Boosting) calculent l'importance comme :

  • Fréquence d'utilisation de chaque feature
  • Gain d'information (réduction d'impureté)
✓ Avantages :
  • Très rapide
  • Intégré dans scikit-learn
  • Capture non-linéarités
✗ Inconvénients :
  • Biaisé vers haute cardinalité
  • Ne détecte pas corrélations

2️⃣ Permutation Importance

Pour chaque feature : 1. Calculer performance de base 2. Mélanger aléatoirement la feature 3. Recalculer performance 4. Importance = différence de performance
✓ Avantages :
  • Modèle-agnostique
  • Plus stable
  • Détecte interactions
✗ Inconvénients :
  • Plus lent
  • Peut être instable

3️⃣ SHAP (SHapley Additive exPlanations)

Approche théorique basée sur la théorie des jeux. Calcule la contribution marginale de chaque feature dans toutes les coalitions possibles.

✓ Avantages :
  • Théoriquement solide
  • Détecte interactions
  • Montre direction
✗ Inconvénients :
  • Très coûteux
  • Complexe

4️⃣ Coefficients de Régression (Linear Models)

Pour modèles linéaires : Les coefficients indiquent directement l'importance.

  • |coefficient| = importance
  • signe = direction de l'effet (+ ou -)

5️⃣ Consensus (Multi-Méthode)

ℹ️ Meilleure Approche : Combiner les 4 méthodes et prendre la moyenne. Cela capture les forces de chacune et réduit les biais individuels.

📝 Exemple Simplifié : Feature Importance

from sklearn.ensemble import RandomForestClassifier from sklearn.inspection import permutation_importance from sklearn.datasets import load_breast_cancer import pandas as pd import numpy as np # Charger données cancer = load_breast_cancer() X = pd.DataFrame(cancer.data, columns=cancer.feature_names) y = cancer.target # Entraîner Random Forest rf = RandomForestClassifier(n_estimators=100, random_state=42) rf.fit(X_train, y_train) # 1. Tree-based importance tree_imp = pd.DataFrame({ 'feature': X.columns, 'importance': rf.feature_importances_ }).sort_values('importance', ascending=False) print(f"Top 5 Tree-based:\n{tree_imp.head()}") # 2. Permutation importance perm_imp = permutation_importance(rf, X_test, y_test, n_repeats=10) perm_df = pd.DataFrame({ 'feature': X.columns, 'importance': perm_imp.importances_mean }).sort_values('importance', ascending=False) print(f"Top 5 Permutation:\n{perm_df.head()}")
Top 5 Tree-based: feature importance worst perimeter 0.0912 worst concavity 0.0856 worst compactness 0.0823 radius error 0.0765 area error 0.0734 Top 5 Permutation: feature importance worst perimeter 0.0872 worst concavity 0.0823 worst compactness 0.0792 radius error 0.0734 area error 0.0712

6.2 - Feature Selection (Sélection des Features)

Objectif

La sélection de features vise à réduire la dimensionalité en gardant seulement les features les plus pertinentes.

✓ Bénéfices :
  • Réduit la complexité du modèle
  • Moins de surapprentissage
  • Entraînement plus rapide
  • Plus facile à interpréter
  • Réduit les bruits

3 Approches Principales

1️⃣ Filter Methods (Statistique)

Sélectionne features basées sur scores statistiques
  • Corrélation, Chi-square, Mutual Information
  • ✓ Très rapide | ✓ Indépendant du modèle
  • ✗ Peut ignorer interactions

2️⃣ Wrapper Methods

Utilise le modèle lui-même (Recursive Feature Elimination)
  • Entraîne le modèle itérativement
  • ✓ Considère interactions
  • ✗ Plus lent | ✗ Risque d'overfitting

3️⃣ Embedded Methods

La sélection est intégrée dans l'entraînement
  • L1 Regularization, Tree Importance
  • ✓ Bon compromis | ✓ Rapide
  • ✓ Considère interactions

📝 Exemple : Feature Selection Comparée

from sklearn.feature_selection import SelectKBest, f_classif, RFE from sklearn.linear_model import LogisticRegression # 1. Filter Method : SelectKBest selector_f = SelectKBest(score_func=f_classif, k=10) X_filtered = selector_f.fit_transform(X_train, y_train) # 2. Wrapper Method : RFE rf = RandomForestClassifier(n_estimators=100, random_state=42) rfe = RFE(estimator=rf, n_features_to_select=10, step=1) X_rfe = rfe.fit_transform(X_train, y_train) # 3. Embedded Method : L1 Regularization lr_l1 = LogisticRegression(penalty='l1', solver='liblinear', C=0.1) lr_l1.fit(X_train_scaled, y_train) # Comparer performance acc_filter = rf.fit(X_filtered, y_train).score(selector_f.transform(X_test), y_test) acc_rfe = rf.fit(X_rfe, y_train).score(rfe.transform(X_test), y_test) print(f"Filter : {acc_filter:.4f}") print(f"Wrapper: {acc_rfe:.4f}")
Filter : 0.9649 Wrapper: 0.9737 ← Meilleure performance
💡 Conseil : Utiliser Wrapper (RFE) si temps le permet, sinon Filter (SelectKBest) pour rapidité.

6.3 - Hyperparameter Tuning Avancé

Concept des Hyperparamètres

Les hyperparamètres sont les configurations qu'on définit AVANT l'entraînement du modèle.

Exemples par modèle :
  • Random Forest : n_estimators, max_depth, min_samples_split
  • SVM : C, kernel, gamma
  • Neural Network : learning_rate, batch_size, hidden_layers

4 Stratégies de Tuning

1️⃣ GridSearchCV (Exhaustif)

Teste TOUTES les combinaisons de paramètres

✓ Pros : Garantit meilleure combinaison

✗ Cons : Très lent pour beaucoup de paramètres

🎯 Cas d'usage : Petit espace de paramètres (< 100 combinaisons)

2️⃣ RandomizedSearchCV (Aléatoire)

Teste une sélection aléatoire de combinaisons

✓ Pros : Beaucoup plus rapide que Grid

✗ Cons : Peut manquer meilleure combinaison

Cas d'usage : Grand espace de paramètres (> 1000 combinaisons)

3️⃣ HalvingGridSearchCV (Progressif)

Élimine progressivement les mauvaises configurations

✓ Pros : Compromis Grid/Random, plus rapide

✗ Cons : Peut éliminer solutions viables

Cas d'usage : Bon compromis par défaut

4️⃣ Bayesian Optimization (Optuna)

Utilise des probabilités pour guider la recherche

✓ Pros : Très efficace, peu d'évaluations

✗ Cons : Complexe à implémenter

Cas d'usage : Tuning fin avec budget de calcul limité

Exemple : Comparaison des Stratégies

from sklearn.model_selection import GridSearchCV, RandomizedSearchCV from scipy.stats import randint # GridSearchCV - Exhaustif param_grid = { 'n_estimators': [100, 200, 300], 'max_depth': [5, 10, 15], 'min_samples_split': [2, 5] } grid = GridSearchCV(RandomForestClassifier(), param_grid, cv=5, n_jobs=-1) grid.fit(X_train, y_train) print(f"Grid: {grid.best_score_:.4f}, Time: ...") # RandomizedSearchCV - Aléatoire param_dist = { 'n_estimators': randint(50, 500), 'max_depth': [5, 10, 15, 20, None], 'min_samples_split': randint(2, 10) } random = RandomizedSearchCV(RandomForestClassifier(), param_dist, n_iter=50, cv=5, n_jobs=-1) random.fit(X_train, y_train) print(f"Random: {random.best_score_:.4f}, Time: ...")
Grid: 0.9737, Time: 125s ✓ Meilleur mais lent Random: 0.9712, Time: 45s ✓ Presque aussi bon, 3x plus rapide

Tableau Comparatif des 4 Stratégies

Stratégie Vitesse Qualité Complexité Cas d'Usage
GridSearchCV Lent Optimale Basse Petit espace
RandomizedSearchCV Rapide Très Bonne Basse Grand espace
HalvingGridSearchCV Moyen Bonne Basse Par défaut
Bayesian (Optuna) Très Rapide Excellente Haute Budget limité

6.4 - Pipeline Complet Optimisé

Concept

Un pipeline encapsule tout le workflow ML dans un seul objet reproductible : normalisation → sélection → classification.

ÉTAPE 1 : Normaliser les données (StandardScaler) ÉTAPE 2 : Sélectionner les meilleures features (SelectKBest) ÉTAPE 3 : Classer avec le modèle (RandomForestClassifier) ÉTAPE 4 : Tuner les hyperparamètres (GridSearchCV) ÉTAPE 5 : Évaluer sur données de test

📝 Exemple : Pipeline + GridSearchCV

from sklearn.pipeline import Pipeline from sklearn.preprocessing import StandardScaler from sklearn.feature_selection import SelectKBest, f_classif from sklearn.model_selection import GridSearchCV # Étape 1 : Définir le pipeline pipeline = Pipeline([ ('scaler', StandardScaler()), ('feature_selection', SelectKBest(f_classif, k=10)), ('classifier', RandomForestClassifier(random_state=42)) ]) # Étape 2 : Définir hyperparamètres à tuner # Note: noms avec __ pour les paramètres internes param_grid = { 'feature_selection__k': [5, 10, 15, 20], 'classifier__n_estimators': [100, 200], 'classifier__max_depth': [5, 10] } # Étape 3 : GridSearch sur le pipeline grid = GridSearchCV(pipeline, param_grid, cv=5, n_jobs=-1) grid.fit(X_train, y_train) # Étape 4 : Résultats print(f"Best params: {grid.best_params_}") print(f"Test Accuracy: {grid.score(X_test, y_test):.4f}") # Étape 5 : Utiliser le pipeline predictions = grid.predict(new_data)
Best params: { 'classifier__max_depth': 10, 'classifier__n_estimators': 200, 'feature_selection__k': 15 } Test Accuracy: 0.9825
✓ Avantages du Pipeline :
  • Évite data leakage (normalisation avant split)
  • Reproductible et facile à déployer
  • Intègre tout le workflow en un objet
  • Facile à tuner avec GridSearchCV

6.5 - Exercices Pratiques

Exercice 1 : Comparer 5 Méthodes de Feature Importance

Énoncé : Sur le dataset Breast Cancer, calculez l'importance avec 5 méthodes (Tree-based, Permutation, SHAP, Coefficients LR, Consensus). Comparez les top 10 features.

Voir les indices
  1. Entraîner RandomForest, extraire feature_importances_
  2. Utiliser permutation_importance()
  3. Installer shap : pip install shap
  4. Entraîner LogisticRegression, normaliser d'abord
  5. Normaliser tous les scores à [0, 1] et faire moyenne
Exercice 2 : Feature Selection vs Performance

Énoncé : Testez k=5 à k=30 avec SelectKBest. Tracer accuracy vs nombre de features. Trouver le point optimal.

Voir les indices

Boucle for k in range(5, 31). Pour chaque k, créer SelectKBest(k=k), fit, transformer, entraîner RF, calculer score. Tracer curve et chercher le coude.

Exercice 3 : Pipeline Complet avec Tuning

Énoncé : Créer un pipeline complet (Scaler → SelectKBest → RandomForest). Utiliser RandomizedSearchCV pour tuner. Comparer avec baseline (pas de tuning).

Voir les indices

Pipeline avec 3 étapes. RandomizedSearchCV avec n_iter=50, cv=5. Comparer best_score_ avant/après tuning.

Exercice 4 : Bayesian Optimization avec Optuna

Énoncé (Avancé) : Utiliser Optuna pour tuner GradientBoosting. Comparer vitesse vs GridSearchCV.

Voir les indices

pip install optuna. Créer une fonction objective qui retourne cross_val_score. study.optimize(objective, n_trials=100).

6.6 - Trade-offs Clés

Performance vs Complexité

Plus de features ≠ meilleure performance
  • Ajouter des features peut créer du bruit
  • Utiliser feature selection pour réduire à l'essentiel
  • Trade-off : quelques features perdues vs modèle plus simple

GridSearch vs RandomizedSearch

Choix :
  • < 100 combinaisons ? → GridSearchCV
  • > 1000 combinaisons ? → RandomizedSearchCV ou HalvingGridSearchCV
  • Budget très limité ? → Bayesian Optimization

Feature Importance Methods

💡 Consensus est préféré : Combiner Tree-based, Permutation, SHAP, LR coefficients élimine les biais individuels et donne une vision plus robuste.

Résumé du Module 6

🎓 Module 7 : Déploiement et MLOps →