← Blog

XGBoost pour prédire le taux de rebut en production

XGBoost appliqué à la prédiction qualité en temps réel. Feature importance sur les paramètres process, seuils adaptatifs, et intégration dans la boucle SPC.

Ce que j’ai vu sur une ligne d’injection plastique

Quatre-vingt-cinq pièces par heure. Taux de rebut habituel : 2,3 %. Le responsable qualité est content — c’est dans les clous du cahier des charges client.

Sauf que ce 2,3 % cache une dynamique que personne n’avait remarquée. Quand j’ai importé six mois de données SCADA — température moule, pression injection, temps de refroidissement, viscosité matière estimée, humidité ambiante, numéro de shift — un pattern est apparu clairement dans l’arbre de décision. Le taux de rebut grimpait systématiquement à 7-9 % dans une fenêtre de 40 minutes après chaque changement de lot matière, mais seulement quand la température ambiante dépassait 19°C et que la pression d’injection avait été ajustée en cours de shift.

L’opérateur ne voyait pas ce pattern. Il aurait fallu croiser manuellement quatre variables sur six mois. Personne n’a le temps de faire ça. Mais un XGBClassifier entraîné sur ces données, si.

Ce n’est pas un exemple fictif de consultant. C’est une situation réelle, un peu habillée pour l’article. Et c’est exactement le genre d’insight que le machine learning peut sortir — pas en remplacement du SPC, mais en complément.

Pourquoi le SPC classique montre ses limites

Le SPC est une technologie remarquable. Je l’ai dit dans l’article sur les cartes de contrôle : une carte Xbar-R correctement implémentée détecte les dérives 7 fois plus vite qu’un contrôle final. Je maintiens cette position.

Mais le SPC classique a une contrainte structurelle : il surveille une variable à la fois, ou au mieux deux (Xbar et R sur la même caractéristique). Il est construit sur l’hypothèse que le processus est stationnaire et qu’on peut isoler les causes spéciales en les cherchant dans une seule dimension.

La réalité d’une ligne de production moderne, c’est 15, 30, parfois 100 variables qui évoluent simultanément. La température de la salle, la pression hydraulique, la viscosité du lubrifiant qui change avec la température, le temps de cycle qui dérive quand l’opérateur enchaîne les pauses… Chacune de ces variables est individuellement dans les limites de contrôle SPC. Mais leur combinaison peut créer un état de processus hors contrôle que personne ne voit.

Le SPC détecte les dérives univariées. XGBoost détecte les interactions entre variables que l’œil humain ne peut pas croiser.

Ce ne sont pas des outils concurrents. Ils jouent dans des espaces différents. La suite de l’article montre comment les faire coopérer.

XGBoost en trois phrases pour le responsable qualité

XGBoost (Extreme Gradient Boosting) est un algorithme d’apprentissage supervisé basé sur des ensembles d’arbres de décision.

Version opérationnelle : vous lui donnez un historique de productions avec leurs paramètres process (entrées) et leur résultat qualité (sortie : conforme / non conforme, ou taux de rebut). L’algorithme construit une suite d’arbres de décision, chacun corrigeant les erreurs du précédent. Au bout de quelques centaines d’arbres, le modèle a appris les règles implicites qui lient les paramètres process au résultat qualité.

Au moment de la production, vous lui injectez les paramètres en temps réel. Il vous dit si la pièce en cours a une probabilité élevée d’être non conforme — avant même la mesure.

