Machine learning classique
Sur données tabulaires — c'est-à-dire l'immense majorité des problèmes industriels — le deep learning ne domine pas. Les méthodes de ce module restent l'état de l'art, s'entraînent en secondes, s'expliquent, et se déploient sans GPU. On les passe en revue par famille, avec pour chacune le mécanisme réel, les cas d'usage, et les raisons de s'en méfier.
📋 Au programme
- Biais, variance et capacité
- Modèles linéaires et régularisation
- Régression logistique
- SVM et astuce du noyau
- Arbres de décision
- Bagging et forêts aléatoires
- Boosting : XGBoost et ses cousins
- Stacking
- Clustering et détection d'anomalies
- Recherche d'hyperparamètres
- Interprétabilité
- Tableau comparatif et pièges
1. Biais, variance et capacité
Pour une prédiction en un point \(x\), l'erreur quadratique attendue — moyennée sur tous les jeux d'entraînement possibles — se décompose en trois termes :
Le biais mesure l'erreur systématique due à l'hypothèse de modèle : une droite ne peut pas épouser une parabole, quel que soit le nombre de points. La variance mesure la sensibilité au jeu d'entraînement particulier : un modèle très flexible dessine une courbe différente à chaque échantillon. Le bruit est la part qu'aucun modèle ne peut expliquer, parce qu'elle n'est pas dans les données.
BIAIS FAIBLE, VARIANCE FAIBLE BIAIS FAIBLE, VARIANCE FORTE
(l'idéal) (surapprentissage)
·:· · ·
·:@:· groupé, au centre · · @ · dispersé autour du centre
·:· · · ·
BIAIS FORT, VARIANCE FAIBLE BIAIS FORT, VARIANCE FORTE
(sous-apprentissage) (le pire des deux)
·:· · ·
·:· @ groupé, mais à côté · · · @ dispersé ET décalé
·:· · ·Augmenter la capacité d'un modèle baisse le biais et monte la variance. Le surapprentissage, c'est le régime où la seconde l'emporte : le modèle mémorise le bruit de son échantillon. Le module 15 montre que ce tableau classique se complique en très haute dimension.
Diagnostiquer avec les courbes
Erreur d'entraînement élevée, et proche de l'erreur de validation → sous-apprentissage : le modèle manque de capacité, ou il manque des variables informatives. Inutile de régulariser davantage. Erreur d'entraînement très basse, erreur de validation bien supérieure → surapprentissage : régulariser, simplifier, ou ajouter des données. La courbe d'apprentissage (performance en fonction du nombre d'exemples, module 13) tranche cette dernière question : si les deux courbes se rapprochent encore, collecter plus de données aidera ; si elles ont convergé, non.
2. Modèles linéaires et régularisation
Le modèle \(\hat{y} = \beta_0 + \sum_j \beta_j x_j\) reste le point de départ obligé : rapide, interprétable, statistiquement bien compris, et souvent une baseline difficile à battre quand les variables sont bien construites (module 12).
Ridge (L²) pénalité λ·Σβ² rétrécit tous les coefficients, n'en annule aucun.
Idéal en présence de colinéarité : répartit le poids
entre variables corrélées au lieu d'en choisir une.
Lasso (L¹) pénalité λ·Σ|β| annule certains coefficients → sélection automatique.
Instable si les variables sont très corrélées : il en
choisit une presque au hasard dans chaque groupe.
Elastic-Net combinaison compromis : sélection ET stabilité sur groupes corrélés.L'intuition géométrique de la différence mérite un dessin. On minimise l'erreur sous la contrainte que \(\beta\) reste dans une boule de rayon fixé. La boule \(L^2\) est ronde : la solution optimale la touche presque toujours en un point où aucune coordonnée n'est nulle. La boule \(L^1\) est un losange, avec des coins pointus sur les axes : le contact se fait fréquemment sur un coin, c'est-à-dire avec des coefficients exactement nuls.
L² (ridge) L¹ (lasso)
β₂ │ ⌒⌒⌒ β₂ │ ◆
│ ⌒ ● ⌒ ← contact │ ◆ ●◆ ← contact SUR L'AXE
│ ⌒( ) ⌒ hors des axes │ ◆ │ ◆ donc β₂ = 0
│ ⌒⌒⌒ │ ◆│◆
└──────────── β₁ └──────────── β₁Le module 8 en donne la lecture spectrale pour ridge — un filtrage qui écrase les directions de faible variance — et le module 10 la lecture bayésienne : un a priori gaussien pour ridge, laplacien pour le lasso.
from sklearn.linear_model import RidgeCV, LassoCV, ElasticNetCV
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
import numpy as np
# la standardisation est OBLIGATOIRE : la pénalité s'applique aux coefficients,
# donc à des grandeurs qui doivent être comparables (module 8)
modele = make_pipeline(
StandardScaler(),
RidgeCV(alphas=np.logspace(-3, 3, 50)), # λ choisi par validation croisée
).fit(X, y)
print(modele[-1].alpha_) # le λ retenu
coefs = modele[-1].coef_
print(sorted(zip(np.abs(coefs), noms), reverse=True)[:10]) # variables les plus pesantes3. Régression logistique
Pour la classification, on ne peut pas prédire directement une probabilité avec un modèle linéaire : celui-ci produirait des valeurs hors de [0, 1]. On modélise donc le logarithme de la cote (le rapport « probabilité de succès sur probabilité d'échec ») :
La fonction de droite est la sigmoïde : elle écrase toute la droite réelle dans l'intervalle ]0, 1[, de façon monotone et dérivable. L'estimation se fait par maximum de vraisemblance, ce qui revient — module 10 — à minimiser l'entropie croisée.
L'interprétation des coefficients est directe et c'est ce qui fait la valeur du modèle : \(e^{\beta_j}\) est le facteur multiplicatif sur la cote quand \(x_j\) augmente d'une unité. Un coefficient de 0,7 signifie que la cote est multipliée par \(e^{0{,}7} \approx 2\) : le phénomène devient deux fois plus « probable » au sens de la cote. C'est le modèle de référence quand l'explication compte autant que la performance — scoring de crédit, épidémiologie —, et ses probabilités sont naturellement bien calibrées, ce qui n'est pas le cas d'un gradient boosting.
4. SVM et astuce du noyau
Une machine à vecteurs de support cherche l'hyperplan séparateur qui maximise la marge — la distance aux points les plus proches de chaque classe. L'idée : parmi toutes les frontières qui séparent correctement les données, celle qui laisse le plus de place de part et d'autre est la plus susceptible de bien généraliser.
○ ○ │ × × ── la frontière
○ ○ ┊ │ ┊ × ┊ les marges
○ ●──┊─────│─────┊──● × ● les VECTEURS DE SUPPORT : seuls
○ ○ ┊ │ ┊ × × ces points déterminent la solution
○ ←── marge ──→ × (déplacer les autres ne change rien)La formulation à marge souple autorise des violations, pénalisées par un paramètre \(C\) :
Le premier terme maximise la marge (une petite norme de \(w\) donne une large marge), le second compte les violations. Seuls les points sur ou à l'intérieur de la marge — les vecteurs de support — interviennent dans la solution, ce qui rend le modèle insensible aux points éloignés de la frontière.
L'astuce du noyau est l'idée élégante. La solution ne dépend des données qu'à travers des produits scalaires \(x_i^\top x_j\). En les remplaçant par une fonction noyau \(k(x_i,x_j)\), on travaille implicitement dans un espace de dimension bien plus grande — voire infinie pour le noyau RBF \(k(x,x') = \exp(-\gamma\|x-x'\|^2)\) — sans jamais calculer les coordonnées dans cet espace. Une frontière non linéaire dans l'espace d'origine devient linéaire dans l'espace induit. On retrouvera exactement ce mécanisme dans les processus gaussiens (module 19).
Réglages : \(C\) contrôle le compromis marge/erreurs (grand \(C\) = peu de tolérance = risque de surapprentissage), \(\gamma\) la portée d'influence d'un point (grand \(\gamma\) = influence très locale = frontière tourmentée). Les deux se règlent ensemble, sur une grille logarithmique.
Limites : le coût est au moins quadratique en nombre d'exemples — au-delà de quelques dizaines de milliers de points, le SVM à noyau devient impraticable ; il exige des variables standardisées (il repose sur des distances) ; et il ne fournit pas de probabilités, celles de predict_proba venant d'une calibration de Platt ajoutée après coup, qui coûte une validation croisée supplémentaire. Il reste excellent quand les exemples sont peu nombreux et les variables nombreuses — chimiométrie, bio-informatique, spectroscopie.
5. Arbres de décision
Un arbre CART partitionne récursivement l'espace par des coupes perpendiculaires aux axes. À chaque nœud, il teste toutes les variables et tous les seuils possibles, et retient la coupe qui rend les enfants les plus « purs ».
Nœud parent : 100 exemples, 50 positifs → Gini = 1 - (0,5² + 0,5²) = 0,500 Coupe candidate A : surface < 60 gauche 40 exemples, 10 positifs → Gini = 1 - (0,25² + 0,75²) = 0,375 droite 60 exemples, 40 positifs → Gini = 1 - (0,67² + 0,33²) = 0,444 impureté pondérée = 0,4×0,375 + 0,6×0,444 = 0,417 → gain 0,083 Coupe candidate B : ville = Lyon gauche 50 exemples, 45 positifs → Gini = 0,180 droite 50 exemples, 5 positifs → Gini = 0,180 impureté pondérée = 0,180 → gain 0,320 ← RETENUE
L'indice de Gini \(\sum_k p_k(1-p_k)\) vaut 0 pour un nœud pur et 0,5 pour un nœud parfaitement mélangé (en binaire). L'entropie donne des résultats très proches ; en régression, on minimise la variance intra-nœud.
Avantages : aucun prétraitement (insensible aux échelles et à toute transformation monotone — prendre le logarithme d'une variable ne change strictement rien), gestion naturelle des variables catégorielles et des interactions, lecture directe des règles. Défaut rédhibitoire : un arbre profond mémorise, un arbre court sous-apprend, et surtout l'arbre est instable — changer quelques points d'entraînement peut produire une structure entièrement différente. Cette instabilité est précisément ce que les méthodes d'ensemble vont transformer en atout.
6. Bagging et forêts aléatoires
Le bagging (bootstrap aggregating) entraîne \(B\) modèles sur des échantillons bootstrap — tirés avec remise dans les données d'origine — et moyenne leurs prédictions. Si les modèles étaient indépendants, la variance serait divisée par \(B\) ; en pratique ils sont corrélés puisqu'ils voient presque les mêmes données, et le gain est plus modeste.
La forêt aléatoire ajoute une seconde source d'aléa pour les décorréler davantage : à chaque nœud, seules \(m\) variables tirées au hasard sont candidates (typiquement \(\sqrt{p}\) en classification, \(p/3\) en régression). Chaque arbre devient un peu moins bon individuellement, mais l'ensemble s'améliore nettement — c'est le compromis central de la méthode.
from sklearn.ensemble import RandomForestClassifier
from sklearn.inspection import permutation_importance
rf = RandomForestClassifier(
n_estimators=500, # plus il y en a, mieux c'est (on sature) — jamais de
# surapprentissage en augmentant ce nombre
max_features="sqrt", # LA source de décorrélation
min_samples_leaf=5, # le vrai levier de régularisation
oob_score=True, # évaluation gratuite (voir ci-dessous)
n_jobs=-1, random_state=0,
).fit(X_train, y_train)
print(rf.oob_score_)
# importance FIABLE : on mélange une colonne et on mesure la perte de performance
imp = permutation_importance(rf, X_val, y_val, n_repeats=10, n_jobs=-1)
for i in imp.importances_mean.argsort()[::-1][:10]:
print(f"{noms[i]:25s} {imp.importances_mean[i]:.4f} ± {imp.importances_std[i]:.4f}")L'échantillonnage bootstrap laisse environ 37 % des points hors de chaque arbre — c'est la limite de \((1-1/n)^n = e^{-1}\). Ces points out-of-bag fournissent une estimation de performance quasi gratuite, sans validation croisée : chaque observation est évaluée par les arbres qui ne l'ont pas vue.
feature_importances_ (réduction moyenne d'impureté) est biaisé en faveur des variables à forte cardinalité et des variables continues, simplement parce qu'elles offrent plus de coupes possibles : un identifiant aléatoire peut y figurer en tête. Utiliser permutation_importance sur un jeu de validation — comme ci-dessus — ou les valeurs de Shapley (section 11).
7. Boosting : XGBoost et ses cousins
Là où le bagging construit des modèles en parallèle pour réduire la variance, le boosting les construit en séquence pour réduire le biais : chaque nouveau modèle corrige ce que les précédents ont raté.
F₀ = moyenne(y) = 100 résidus : +20, -15, +5, -10
↓ un petit arbre apprend ces RÉSIDUS, pas la cible
F₁ = F₀ + ν·h₁ résidus restants : +8, -6, +2, -4 (plus petits)
↓ un nouvel arbre apprend les résidus RESTANTS
F₂ = F₁ + ν·h₂ résidus restants : +3, -2, +1, -1
↓ …et ainsi de suite, sur des centaines d'arbres
ν (learning rate) amortit chaque correction :
petit ν = corrections prudentes = plus d'arbresLe gradient boosting généralise cette idée à n'importe quelle perte dérivable, en remplaçant le résidu par l'opposé du gradient de la perte par rapport à la prédiction courante — d'où le nom :
Avec la perte quadratique, ces pseudo-résidus sont exactement les résidus ordinaires, ce qui fait le lien avec le schéma ci-dessus. XGBoost raffine en utilisant aussi la dérivée seconde (approximation de Newton, module 8) et en intégrant la régularisation directement dans le critère de coupe.
import xgboost as xgb
modele = xgb.XGBClassifier(
n_estimators=2000, # volontairement grand : l'early stopping tranchera
learning_rate=0.05, # plus il est bas, plus il faut d'arbres : compromis n°1
max_depth=6, # 3-8 typiquement ; profondeur = ordre des interactions
# capturées (profondeur 3 = interactions à 3 variables)
min_child_weight=5, # poids minimal dans une feuille : anti-surapprentissage
subsample=0.8, # 80 % des LIGNES par arbre : du bruit utile
colsample_bytree=0.8, # 80 % des COLONNES par arbre : décorrélation
reg_lambda=1.0, # L² sur les poids des feuilles
eval_metric="aucpr",
early_stopping_rounds=100, # arrête quand la validation ne progresse plus
)
modele.fit(X_train, y_train, eval_set=[(X_val, y_val)], verbose=False)
print(f"meilleur nombre d'arbres : {modele.best_iteration}")XGBoost la référence, très réglable, excellent support GPU, écosystème mature.
LightGBM croissance par FEUILLE (leaf-wise) plutôt que par niveau, et binning en
histogrammes : nettement plus rapide sur grands jeux. Peut surapprendre
si num_leaves est trop grand.
CatBoost gère nativement les catégorielles avec un target encoding ordonné (donc
sans fuite, module 12), excellents résultats par défaut. Souvent le
meilleur choix quand il y a beaucoup de variables catégorielles à
forte cardinalité.Une bonne pratique : commencer par HistGradientBoostingClassifier de scikit-learn — pas de dépendance supplémentaire, gestion native des valeurs manquantes, performances très proches. Le réglage fin des variantes vient après, et rapporte généralement quelques pourcents, pas un changement de nature.
Pourquoi le boosting domine le tabulaire
Les données tabulaires sont hétérogènes (des échelles et des natures différentes dans la même ligne), pleines de relations non lisses (effets de seuil : « à partir de 3 pièces », « au-delà de 65 ans ») et souvent de taille modeste. Les arbres découpent l'espace sans aucune hypothèse de régularité, sont invariants aux transformations monotones et exploitent naturellement les interactions. Un réseau de neurones doit apprendre tout cela à partir des données, sans le biais inductif qui l'y aiderait (module 15). Les comparaisons systématiques publiées depuis 2022 continuent de donner l'avantage au boosting sur ce terrain, malgré les architectures tabulaires spécialisées.
8. Stacking
Trois façons de combiner des modèles : le vote ou la moyenne (simple, robuste), le blending pondéré (poids optimisés sur un jeu de validation) et le stacking, où un méta-modèle apprend à combiner les prédictions des modèles de base. La condition de réussite est toujours la même : les modèles combinés doivent se tromper différemment. Assembler cinq gradient boosting aux réglages voisins n'apporte rien ; combiner un modèle linéaire, un boosting et un k-NN apporte souvent quelques points.
Le stacking impose une précaution stricte : les prédictions servant à entraîner le méta-modèle doivent être produites hors échantillon, par validation croisée. Sinon le méta-modèle apprend sur des prédictions déjà ajustées sur ces points, et la fuite est garantie. StackingClassifier s'en charge automatiquement.
9. Clustering et détection d'anomalies
k-means minimise l'inertie intra-classe \(\sum_k \sum_{x \in C_k}\|x-\mu_k\|^2\) en alternant deux étapes jusqu'à stabilisation :
1. AFFECTATION : chaque point rejoint le centre le plus proche
2. MISE À JOUR : chaque centre se replace au barycentre de ses points
→ répéter. L'inertie décroît à chaque étape, donc l'algorithme converge
(vers un optimum LOCAL, qui dépend de l'initialisation → k-means++)Rapide et simple, mais il suppose des groupes sphériques de tailles comparables, exige de fixer \(k\) à l'avance, et affecte forcément tous les points — y compris les aberrants, qui déplacent les centres.
DBSCAN groupes de forme quelconque, détecte le BRUIT (points non affectés),
pas de k à fixer. Mais deux paramètres sensibles (eps, min_samples)
et souffre en grande dimension.
HDBSCAN version hiérarchique de DBSCAN : plus robuste, un seul paramètre
principal. Mon défaut quand la structure des groupes est inconnue.
Hiérarchique produit un dendrogramme : on choisit le nombre de groupes APRÈS coup,
en coupant l'arbre. O(n²) : réservé aux petits jeux, mais très parlant.
GMM mélange de gaussiennes : affectation PROBABILISTE, groupes
ellipsoïdaux, sélection de k par BIC. Le bon choix quand les groupes
se chevauchent.Évaluer un clustering est intrinsèquement ambigu, puisqu'il n'y a pas de vérité terrain. Le coefficient de silhouette compare, pour chaque point, sa distance moyenne à son groupe et au groupe voisin le plus proche : il varie de −1 à 1, et une valeur négative signale un point probablement mal affecté. La méthode du coude sur l'inertie est populaire mais souvent illisible. Le vrai critère reste l'utilité : un clustering est bon s'il produit des segments sur lesquels on peut agir différemment.
Détection d'anomalies : IsolationForest isole les points atypiques par découpes aléatoires — un point anormal se retrouve seul en peu de coupes, ce qui donne un score directement exploitable ; LocalOutlierFactor compare la densité locale d'un point à celle de ses voisins ; et l'erreur de reconstruction d'une PCA (module 8) ou d'un autoencodeur (module 16) fonctionne très bien quand les données ont une structure de faible rang.
10. Recherche d'hyperparamètres
GridSearchCV exhaustif sur une grille. Explose combinatoirement ; à réserver
à 2-3 paramètres peu nombreux.
RandomizedSearchCV tirage aléatoire. Meilleur que la grille dès 3+ paramètres :
seuls quelques-uns comptent vraiment, et l'aléatoire les
explore sur bien plus de valeurs distinctes.
HalvingRandomSearchCV successive halving : beaucoup de candidats sur peu de données,
puis on élimine les pires et on affine. Excellent rapport
coût/résultat.
Optuna (TPE) recherche bayésienne : un modèle probabiliste guide les essais.
Le meilleur choix quand chaque entraînement est coûteux (module 19).import optuna
def objectif(essai):
params = {
# échelle LOGARITHMIQUE pour les paramètres multiplicatifs
"learning_rate": essai.suggest_float("learning_rate", 1e-3, 0.3, log=True),
"num_leaves": essai.suggest_int("num_leaves", 15, 255, log=True),
"min_child_samples": essai.suggest_int("min_child_samples", 5, 200),
"subsample": essai.suggest_float("subsample", 0.5, 1.0),
"reg_lambda": essai.suggest_float("reg_lambda", 1e-3, 10, log=True),
}
scores = cross_val_score(LGBMClassifier(**params), X, y, cv=5,
scoring="average_precision")
return scores.mean()
etude = optuna.create_study(direction="maximize",
pruner=optuna.pruners.MedianPruner())
etude.optimize(objectif, n_trials=100, n_jobs=4)
print(etude.best_params, etude.best_value)
optuna.visualization.plot_param_importances(etude) # quels paramètres comptaientDeux règles pratiques : chercher sur une échelle logarithmique pour les paramètres multiplicatifs (taux d'apprentissage, \(C\), \(\lambda\)), et se rappeler que le gain d'un réglage fin — quelques pourcents — est presque toujours inférieur au gain d'une bonne variable ou de données supplémentaires. Optimiser 200 configurations en regardant le score de test transforme par ailleurs ce test en jeu d'entraînement (module 12).
11. Interprétabilité
- Importance par permutation — mélanger une colonne et mesurer la perte de performance. Global, fiable, agnostique au modèle ; à calculer sur un jeu de validation. Attention aux variables corrélées : mélanger l'une alors que l'autre porte la même information sous-estime les deux.
- PDP et ICE — le partial dependence plot montre l'effet moyen d'une variable sur la prédiction, en faisant varier cette variable pour tous les individus ; les courbes ICE font de même individu par individu et révèlent les effets hétérogènes que la moyenne masque (si la moitié des courbes monte et l'autre descend, le PDP est plat et trompeur).
- SHAP — issu de la théorie des jeux, il attribue à chaque variable sa contribution marginale moyenne sur tous les ordres d'inclusion possibles. C'est la seule méthode à satisfaire des axiomes d'équité (efficacité : les contributions somment à l'écart entre la prédiction et la moyenne ; symétrie ; nullité d'une variable inutile), avec une version exacte et rapide pour les arbres.
import shap explainer = shap.TreeExplainer(modele) valeurs = explainer(X_val) shap.plots.beeswarm(valeurs) # vue globale : importance ET sens de l'effet shap.plots.waterfall(valeurs[42]) # pourquoi CETTE prédiction : contribution par variable shap.plots.scatter(valeurs[:, "surface"], color=valeurs) # forme de l'effet + interaction
12. Tableau comparatif et pièges
Famille Forces Faiblesses Quand
──────────────────────────────────────────────────────────────────────────────────────
Linéaire/logit interprétable, rapide, suppose la linéarité, baseline,
calibré, fiable en petit n sensible à la colinéarité explication
Régularisé gère p > n, sélectionne réglage de λ nécessaire haute dimension
k-NN aucun apprentissage, coûteux en prédiction, petits jeux,
non linéaire fléau de la dimension recommandation
Naive Bayes très rapide, marche en très hypothèse d'indépendance texte,
haute dimension irréaliste baseline NLP
SVM noyau frontières complexes, robuste O(n²), pas de probas, n petit,
opaque, standardisation p grand
Arbre lisible, sans prétraitement instable, peu performant explication
seul
Random Forest robuste, peu de réglage, OOB modèle volumineux, moins défaut solide
précis que le boosting
Gradient boosting meilleur sur tabulaire, gère plus de réglages, sensible production
les manquants, early stopping au bruit des étiquettes tabulaire
Clustering découverte non supervisée évaluation ambiguë segmentationLes pièges qui reviennent le plus souvent
- Fuite de données — la cause n° 1 des scores mirobolants (module 12).
- Oublier la standardisation — pour les modèles à distance ou à gradient (k-NN, SVM, linéaires, réseaux). Les arbres, eux, s'en moquent complètement.
- Seuil laissé à 0,5 — c'est une valeur par défaut, pas une décision (module 24).
- Optimiser la mauvaise métrique — accuracy en classes déséquilibrées (module 8).
- Comparer des modèles sur un seul découpage — l'écart observé est souvent dans le bruit d'échantillonnage.
- Extrapoler — les modèles à base d'arbres prédisent une constante hors du domaine vu à l'entraînement : ils n'extrapolent pas. Sur une tendance temporelle croissante, c'est fatal, et un modèle linéaire fait mieux.
- Ignorer la calibration — nécessaire dès qu'on utilise la probabilité elle-même, et pas seulement l'ordre.
Ce qu'il faut retenir du module
- Capacité, biais et variance : les courbes d'apprentissage disent quoi faire ensuite.
- Toujours commencer par un modèle linéaire régularisé comme baseline.
- Bagging réduit la variance, boosting réduit le biais ; sur tabulaire, le gradient boosting est le défaut raisonnable.
- Se méfier de
feature_importances_; préférer permutation ou SHAP sur un jeu de validation. - Le clustering n'a pas de vérité terrain : le juger à son utilité.
- Une bonne variable vaut mieux qu'un réglage fin d'hyperparamètres.