Leçon : Analyse de l'erreur en machine learning¶

Introduction & définition¶

En machine learning, il s'agit du processus visant à isoler, observer et diagnostiquer les erreurs de vos modèles.

Cette analyse est une étape indispensable pour améliorer un modèle de machine learning, que ce soit sa performances et capacité de généralisation, ou son interprétablité, afin de guider vos futures itératations.

Elle s'applique à différent moment du cycle de vie d'un modèle :

  • à la fois avant la mise en production, pour minimiser les futures erreurs du modèles
  • et en production pour éviter que les performances et l'interprétabilité du modèle ne dérive pas (concept de model drit)

Principes génériques¶

Même si l'analyse de l'erreur dépend de votre, problème, on peut dégager quelques principes génériques ci-dessous.

En première itération¶

Avant de s'ateler à l'analyse de l'erreur, il est souvent nécessaire d'avoir traité des étapes préalables :

  • S'assurer de la bonne qualité des données (en avez vous une description détaillée ? contiennent t'elles des erreurs ?)
  • construit un modèle de référence (baseline)
  • entrainé un 1er modèle simple
  • défini une ou plusieurs métriques d'évaluation adaptée.s au problème
  • comparer votre modèle à celui de référence

Itérer pour améliorer le modèle¶

Itérer, en améliorant les points suivants :

  • Tracer des courbes d'apprentissage
  • Gérer les potentiels problèmes d'apprentissage (régularisation, sélection de variable, enrichissement de données)
  • Affiner la cross validation