flowchart TD
    A[Données historiques\nSCADA + Qualité] --> B[Feature Engineering\nfenêtres glissantes, lags, ratios]
    B --> C[XGBClassifier\nEntraînement offline]
    C --> D[Modèle sérialisé\nmodel.ubj]
    
    E[Production temps réel\nparamètres process t₀] --> F[Feature Extraction\nidentique à l'entraînement]
    F --> D
    D --> G{Proba rebut}
    G -- "> 0.65 seuil alerte" --> H[Alerte opérateur\nSPC augmenté]
    G -- "< 0.65" --> I[Production normale\nSPC standard]
    
    H --> J[Action corrective\n+10 min avant rebut]
    J --> K[Feedback loop\nnouvelle donnée étiquetée]
    K --> A

Le pipeline complet : de la donnée brute à l’alerte

Étape 1 — Collecte et assemblage

Vous avez un historique SCADA qui enregistre les paramètres process à intervalle régulier (toutes les secondes, toutes les minutes selon la ligne). Vous avez un historique qualité : mesures Cpk, résultats go/no-go, taux de rebut par lot.

La première difficulté est la jointure temporelle. Le résultat qualité d’une pièce correspond à quels paramètres process exactement ? Si le cycle dure 45 secondes, les paramètres de fin de cycle influencent plus le résultat que ceux du début. Ce n’est pas une question triviale — c’est souvent là que les projets ML qualité ratent.

Règle pratique : définissez une fenêtre temporelle fixe (typiquement 2-5 cycles) et calculez des statistiques agrégées sur cette fenêtre pour chaque lot mesuré.

Étape 2 — Feature engineering

Les données brutes SCADA ne sont pas de bonnes variables d’entrée. Il faut les transformer.

Variable bruteFeatures dérivéesPourquoi
temperature_moulemean, std, max-min, lag-1, lag-5La tendance compte autant que la valeur
pression_injectionmean, max, variabilité relativeUn pic de pression est plus informatif qu’une moyenne
temps_cyclevaleur brute, dérive sur 10 cyclesUn drift lent est souvent précurseur
humidite_ambiantevaleur + rate of changeL’humidité en elle-même est moins utile que sa variation
shiftone-hot encodingShift de nuit / shift de jour ont des comportements différents
age_outilnombre de cycles depuis dernier changementL’usure outil est souvent le facteur #1 caché

Étape 3 — Entraînement du modèle

import pandas as pd
import numpy as np
import xgboost as xgb
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import classification_report, roc_auc_score
import shap
import matplotlib.pyplot as plt

# Chargement données
df = pd.read_parquet("data/production_labeled.parquet")

# Features et target
FEATURES = [
    "temp_moule_mean", "temp_moule_std", "temp_moule_lag1",
    "pression_inj_mean", "pression_inj_max", "pression_inj_variabilite",
    "temps_cycle_mean", "temps_cycle_drift_10",
    "humidite_mean", "humidite_roc",
    "age_outil_cycles",
    "shift_nuit",  # one-hot
]
TARGET = "rebut_binaire"  # 1 si taux_rebut > seuil, 0 sinon

X = df[FEATURES]
y = df[TARGET]

# Split temporel — IMPORTANT : ne pas mélanger passé/futur
# Les données de production ont une dimension temporelle
split_idx = int(len(df) * 0.8)
X_train, X_test = X.iloc[:split_idx], X.iloc[split_idx:]
y_train, y_test = y.iloc[:split_idx], y.iloc[split_idx:]

# Calcul du poids des classes (données déséquilibrées : rebuts rares)
neg, pos = y_train.value_counts()
scale_pos_weight = neg / pos  # typiquement 15-30 en production

# Entraînement XGBoost
model = xgb.XGBClassifier(
    n_estimators=400,
    max_depth=5,
    learning_rate=0.05,
    subsample=0.8,
    colsample_bytree=0.8,
    scale_pos_weight=scale_pos_weight,  # compensate class imbalance
    eval_metric="auc",
    early_stopping_rounds=20,
    random_state=42,
    device="cpu",  # edge deployment
)

model.fit(
    X_train, y_train,
    eval_set=[(X_test, y_test)],
    verbose=50,
)

# Évaluation
y_prob = model.predict_proba(X_test)[:, 1]
y_pred = (y_prob > 0.60).astype(int)  # seuil opérationnel, pas 0.5

print(classification_report(y_test, y_pred,
                             target_names=["Conforme", "Rebut probable"]))
print(f"AUC-ROC : {roc_auc_score(y_test, y_prob):.4f}")

# Sauvegarde modèle
model.save_model("models/xgb_qualite_v1.ubj")

Le point critique est le scale_pos_weight. En production, les rebuts représentent 2-5 % des pièces. Si vous entraînez sans corriger ce déséquilibre, le modèle apprend à toujours prédire “conforme” — il obtient 97 % d’accuracy sur le jeu de test tout en étant parfaitement inutile.

L’autre point est le split temporel. Ne faites jamais de train_test_split aléatoire sur des données de production. Vous entraîneriez sur des données futures et testeriez sur des données passées — le modèle serait fantastiquement précis sur le jeu de test et complètement à côté en production.

SHAP — expliquer les prédictions au responsable qualité

Un modèle qui prédit “probabilité de rebut : 78 %” sans explication est inutilisable sur le terrain. L’opérateur a besoin de savoir pourquoi le modèle tire la sonnette d’alarme — pour pouvoir agir.

SHAP (SHapley Additive exPlanations) décompose la prédiction du modèle en contributions individuelles de chaque variable. La valeur de Shapley de chaque feature représente sa contribution marginale à la prédiction pour cet exemple précis.

# Calcul des valeurs SHAP
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X_test)

