Bagging (Bootstrap Aggregating) : Guide Complet — Principes, Exemples et Implémentation Python

Bagging (Bootstrap Aggregating) : Guide Complet — Principes, Exemples et Implémentation Python

Bagging (Bootstrap Aggregating) : Guide complet — Principes, Exemples et Implémentation Python

Résumé

Le bagging (Bootstrap Aggregating) est une méthode d’ensemble introduite par Léo Breiman en 1996. Son principe est simple mais puissant : entraîner plusieurs modèles identiques sur des échantillons bootstrap (tirages avec remise) du jeu d’entraînement, puis agréger leurs prédictions par moyenne (régression) ou vote majoritaire (classification). Le bagging réduit considérablement la variance des modèles instables — comme les arbres de décision — sans augmenter le biais. Il forme le fondement théorique de nombreuses méthodes d’ensemble modernes, dont la Random Forest.


Principe mathématique du bagging bootstrap

Échantillonnage bootstrap

Soit un jeu d’entraînement D = {(x₁, y₁), …, (xₙ, yₙ)} de taille n. Le bootstrap consiste à générer B échantillons D₁, D₂, …, D_B de même taille n, chacun obtenu par tirage avec remise depuis D.

Pour chaque échantillon D_b, on entraîne un modèle f_b. Après les B entraînements, on dispose d’un ensemble de modèles {f₁, f₂, …, f_B}.

Agrégation des prédictions

En régression, la prédiction finale est la moyenne arithmétique :

ŷbagging(x) = (1/B) × Σ{b=1}^{B} f_b(x)

En classification, on utilise le vote majoritaire : la classe prédite est celle qui reçoit le plus de voix parmi les B modèles.

Réduction de variance

Supposons que chaque modèle f_b(x) ait la même variance σ² et que les modèles soient indépendants (approximation). La variance du prédicteur agrégé est :

Var(ŷ_bagging) = σ² / B

La variance diminue donc proportionnellement au nombre B de modèles. En pratique, les modèles ne sont pas parfaitement indépendants (ils partagent le même jeu d’origine), mais la réduction de variance reste substantielle — en particulier pour les modèles à haute variance comme les arbres de décision non élagués.

Note importante : le bagging n’a guère d’effet sur les modèles à faible variance et biais élevé (régression linéaire, par exemple). Son efficacité est maximale pour les algorithmes instables : ceux dont les prédictions varient fortement en réponse à de petits changements dans les données d’entraînement.

Probabilité d’inclusion bootstrap

Chaque observation a une probabilité de 1 − (1 − 1/n)ⁿ ≈ 1 − e⁻¹ ≈ 0,632 d’être sélectionnée dans un échantillon bootstrap donné. Environ 63,2 % des données originales apparaissent dans chaque échantillon, les 36,8 % restants constituent l’échantillon Out-of-Bag (OOB), utilisable pour l’estimation de l’erreur sans jeu de validation séparé.


Intuition : pourquoi le bagging bootstrap fonctionne

Imaginez que vous consultiez B médecins indépendants pour un diagnostic complexe. Chaque médecin a son propre raisonnement, ses propres biais, ses propres angles morts. Individuellement, chacun peut se tromper. Mais si vous prenez la décision majoritaire parmi les B avis, l’erreur collective est généralement moindre que celle d’un seul médecin.

Le bagging bootstrap applique exactement cette logique aux modèles de machine learning :

  • Chaque échantillon bootstrap est l’« expérience vécue » unique de chaque modèle.
  • Les modèles apprennent des patterns légèrement différents parce qu’ils voient des sous-ensembles différents des données.
  • En agrégeant, on lisse les erreurs idiosyncratiques de chaque modèle.

C’est l’équivalent algorithmique de la sagesse des foules : la moyenne de nombreuses opinions imparfaites est souvent meilleure que l’opinion la plus éclairée prise isolément.


Implémentation Python avec scikit-learn

BaggingClassifier sur DecisionTreeClassifier

Comparons un arbre de décision unique avec un ensemble baggé de 50 arbres :

from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import BaggingClassifier, RandomForestClassifier
from sklearn.metrics import accuracy_score, classification_report
import numpy as np

# Données synthétiques
X, y = make_classification(
    n_samples=5000, n_features=20, n_informative=15,
    n_redundant=5, random_state=42
)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

# Arbre de décision unique (profondeur non limitée)
tree = DecisionTreeClassifier(random_state=42)
tree.fit(X_train, y_train)
tree_pred = tree.predict(X_test)
tree_acc = accuracy_score(y_test, tree_pred)
print(f"Arbre seul         : {tree_acc:.4f}")

# Bagging de 50 arbres de décision
bagging = BaggingClassifier(
    estimator=DecisionTreeClassifier(),
    n_estimators=50,
    max_samples=1.0,
    bootstrap=True,
    random_state=42,
    n_jobs=-1
)
bagging.fit(X_train, y_train)
bag_pred = bagging.predict(X_test)
bag_acc = accuracy_score(y_test, bag_pred)
print(f"Bagging (50 arbres): {bag_acc:.4f}")