Réaliser l'analyse de l'erreur¶

  • Identifier des sous groupe de données ayant conduit à des erreurs et analyser leur caractéristiques
  • Mettre en place des tests automatisés (qui peuvent mesurer l'écart par rapport à l'itération précédante ou bien une évaluation des performances d'observations causant des erreurs)
  • Vérifier les dérives de vos modèles en production

Le modèle de référence (baseline)¶

Il s'agit d'un modèle qui vous sert de point de comparaison aux moins aux premières itérations d'un modèle

Il peut s'agir d'un résultat provenant de l'état de l'art du domaine étudié, par exemple:

  • un modèle physique pour la prédiction du réchauffement climatique
  • la performance d'un humain sur la même tache

Ou sinon d'un modèle stupide donnant une réponse stéréotypée, par exemple:

  • donner une réponse aléaroire
  • pour la classification: prédire la classe la plus fréquente
  • pour la régression: prédire une mesure de tendance centrale (moyenne, médiane, mode)
  • ...

Par la suite, les itérations plus avancées d'amélioration de votre modèles peuvent être utilisées comme nouvelle référence

Changer, affiner, ajouter une métrique d'évaluation¶

Comme nous l'avons vu dans la leçon dédiée, il convient de choisir ces métriques en fonction des caractétistiques du problème à résoudre (comme dans les tâches de classification, régression, ou clustering)

Même pour un problème donné, il peut être intéressant de changer de métrique d'évaluation, par exemple dans le cas d'un data set ayant des classes déséquilibrées, la simple accuracy sera une métrique trop confiante.

Il vaut mieux dans ce cas choisir des métriques prenant en compte ce déséquilibre, comme la balanced accuracy ou y étant moins affecté, comme l'aire sous la courbe ROC

Pour aller plus loin, il est conseillé d'évaluer son modèle en production avec un ensemble de plusieurs métriques, comme le conseille cet article

Tracer les courbes d'apprentissage¶

Elle permettent de diagnostiquer l'état du compromis de sous apprentissage/sur apprentissage de votre modèle.

Comparaison de courbes d'apprentissage pour deux modèles linéaires

Voir cet article vulgarisé pour plus de détails concernant leur interprétation

Gérer un modèle qui sur apprend¶

  • détecter et corriger des potentiels outliers
  • afiner la méthode de validation croisée utilisée
  • appliquer de la régularisation (souvent une régularisation L1 ou L2)
  • réduire le nombre de variable par des méthodes de sélections de variable
  • utiliser des méthodes ensemblistes de type bagging

Détecter des potentielles données abérantes (outliers)¶

Certains modèles (comme la régression linéaire estimée avec les moindres carrés) sont très sensibles aux données abérantes, ce qui peut conduire à un sur apprentissage.

Il convient dans ce cas d'améliorer son exploration des données en faisant des grahiques pour détecter les outliers et/ou utiliser des méthodes algorithmiques pour leur détection

Exemple — détection d'outliers et impact sur une régression linéaire

On simule l'ajout d'outliers extrêmes sur la variable cible, et on observe leur impact visuel (boxplot) et quantitatif (RMSE) :

In [1]:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_diabetes
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error

# --- Chargement des données (dataset Diabetes, tâche de régression) ---
diabetes = load_diabetes()
X, y = diabetes.data, diabetes.target

# --- Simulation d'outliers extrêmes sur la variable cible ---
np.random.seed(42)
y_with_outliers = y.copy()
outlier_idx = [10, 42, 100, 180, 300]
y_with_outliers[outlier_idx] += [350, -250, 400, -300, 450]
In [2]:
# --- Visualisation : boxplots (méthode IQR) ---
fig, axes = plt.subplots(1, 2, figsize=(11, 4))
bp_props = dict(patch_artist=True)

for ax, data, title, color in zip(
    axes,
    [y, y_with_outliers],
    ["Variable cible — données originales", "Variable cible — avec outliers artificiels"],
    ["steelblue", "coral"]
):
    bp = ax.boxplot(data, patch_artist=True, widths=0.4)
    bp["boxes"][0].set_facecolor(color)
    bp["boxes"][0].set_alpha(0.7)
    ax.set_title(title, fontsize=11)
    ax.set_ylabel("Progression du diabète")
    ax.set_xticks([])

plt.suptitle("Détection d'outliers par boxplot — les points hors moustaches sont suspects", fontsize=12)
plt.tight_layout()
plt.show()
No description has been provided for this image
In [3]:
# --- Impact quantitatif sur le modèle de régression ---
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
X_train_o, _, y_train_o, _ = train_test_split(X, y_with_outliers, test_size=0.2, random_state=42)

lr_clean = LinearRegression().fit(X_train, y_train)
lr_out = LinearRegression().fit(X_train_o, y_train_o)

rmse_clean = np.sqrt(mean_squared_error(y_test, lr_clean.predict(X_test)))
rmse_out   = np.sqrt(mean_squared_error(y_test, lr_out.predict(X_test)))

print(f"RMSE (sans outliers) : {rmse_clean:.2f}")
print(f"RMSE (avec outliers) : {rmse_out:.2f}")
print(f"→ Les outliers d'entraînement dégradent le RMSE de +{rmse_out - rmse_clean:.2f} points")
RMSE (sans outliers) : 53.85
RMSE (avec outliers) : 53.11
→ Les outliers d'entraînement dégradent le RMSE de +-0.74 points

Affiner la méthode de validation croisée utilisée¶

En fonction de la distribution de vos données, il peut être utile d'affiner la méthode de validation croisée utilisée plutôt que d'utiliser une classique k-fold:

  • en faisant varier le nombre de fold (en pratique on conseille 5 ou 10 folds)
  • utiliser des méthodes plus fines comme la validation croisée stratifiée, pour mieux prendre en compte la répartition des classes dans les partitions générées lors de la validation croisée

Appliquer de la régularisation à votre modèle¶

La régularisation introduit, au moment de l'apprentissage, une contrainte visant à limiter l'amplitude des paramètres qui vont être appris, de manière à privilégier un modèle ayant une variance plus faible de sorte à obtenir un modèle plus "lisse":

Cela se manifeste par un terme additionnel dans la fonction de perte :

$Loss(\theta) + \alpha{||\theta||}^2$ avec $\alpha$ le paramètre controlant la force de la régularisation

Il est courant d'utiliser la norme $L_2 = \sum_{i} \theta{_i}^2$ ou la norme $L_1 = \sum_{i} |\theta{_i}|$ dans ce calcul, celle-ci ayant des effets un peu différents (voir par ex cet article pour plus de détails)

Exemple : calcul du lasso path

In [4]:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_diabetes
from sklearn.linear_model import lasso_path
from sklearn.preprocessing import StandardScaler

# Chargement et normalisation (indispensable avant la régularisation)
diabetes = load_diabetes()
X, y = diabetes.data, diabetes.target
X_scaled = StandardScaler().fit_transform(X)

# Calcul du Lasso path (du alpha max → alpha min)
alphas, coefs, _ = lasso_path(X_scaled, y, eps=5e-3, n_alphas=100)
In [5]:
# Visualisation
fig, ax = plt.subplots(figsize=(11, 5))
for i, name in enumerate(diabetes.feature_names):
    ax.plot(np.log10(alphas), coefs[i], label=name, linewidth=1.8)

# Annotation : zone de forte vs faible régularisation
ax.axvspan(ax.get_xlim()[0], np.log10(alphas).mean(), alpha=0.05, color='red')
ax.axvspan(np.log10(alphas).mean(), ax.get_xlim()[1], alpha=0.05, color='green')
ax.text(np.log10(alphas[5]), coefs.max() * 0.85, "forte\nrégularisation\n(coefs → 0)", color='red', fontsize=9)
ax.text(np.log10(alphas[-10]), coefs.max() * 0.85, "faible\nrégularisation\n(coefs → OLS)", color='green', fontsize=9)

ax.axhline(0, color='black', linewidth=0.8, linestyle='--')
ax.invert_xaxis()   # alpha décroît de gauche (fort) à droite (faible)
ax.set_xlabel("log₁₀(α) — force de régularisation (L1)")
ax.set_ylabel("Valeur des coefficients")
ax.set_title("Lasso path sur le dataset Diabetes\n"
             "→ les features dont le coefficient touche 0 en premier sont les moins informatives")
ax.legend(loc='lower right', fontsize=8, ncol=2)
plt.tight_layout()
plt.show()
No description has been provided for this image

Exemple — Lasso path : comment la régularisation L1 réduit les coefficients

Le coefficient path montre comment les coefficients de chaque feature évoluent quand on augmente la force de la régularisation $\alpha$. Avec Lasso (L1), certains coefficients tombent exactement à zéro — ce qui opère une sélection automatique de features :

Certains modèles intégrent un paramètre ou hyper-paramètres de régularisation:

  • la régression ridge, une variante de la régression linéaire avec un terme de régularisation $L_2$
  • la régression lasso, une variante de la régression linéaire avec un terme de régularisation $L_1$
  • elastic net, une régression linéaire qui combine une régularisation $L_1$ et $L_2$
  • la régression logistique via son paramètre penalty
  • SVM qui possède naturellement un hyper paramètre C controlant la force de la régularisation à appliquer (voir cet exemple avec SVC pous plus de détails)
  • les réseaux de neurones en général, comme le MultiLayer Perceptron possède une terme de régularisation. Il existe aussi une méthode spécifique au réseaux de neurones, le dropout
  • les modèles ensemblistes de gradient boosting peuvent également produire un effet similaire à la régularisation en diminuant sur le learning rate (learning rate <1)
  • ...

Utiliser des méthodes de sélections de features¶

Ces méthodes visent à rendre votre modèles plus parcimonieux, en ne gardant que les variables les plus informatives pour votre modèle tout en conservant de bonnes performances

Utiliser des modèles enseblistes de bagging¶

Ces méta modèles consistent à entraîner en parallèle un grand nombre de modèles individuels. Le méta modèle ainsi crée tend à produire un modèle ayant une variance moindre par rapport aux modèle individuel (modèle moins felxible) et donc contribue à diminuer le sur apprentissage

Gérer un modèle qui sous apprend :¶

  • affiner votre optimisation des paramètres
  • utiliser un modèle plus complexe
  • enrichir vos données: augmentation de données, creation de features, collecter de nouvelles données

Affiner l'optimisation des paramètres¶

Les mauvaises performances obtenues avec un modèles peuvent être dues à une mauvaise optmisation, qu'il est possible d'affiner en:

  • en affinant la grille des paramètres testés de votre GridSearch : il est souvent intéressant de combiner deux itérations, une première grossière, en testant des ordres de grandeurs différents, puis une seconde plus précise autour des valeurs pré-identifiées
  • changeant de méthode d'optimisation (par exemple en utilisant le HalvingGridSearch ou des méthodes plus généralistes comme la descente de gradient ou l'optimisation bayésienne)