# Waterfall plot — explication d'une prédiction individuelle
# "Lot 4872 — pourquoi 78% de risque rebut ?"
sample_idx = 42  # exemple à expliquer

shap.waterfall_plot(
    shap.Explanation(
        values=shap_values[sample_idx],
        base_values=explainer.expected_value,
        data=X_test.iloc[sample_idx],
        feature_names=FEATURES,
    ),
    max_display=10,
    show=True,
)

# Feature importance globale — quelles variables comptent le plus ?
shap.summary_plot(shap_values, X_test, plot_type="bar", show=True)

# Interaction — température moule × âge outil
shap.dependence_plot(
    "temp_moule_std",
    shap_values,
    X_test,
    interaction_index="age_outil_cycles",
    show=True,
)

Le waterfall plot pour un lot à risque élevé ressemble à ceci :

Prédiction : P(rebut) = 0.78
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Valeur de base                         0.038
+ age_outil_cycles (48 200)          +0.261
+ temp_moule_std (2.8°C)             +0.198
+ pression_inj_variabilite (12.3%)   +0.142
+ humidite_roc (+0.8%/h)             +0.087
+ temps_cycle_drift_10 (+0.9s)       +0.056
- temp_moule_mean (195.2°C)          -0.012
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Prédiction finale                      0.780

Ce que cela dit au responsable qualité : l’outil est proche de sa limite (48 200 cycles), la variabilité thermique du moule est anormalement haute ce matin, et la pression d’injection est instable. L’action est claire : vérifier l’état de l’outil et contrôler le circuit de régulation thermique.

SHAP transforme une boîte noire en liste d’actions opérationnelles. C’est la condition sine qua non du déploiement en production.

Comparaison des approches qualité

Il n’y a pas de solution universelle. Voici une comparaison honnête des trois approches.

CritèreSPC classiqueRégression logistiqueXGBoost + SHAP
Mise en œuvreSimple — Excel ou logiciel dédiéMoyen — Python ou RComplexe — data pipeline requis
Données requises50-100 sous-groupes500+ observations5 000+ observations étiquetées
Interactions entre variablesNonLimitée (termes croisés manuels)Oui — automatique
InterprétabilitéExcellente — lecture directe carteBonne — coefficientsExcellente avec SHAP
Détection dérive progressiveExcellente (CUSUM, EWMA)FaibleBonne (avec monitoring)
Détection état hors contrôle multi-variableFaibleMoyenExcellente
Maintenance du modèleRecalibration périodique Cp/CpkRe-entraînement trimestrielRe-entraînement mensuel + monitoring drift
Coût implémentationFaibleMoyenÉlevé (première fois)
Réentraînement automatiqueNon applicableOui — simpleOui — pipeline MLOps
Adapté àProcessus stables, univariésCauses connues, linéairesProcessus complexes, interactions non-linéaires

La régression logistique est souvent sous-estimée. Sur des problèmes qualité avec 3-5 facteurs identifiés, elle peut rivaliser avec XGBoost tout en étant 10 fois plus simple à déployer et à expliquer. Ne la rejetez pas par effet de mode.

XGBoost brille quand le nombre de variables est élevé (> 10), quand les interactions non-linéaires sont importantes, et quand vous avez suffisamment de données historiques étiquetées.

Intégration dans la boucle SPC existante

Le point critique que la plupart des articles ML qualité oublient : comment intégrer le modèle dans ce que les opérateurs font déjà.

Faire remplacer les cartes SPC par un tableau de bord ML, c’est une erreur. Ça créé de la résistance, ça détruit la confiance, et ça perd les bénéfices du SPC sur les dérives univariées simples.

La bonne approche est l’augmentation du SPC, pas son remplacement.