# Comparaison avec Random Forest
rf = RandomForestClassifier(n_estimators=50, random_state=42, n_jobs=-1)
rf.fit(X_train, y_train)
rf_acc = accuracy_score(y_test, rf.predict(X_test))
print(f"Random Forest      : {rf_acc:.4f}")

La différence est souvent frappante : un arbre profond surajuste (overfitting) et peut atteindre une précision correcte sur l’entraînement mais médiocre sur le test. Le bagging bootstrap réduit ce surajustement en moyennant les prédictions de 50 arbres qui ont chacun appris sur des données légèrement différentes.

BaggingRegressor pour la régression

from sklearn.datasets import make_regression
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import BaggingRegressor
from sklearn.metrics import mean_squared_error, r2_score

# Données de régression
X_reg, y_reg = make_regression(
    n_samples=3000, n_features=15, noise=15.0, random_state=42
)
X_train_r, X_test_r, y_train_r, y_test_r = train_test_split(
    X_reg, y_reg, test_size=0.2, random_state=42
)

# Arbre seul
tree_reg = DecisionTreeRegressor(random_state=42)
tree_reg.fit(X_train_r, y_train_r)
print(f"Arbre seul (MSE)   : {mean_squared_error(y_test_r, tree_reg.predict(X_test_r)):.2f}")

# BaggingRegressor
bag_reg = BaggingRegressor(
    estimator=DecisionTreeRegressor(),
    n_estimators=100,
    random_state=42
)
bag_reg.fit(X_train_r, y_train_r)
bag_pred_r = bag_reg.predict(X_test_r)
print(f"Bagging (MSE)      : {mean_squared_error(y_test_r, bag_pred_r):.2f}")
print(f"Bagging (R²)       : {r2_score(y_test_r, bag_pred_r):.4f}")

Estimation Out-of-Bag (OOB)

L’échantillon Out-of-Bag permet d’estimer l’erreur de généralisation sans jeu de validation séparé. Chaque observation est prédite par les modèles qui ne l’ont pas vue pendant l’entraînement :

bagging_oob = BaggingClassifier(
    estimator=DecisionTreeClassifier(),
    n_estimators=100,
    oob_score=True,
    random_state=42,
    n_jobs=-1
)
bagging_oob.fit(X_train, y_train)

print(f"Score OOB  : {bagging_oob.oob_score_:.4f}")
print(f"Score test : {bagging_oob.score(X_test, y_test):.4f}")

Le score OOB est une estimation non biaisée de la performance en généralisation, comparable à une validation croisée mais beaucoup plus rapide car elle réutilise l’entraînement existant.

Visualisation de la convergence du bagging

import matplotlib.pyplot as plt

# Analyse de la convergence en fonction du nombre d'estimateurs
scores = []
for n in range(1, 101):
    model = BaggingClassifier(
        estimator=DecisionTreeClassifier(),
        n_estimators=n,
        random_state=42
    )
    model.fit(X_train, y_train)
    scores.append(accuracy_score(y_test, model.predict(X_test)))

plt.figure(figsize=(10, 6))
plt.plot(range(1, 101), scores, marker='o', markersize=3,
         linewidth=1.5, color='steelblue')
plt.axhline(y=tree_acc, color='red', linestyle='--',
            label=f'Arbre seul ({tree_acc:.3f})')
plt.xlabel("Nombre d'estimateurs (B)")
plt.ylabel('Précision')
plt.title('Convergence du bagging bootstrap en fonction de B')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()

Cette courbe montre typiquement une amélioration rapide jusqu’à B ≈ 20-30, puis un plateau où ajouter des estimateurs n’apporte plus de gain significatif.


Hyperparamètres clés du bagging bootstrap

Paramètre Description Valeur par défaut Impact
n_estimators Nombre de modèles dans l’ensemble 10 ↑ améliore la réduction de variance, mais rend les gains marginaux au-delà d’un certain seuil
max_samples Proportion ou nombre d’échantillons par modèle 1.0 (100 %) Plus petit = plus de diversité, mais chaque modèle est moins précis
max_features Proportion ou nombre de features par modèle 1.0 Limiter augmente la diversité (principe de la Random Forest)
bootstrap Tirage avec remise des échantillons True Sans bootstrap, le bagging perd son effet de régularisation
bootstrap_features Tirage avec remise des features False Utile quand le nombre de features est très élevé
oob_score Calcul du score Out-of-Bag False Permet l’estimation de l’erreur sans validation croisée

Guide pratique de réglage

  • Commencez avec n_estimators=50 à 100. Augmenter au-delà de 100 apporte rarement un gain significatif.
  • max_samples=0.8 peut améliorer la diversité des modèles au prix d’une légère baisse de performance individuelle.
  • max_features < 1.0 transforme progressivement le bagging bootstrap en Random Forest : c’est le mécanisme de double randomisation (échantillons × features) qui rend la Random Forest si puissante.
  • Activez oob_score=True pour obtenir une estimation gratuite de la généralisation pendant l’entraînement.