Utiliser une modèle plus complexe¶

Un modèle qui sous apprend est probablement trop peu complexe pour le problème à modéliser, c.a.d qu'il ne contient pas assez de paramètres, ou encore il est trop simpliste et ne parviens pas à capturer des propriétés suffisament complexe dans les données. Voici quelques possibilités :

  • essayer un modèle non linéaire pour capturer des comportements non linéaires des données
  • utiliser des features additionnelles non linéaires (comme les features ploynomiales)
  • complexifier l'architecture du modèle (ajouter plus de termes de puissance élevée dans une régression, plus de neurones/couches dans un réseau de de neurone)
  • utiliser des modèles ensemblistes de boosting ou de stacking

Enrichir vos données¶

Le sous apprentissage peut tout simplement être du à une qualité des données insuffisantes : volume insufisant, données peu représentatives, ... Dans ce cas, une solution est d'enrichir les données de plusieurs manières

  • en créeant des transformations à appliquer aux données pour fabriquer de nouvelles observations (très courant avec les images)
  • en collectant de nouvelles données (observations et/ou features)
  • en créant des features additionnelles

Identifier et analyser les erreurs d'évaluation¶

Enfin, analyser de manière exhaustive les erreurs produite par votre modèle est indispensable pour l'améliorer dans les itérations suivantes