flowchart LR
    subgraph Production["Ligne de production"]
        P[Paramètres process\nt₀ → temps réel]
        M[Mesure pièce\ncontrôle statistique]
    end

    subgraph SPC_Classique["SPC existant"]
        X[Carte Xbar-R\npar caractéristique]
        C[Règles Western Electric\nCUSUM EWMA]
        X --> C
    end

    subgraph ML_Layer["Couche ML — XGBoost"]
        F[Feature extraction\nfenêtres glissantes]
        XG[XGBClassifier\ninférence < 50ms]
        SH[SHAP explainer\ntop 3 features]
        F --> XG --> SH
    end

    subgraph Alertes["Interface opérateur"]
        A1[Alerte SPC standard\ndérive univariée]
        A2[Alerte ML prédictive\nrebut imminent + cause]
        HMI[HMI / MES\naffichage unifié]
        A1 --> HMI
        A2 --> HMI
    end

    P --> F
    M --> X
    C --> A1
    SH --> A2

    HMI --> OP[Opérateur\naction corrective]
    OP --> Feedback[Feedback étiquetage\nré-entraînement mensuel]
    Feedback --> XG

Dans cette architecture, le SPC surveille chaque caractéristique individuellement avec les règles Western Electric habituelles. Le modèle ML tourne en parallèle sur les données process brutes et déclenche ses propres alertes, avec explication SHAP des 3 facteurs principaux.

L’opérateur voit les deux flux dans son HMI ou son MES. Si le SPC déclenche seul, il suit la procédure standard. Si le ML déclenche seul (avant que le SPC ne détecte quoi que ce soit), il peut anticiper. Si les deux déclenchent simultanément, c’est un signal fort — action prioritaire.

Ce qui change concrètement pour l’opérateur :

  • Même carte SPC qu’avant
  • Un indicateur supplémentaire : “Risque rebut ML : 72% — causes : variabilité température + âge outil”
  • Un bouton “Confirmer rebut / Pièce conforme” pour le feedback au modèle

C’est tout. Le workflow reste le même. L’intelligence ML s’ajoute sans disrupter.

Seuils adaptatifs — au-delà du 0.5 par défaut

Un classifieur sort une probabilité entre 0 et 1. La plupart des implémentations utilisent le seuil par défaut de 0.5 : au-dessus, c’est prédit comme “rebut”. C’est une erreur en contexte industriel.

Le bon seuil dépend du coût relatif des erreurs.

Type d’erreurDescriptionCoût
Faux positif (FP)On alerte pour une pièce qui sera conformeInterruption inutile, perte de productivité, fatigue des opérateurs = 15€/épisode estimé
Faux négatif (FN)On rate une pièce qui sera non conformeRebut non évité, potentiellement jusqu’au client = 200-2000€/pièce selon secteur

Dans la quasi-totalité des cas industriels, le faux négatif coûte 10 à 100 fois plus cher que le faux positif. Cela signifie qu’on doit baisser le seuil d’alerte — plutôt 0.35 ou 0.40 — pour augmenter le rappel (recall) au détriment de la précision.

from sklearn.metrics import precision_recall_curve, f1_score
import matplotlib.pyplot as plt

# Courbe précision-rappel
precisions, recalls, thresholds = precision_recall_curve(y_test, y_prob)

# Calcul du seuil optimal selon coût relatif FP/FN
cost_fp = 15    # euros — interruption opérateur
cost_fn = 500   # euros — rebut moyen atelier

# Score pondéré par les coûts
costs = []
for thresh in thresholds:
    y_pred_t = (y_prob >= thresh).astype(int)
    fp = ((y_pred_t == 1) & (y_test == 0)).sum()
    fn = ((y_pred_t == 0) & (y_test == 1)).sum()
    costs.append(fp * cost_fp + fn * cost_fn)

optimal_threshold = thresholds[np.argmin(costs)]
print(f"Seuil optimal (coût-aware) : {optimal_threshold:.3f}")

# En pratique : recalculer ce seuil à chaque re-entraînement
# Il évolue avec la distribution des données

Le seuil d’alerte est une décision business, pas un hyperparamètre technique. Impliquez le responsable qualité et le contrôleur de gestion dans ce choix.

Impact business — ce que vous pouvez réalistement attendre

Je vais donner des chiffres réalistes, pas des chiffres de slide commercial.

Scénario de référence :

  • Ligne produisant 400 pièces/heure, 2 shifts × 8h/j, 220 jours/an
  • Taux de rebut actuel : 2.8 % (soit ~18 000 rebuts/an)
  • Coût moyen d’un rebut : 45€ (matière + temps machine + contrôle)
  • Coût rebuts actuel : 810 000€/an

Résultats observés dans des déploiements comparables :

  • Détection précoce des états à risque : 65-75% des rebuts prévisibles sont anticipés
  • Réduction effective du taux de rebut total : 18 à 25% (les rebuts restants sont les imprévisibles — défauts matière aléatoires, etc.)
  • Réduction rebuts = 18 000 × 22% = 3 960 rebuts évités/an
  • Gain financier : 3 960 × 45€ = 178 200€/an