Avantages du bagging bootstrap

  1. Réduction massive de la variance : particulièrement efficace pour les modèles instables (arbres de décision profonds, k-NN avec petit k, réseaux de neurones).
  2. Parallélisation triviale : chaque modèle f_b est entraîné indépendamment des autres — le bagging bootstrap s’adapte parfaitement au calcul distribué avec n_jobs=-1.
  3. Pas de surajustement accru : contrairement au boosting, le bagging ne surajuste pas quand on augmente B.
  4. Estimation OOB gratuite : l’échantillon Out-of-Bag fournit une validation intégrée sans coût supplémentaire.
  5. Simplicité conceptuelle : le principe est facile à expliquer et à implémenter.

Limites du bagging bootstrap

  1. Inefficace pour les modèles stables : la régression linéaire, la régression logistique ou les SVM linéaires bénéficient peu du bagging bootstrap car leur variance est déjà faible.
  2. Interprétabilité réduite : un ensemble de 100 arbres est beaucoup moins interprétable qu’un seul arbre.
  3. Coût computationnel : entraîner B modèles coûte B fois plus en temps et en mémoire.
  4. Pas de correction du biais : si les modèles de base ont un biais élevé (sous-apprentissage), le bagging ne le corrige pas — il ne réduit que la variance.
  5. Moins puissant que le boosting : dans de nombreux benchmarks, le gradient boosting et XGBoost surpassent le bagging simple en précision pure, au prix d’une plus grande complexité.
  6. Pas de sous-échantillonnage des features par défaut : contrairement à la Random Forest, le bagging standard utilise toutes les features pour chaque modèle, ce qui limite la diversité de l’ensemble.

4 cas d’usage concrets du bagging bootstrap

1. Détection de fraude bancaire

Les transactions frauduleuses sont rares et les données sont déséquilibrées. Un seul arbre de décision a tendance à surajuster sur les patterns spécifiques au jeu d’entraînement. Le bagging de 100 arbres, chacun entraîné sur un sous-échantillon bootstrap différent, capture une plus grande variété de schémas de fraude tout en réduisant les faux positifs :

bagging_fraud = BaggingClassifier(
    estimator=DecisionTreeClassifier(max_depth=8),
    n_estimators=100,
    max_samples=0.7,
    oob_score=True,
    random_state=42
)
bagging_fraud.fit(X_train_fraud, y_train_fraud)

2. Prédiction de prix immobilier

Les données immobilières contiennent de nombreuses interactions non linéaires entre les variables (quartier × surface × année de construction). Un BaggingRegressor avec 200 arbres capture ces interactions mieux qu’un modèle linéaire, tout en restant plus robuste qu’un seul arbre sujet au surajustement.

3. Diagnostic médical assisté

L’analogie des médecins multiples est ici littérale : entraîner 50 classifieurs sur des échantillons bootstrap de données médicales permet de combiner différentes « perspectives » sur les mêmes symptômes, réduisant le risque qu’un pattern aberrant dans l’ensemble d’entraînement influence le diagnostic final. Le score OOB offre une validation rigoureuse sans réduire la taille du jeu d’entraînement.

4. Classification de texte avec des classifieurs faibles

On peut appliquer le bagging bootstrap à n’importe quel classifieur. Par exemple, des classifieurs Naïve Bayes individuellement médiocres sur un corpus de texte peuvent atteindre une précision remarquable quand on en agrège 50 par vote majoritaire — chaque classifieur capturant des aspects différents du vocabulaire grâce aux échantillons bootstrap.


Le bagging bootstrap dans l’écosystème des méthodes d’ensemble

Le bagging occupe une place centrale dans la famille des méthodes d’ensemble :

  • Random Forest = bagging + sélection aléatoire des features (article #025). C’est le cas le plus célèbre et le plus utilisé du bagging bootstrap.
  • AdaBoost = pondération adaptative des échantillons mal classés (article #030). Contrairement au bagging, les échantillons sont tirés sans remise avec des poids ajustés.
  • Gradient Boosting = apprentissage séquentiel des erreurs résiduelles (article #027). Chaque modèle corrige les erreurs du précédent, là où le bagging entraîne tous les modèles en parallèle.

La distinction fondamentale est claire : le bagging cherche à réduire la variance par agrégation de modèles indépendants, tandis que le boosting cherche à réduire le biais par apprentissage séquentiel des erreurs.


Conclusion

Le bagging bootstrap est l’une des idées les plus élégantes du machine learning moderne. En exploitant la puissance de la moyenne sur des modèles entraînés sur des échantillons bootstrap différents, il transforme des algorithmes instables en prédicteurs robustes et fiables. Bien que des méthodes plus sophistiquées comme le gradient boosting le dépassent en précision brute sur certains benchmarks, le bagging reste incontournable pour sa simplicité, sa parallélisation native et sa résistance au surajustement.

Pour tout problème où un arbre de décision seul surajuste, le bagging bootstrap est la première amélioration à tenter — souvent avec des résultats remarquables.


Voir aussi

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur la façon dont les données de vos commentaires sont traitées.