Il est souvent conseillé d'identifier et concentrer ses efforts sur les groupes d'erreurs impactant le plus le modèle !

Erreur globale¶

Dans cette phase de l'analyse de données, il s'agit d'étendre l'analyse exploratoire de donnée pour comprendre et mesurer le niveau d'erreur global des prédictions.

Voici certaines analyses qu'il peut être intéressant de produire :

  • la matrice de confusion (pour la classification)
  • l'intervalle de confiance des prédictions
  • comparer la distribution des prédictions à celle des labels
  • ....

Analyse des erreurs spécifiques à certains modèles¶

La plupart des modèles en machine learning sont des modèles statistiques dont certains reposent sur des hypothèses préalables afin d'être valables (au risque de ne pas pouvoir estimer le modèle ou donne des estimations biaisées)

C'est le cas de la plupart des modèles de régression, comme la régression linéaire qui suppose au préalable:

  • que les features ne sont pas colinéaires
  • que les erreurs residuelle $\epsilon_1, \epsilon_2, ...\epsilon_n$ soient indépendantes et identiquement distribuées
  • que les features ne sont pas corrélées aux erreurs résiduelles (exogéneité)
  • que la variance des erreurs résiduelles est identique pour chaque observation (homoscédasticité)

Dans l'exemple de la régression linéaire, on vérifiera ces hypothèses des tests dédiés (test d'hétéroscédasctitité, test d'indépendance) ou en faisant une analyse complète des résidus

Penchez vous sur les mathématiques propres à chaque modèle pour effectuer les analyses d'erreurs préalables adaptées !

Exemple — analyse graphique des résidus d'une régression linéaire

Trois graphiques complémentaires pour vérifier les hypothèses du modèle :

  • Distribution des résidus → vérifier la normalité (≈ cloche centrée en 0)
  • Résidus vs valeurs prédites → vérifier l'homoscédasticité (répartition uniforme autour de 0)
  • QQ-plot → vérifier que les résidus suivent bien une loi normale
In [6]:
import numpy as np
import matplotlib.pyplot as plt
import scipy.stats as stats
from sklearn.datasets import load_diabetes
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split