Coût du projet :

  • Implémentation initiale (data pipeline + modèle + intégration HMI) : 25 000 – 45 000€
  • Maintenance annuelle (re-entraînement, monitoring) : 8 000€/an
  • ROI an 1 : 3 à 6x. Payback < 4 mois après déploiement.

Ces chiffres supposent un jeu de données historiques propre (étiquetage qualité fiable sur 12+ mois), une intégration avec le SCADA ou MES existant, et une adoption par les opérateurs (formation + interface utilisable).

Si votre historique qualité est mal étiquetté ou que vos données SCADA ont des trous importants, divisez les gains par 2 et ajoutez 30 % au coût d’implémentation pour la phase de remise en forme des données.

Ce que XGBoost ne fait pas

Pour équilibrer : ce qu’on ne peut pas attendre de ce type de modèle.

Il ne prédit pas les défauts matière aléatoires. Si votre fournisseur livre un lot avec une inclusion métallique imprévue, aucun paramètre process ne l’annonce. C’est un défaut amont que le modèle ne peut pas détecter — car il n’en voit pas le précurseur.

Il ne remplace pas la capabilité process. Si votre Cpk est à 0.8, le problème n’est pas la détection — c’est que votre process est fondamentalement trop variable pour la tolérance client. Le ML ne résout pas la capabilité. Il optimise la détection dans l’enveloppe de variabilité existante.

Il dérive. Les modèles entraînés sur des données passées deviennent obsolètes. Un changement de matière première, un nouvel outil, une modification du réglage de base — et le modèle voit une distribution de données différente de celle sur laquelle il a été entraîné. Sans monitoring du drift et re-entraînement régulier (au minimum mensuel), les performances se dégradent silencieusement.

Il a besoin de retours. Un modèle sans feedback loop se dégrade. Chaque fois qu’un opérateur confirme ou infirme une alerte, c’est une nouvelle donnée étiquetée qui améliore le modèle suivant. Sans ce mécanisme de feedback, on abandonne la moitié de la valeur du système.

Démarrer — ce qu’il faut avoir avant de coder

Checklist avant de lancer un projet XGBoost qualité :

Données :

  • Historique SCADA ≥ 12 mois avec horodatage fiable
  • Historique qualité sur la même période, étiquetté par lot ou par pièce
  • Correspondance temporelle définie entre paramètres process et résultat qualité
  • < 20 % de valeurs manquantes sur les variables principales

Process :

  • Taux de rebut > 1 % (en dessous, le dataset sera trop déséquilibré)
  • Rebuts mesurables et étiquettés (pas juste “pièce rejetée” sans cause identifiée)
  • Au moins un technicien qui connaît le process disponible pour valider les features

Organisationnel :

  • Sponsor côté production ou qualité identifié
  • Engagement sur l’intégration HMI (sinon le modèle reste sur un laptop)
  • Plan de re-entraînement défini dès le départ

Si ces conditions sont remplies, les chances de succès sont élevées. Si deux ou trois cases sont vides, commencez par les remplir — le projet ML attendra.

Conclusion — le modèle comme extension du SPC

XGBoost ne remplace pas le responsable qualité. Il ne remplace pas le SPC. Il voit des patterns dans 20 variables simultanées que personne n’a le temps de croiser manuellement — et il les traduit en alertes actionnables grâce à SHAP.

La vraie valeur n’est pas dans la précision du modèle. Elle est dans la réduction du temps entre la dérive du processus et l’intervention corrective. Passer de 2 heures à 15 minutes, c’est la différence entre 200 rebuts et 30 rebuts sur un poste.

Le SPC reste le fondement. Il est simple, robuste, compris par tous. XGBoost est la couche de veille avancée au-dessus — pour les cas où les interactions entre variables sont trop complexes pour une carte de contrôle univariée.

Deux outils, deux espaces de détection, zéro conflit.


Vous avez un historique SCADA et un taux de rebut qui résiste aux actions SPC classiques ? Contactez BCUB3 pour un diagnostic data initial — on commence par regarder vos données avant de parler modèle.

Cet article vous a été utile ?

BCUB3 est une petite structure. Si vous pensez à un collègue ou un partenaire qui pourrait en tirer quelque chose, la meilleure manière de nous aider est de partager le lien. Et si vous avez un cas concret à discuter, parlons-en directement.

Prendre un RDV de cadrage