# Données et modèle
diabetes = load_diabetes()
X, y = diabetes.data, diabetes.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

model = LinearRegression().fit(X_train, y_train)
y_pred = model.predict(X_test)
residuals = y_test - y_pred
In [7]:
# Figure : 3 graphes d'analyse des résidus
fig, axes = plt.subplots(1, 3, figsize=(15, 4))

# 1. Distribution des résidus (normalité)
axes[0].hist(residuals, bins=25, color='steelblue', alpha=0.75, edgecolor='white')
axes[0].axvline(0, color='red', linestyle='--', linewidth=1.5, label='μ = 0 (attendu)')
axes[0].set_title("Distribution des résidus\n→ normalité attendue (forme de cloche)", fontsize=10)
axes[0].set_xlabel("Résidus (y_test − ŷ)")
axes[0].set_ylabel("Fréquence")
axes[0].legend(fontsize=9)

# 2. Résidus vs valeurs prédites (homoscédasticité)
axes[1].scatter(y_pred, residuals, alpha=0.45, color='steelblue', s=20)
axes[1].axhline(0, color='red', linestyle='--', linewidth=1.5)
axes[1].set_title("Résidus vs valeurs prédites\n→ homoscédasticité : nuage bien centré en 0", fontsize=10)
axes[1].set_xlabel("Valeurs prédites (ŷ)")
axes[1].set_ylabel("Résidus")

# 3. QQ-plot (comparaison à une loi normale)
stats.probplot(residuals, dist="norm", plot=axes[2])
axes[2].set_title("QQ-plot des résidus\n→ normalité : points alignés sur la droite", fontsize=10)

plt.suptitle("Analyse des résidus — Régression linéaire (dataset Diabetes)", fontsize=12, y=1.02)
plt.tight_layout()
No description has been provided for this image
In [8]:
print(f"Moyenne des résidus : {residuals.mean():.3f}  (attendu : ≈ 0)");
print(f"Écart-type des résidus : {residuals.std():.2f}");
Moyenne des résidus : 3.913  (attendu : ≈ 0)
Écart-type des résidus : 53.71

Analyse des erreurs par groupes¶

Une première itération conseillée est de repérer des groupes caractéristiques pouvant être sources d'erreurs particulières, par exemple un groupe produisant sur estimation ou sous estimation systématique, et/ou un groupe responsable d'une grande part de l'erreur totale.

Voici quelques exemples de groupes à examiner :

  • des observations associées à certaines classes (en particulier celles sous représentées)
  • des quantiles, clusters de variables, ou des méthodes de manifold
  • observations visuelle d'échantillons du data set
Analyser les observations des classes les moins fréquentes¶

En général, ces observations auront tendeance à causer plus d'erreurs, car elles auront été "vues" moins souvent par votre modèle lors de l'apprentissage, surtout lorsque le déséquilibre des classes est important

Solutions potentielles

Si le déséquilibre des classes n'est pas trop impactant sur l'erreur, il est possible de minimiser l'erreur produite par le modèle en favorisant une méthode de validation croisée stratifiée

Si ces observations conduisent à des erreurs systématiques, il est conseillé de les ré-équilibrer, souvent par des méthodes de sous échantillonnage de la classe majoritaire ou de sur echantillonnage de la classe minoritaire. Il existe des packages spécifiques pour gérer ce problème comme imbalanced-learn

Exemple — distribution de l'erreur par décile de la variable cible

Ce graphe permet d'identifier rapidement pour quelles valeurs de la cible le modèle se trompe le plus. Ici, on compare l'erreur absolue moyenne sur chaque décile de la variable cible :

Afin de mieux comprendre l'influence de certaines variables continues sur la performance, il est parfois plus facile de les découper en quantiles pour examiner leur impact quantile par quantile.

In [9]:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_diabetes
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split

# Données et modèle
diabetes = load_diabetes()
X, y = diabetes.data, diabetes.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

model = LinearRegression().fit(X_train, y_train)
y_pred = model.predict(X_test)

# DataFrame pour l'analyse par groupe
df_err = pd.DataFrame({
    'y_test'    : y_test,
    'y_pred'    : y_pred,
    'erreur_abs': np.abs(y_test - y_pred)
})
df_err['decile'] = pd.qcut(df_err['y_test'], q=10, labels=[f"D{i}" for i in range(1, 11)])

decile_stats = df_err.groupby('decile',observed=True)['erreur_abs'].agg(['mean', 'count'])
In [13]:
# Visualisation
fig, ax = plt.subplots(figsize=(11, 4))
bars = ax.bar(decile_stats.index, decile_stats['mean'],
              color=['coral' if v > df_err['erreur_abs'].mean() else 'steelblue'
                     for v in decile_stats['mean']],
              alpha=0.8, edgecolor='white')

ax.axhline(df_err['erreur_abs'].mean(), color='black', linestyle='--',
           linewidth=1.5, label=f"Erreur moyenne globale : {df_err['erreur_abs'].mean():.1f}")
ax.set_title("Erreur absolue moyenne par décile de la variable cible\n"
             "→ en rouge : déciles où le modèle se trompe le plus (au-dessus de la moyenne)", fontsize=11)
ax.set_xlabel("Décile de la progression du diabète (D1 = faible, D10 = forte)")
ax.set_ylabel("Erreur absolue moyenne (MAE)")
ax.legend(fontsize=9)
plt.tight_layout()
plt.show()

print("Taille des déciles :", dict(decile_stats['count']));
No description has been provided for this image
Taille des déciles : {'D1': np.int64(10), 'D2': np.int64(8), 'D3': np.int64(9), 'D4': np.int64(9), 'D5': np.int64(9), 'D6': np.int64(8), 'D7': np.int64(9), 'D8': np.int64(9), 'D9': np.int64(9), 'D10': np.int64(9)}

De même pour des tâches supervisées, un clustering préalable des données peut permettre d'identifier des groupes de variables et d'observations qui ont un comportement particulier.

Une solution peut consister à supprimer de la modélisation certains clusters ou à utiliser une modèle différents sur ces clusters, comme par exemple pour des applications de santé ou il est courant d'entrainer différents modèles sur différents groupes de patients

Pour les tâches non supervisées, examiner quelques caractéristiques (tendeance centrale, variabilité) des points des clusters formés peut vous aider à comprendre les données ayant été groupées de manière erronnée ou les clusters qui pourraient être sur-numéraires (pour de nombreux modèles, le nombr de clusters est un hyperparamètre)

Examen visuel d'échantillons du data set¶

Dans certains cas, les erreurs peuvent provenir d'une mauvaise annotation des certaines parties données (c'est assez courant avec les images), causant des erreurs impossibles à corriger si non détectées

Dans ce cas, une solution peut constituer à examiner visuellement des échantillons pris au hasard des données afin de se faire une idée

Erreurs individuelles¶

Il s'agit d'erreurs dues à des observations ou variables individuelles. Affiner l'analyse exploratoire préalable est souvent la meilleure chose à faire pour les détecter !

Les données abérantes sont un exemple particulièrement important de données individuelles que vous souhaitez gérér en priorité :

  • en les supprimant ou les corrigeant (si elles paraissent erronnées)
  • en utilisant un modèle robuste aux outliers (par exemple des régressions robustes)

Conseils génériques¶

Exemple — importance des features par permutation

La permutation importance mesure la dégradation du score R² quand on mélange aléatoirement les valeurs d'une feature. Plus la dégradation est grande, plus la feature est importante. C'est une méthode agnostique au modèle (fonctionne avec n'importe quel estimateur) :

L'analyse des erreurs demande une compréhension fine du problème et des données et leur traitement nécessite souvent une approche adaptive (il n'y a pas de méthode absolue) et itérative (il faut souvent plusieurs étapes)

In [11]:
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.datasets import load_diabetes
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.model_selection import train_test_split
from sklearn.inspection import permutation_importance

# Données et modèle
diabetes = load_diabetes()
X, y = diabetes.data, diabetes.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

model = GradientBoostingRegressor(n_estimators=100, random_state=42).fit(X_train, y_train)
print(f"Score R² sur le test set : {model.score(X_test, y_test):.3f}")

# Permutation importance (n_repeats=20 pour réduire la variance de l'estimateur)
result = permutation_importance(model, X_test, y_test, n_repeats=20, random_state=42, scoring='r2')

imp_df = pd.DataFrame({
    'feature'        : diabetes.feature_names,
    'importance_mean': result.importances_mean,
    'importance_std' : result.importances_std
}).sort_values('importance_mean')
Score R² sur le test set : 0.453
In [12]:
# Visualisation
fig, ax = plt.subplots(figsize=(8, 5))
ax.barh(imp_df['feature'], imp_df['importance_mean'],
        xerr=imp_df['importance_std'], color='steelblue', alpha=0.8, capsize=4, edgecolor='white')
ax.axvline(0, color='gray', linestyle='--', linewidth=0.8)
ax.set_title("Importance des features par permutation — GradientBoosting (Diabetes)\n"
             "→ chute du score R² quand la feature est mélangée aléatoirement", fontsize=10)
ax.set_xlabel("Diminution du score R² (± écart-type sur 20 répétitions)")
plt.tight_layout()
plt.show()

print("\nTop 3 features les plus importantes :")
for _, row in imp_df.tail(3).iterrows():
    print(f"  {row['feature']:5s} : {row['importance_mean']:.4f} ± {row['importance_std']:.4f}")
No description has been provided for this image
Top 3 features les plus importantes :
  sex   : 0.0640 ± 0.0198
  bmi   : 0.2457 ± 0.0614
  s5    : 0.3255 ± 0.0860

Cadre de travail¶

Voici néanmoins un cadre de travail générique à appliquer itérativement :

  1. identifier les erreurs et les discriminer en fonction de leur impacts

  2. se concentrer en priorité sur les erreurs impactant le plus le modèle (outliers, groupes caractéristiques, ...)

  3. construire une hypothèse de la cause de ces erreurs

  4. tester l'impact de cette hypothèse sur les performances et/ou l'interprétabilité

  5. répéter

Idées de processus et d'analyses¶

  • Evaluer son modèle avec un aggrégat de plusieurs métriques

  • Observer la couverture des erreurs (en comparant les labels et leur prédictions)

  • Analyser les relations entre les variables, par exemple avec les partial depence plot (PDP) et individual conditional plot (ICE)

  • Vérifier l'importance des features pour le modèles (en utilisant par exemple les modules LIME ou SHAP)

  • Observer les propriétés des données erronnées pour identifier des causes potentielles d'erreurs:

    • examen visuel (image, texte)
    • graphiques de couverture des erreurs (carte de chaleur, nuage de point, ..)
    • ..
  • Analyse des residus (dans le cas de modèles statistiques)

  • Intervalle de confiance des prédictions

  • Examiner les clusters formés en regardant leur statistiques descriptives (dans le cas du clusering ou pré-clustering)

  • Vérifier l'équilibrage des classes et les ré-équilibrer (pour la classification)

Quelques paquets pour l'analyse exploratoire et l'analyse de l'erreur¶

  • yellowbricks est un paquet utilisé pour l'enseignement, facilitant l'analyse exploratoire en incluant des visualisations adaptées
  • deepchecks est un paquet spécialisé dans la création de tests automatisés pour la validation des modèles en machine learning
  • la toolbox error analysis (du paquet Responsible AI Toolbox) est une module dédié à l'analyse exploratoire et analyse de l'erreur utilisant des interfaces utilisateurs

Demo avec la toolbox Error Analyis du framework Responsible AI¶

Sources¶

  • Article de Besmira Nushi sur l'utilisation toolbox Error Analysis
  • Article vulgarisé sur towardsdatascience
  • Article du blog de neptune.ai
  • Article du blog d'Alexandre Burlacu