Deux questions, toujours : Le modèle est-il efficace ? Et son raisonnement est-il acceptable ?
| Partie | Question traitée | Données | Outil principal |
|---|---|---|---|
| Partie 1 | Jusqu'où l'interprétabilité classique peut nous mener ? | Census (tabulaire) | Arbre, coefficients, ACP, SHAP |
| Partie 2 | La même logique tient-elle sur texte et multi-classes ? | Émotions (texte) | SHAP multi-classes |
| Partie 3 | Pouvez-vous mener le workflow seul·e ? | Votre dataset | Analyse SHAP autonome |
Les variables sont lisibles par un humain. Quand le modèle met en avant marital-status ou hours-per-week, on peut juger immédiatement si la logique est raisonnable — ou à auditer.
[RACINE]
variable ≤ valeur
/ \
Vrai Faux
[enfant gauche] [enfant droit]
| |
[FEUILLE] [FEUILLE]
classe : A classe : B
DecisionTreeClassifier(max_depth=3, random_state=42) — profondeur 3 pour rester lisible.
La variable à la racine est le premier séparateur le plus fort des données.
Lisible uniquement parce qu'il est peu profond. Dès qu'on le laisse grandir, l'interprétabilité disparaît.
Fréquence d'utilisation pour splitter × réduction d'impureté.
Positif = pousse vers classe 1 · négatif = vers classe 0.
tree_clf.feature_importances_ · pipeline['logistic_regression'].coef_[0] (avec StandardScaler).
CP2 ▲
│ ● ● ○ ○ ○ ● = classe 0 (≤50K)
↑ flèche │ ● ● ○ ○ ○ ○ = classe 1 (>50K)
variable A │● ●● ○ ○ ○
│ ● ○ ○ ○ ○
└──────────────► CP1
→ flèche pour variable B
L'ACP est excellente pour l'exploration. Mais la projection perd de l'information — jamais une explication finale.
| Modèle | Score F1 | Interprétabilité |
|---|---|---|
| Arbre de décision (profondeur 3) | ~0.75 | Règles lisibles |
| Régression logistique | ~0.78 | Coefficients directement inspectables |
| XGBoost | ~0.81 | Non inspectable directement |
Meilleure performance → moins lisible. Pas d'arbre unique à inspecter. Pas de tableau de coefficients. Le raisonnement est distribué sur des centaines d'arbres.
xgb.XGBClassifier(eval_metric='logloss', random_state=42) — 100 arbres par défaut, max_depth=6. C'est ce modèle qu'on va expliquer avec SHAP.
Pour cette prédiction, quelle est la contribution de chaque variable, par rapport à une ligne de base ?
prédiction de base (expected value)
+ contribution de la variable 1
+ contribution de la variable 2
+ contribution de la variable 3
+ ...
= prédiction pour cette personne
Voyez SHAP comme un outil de décomposition de prédiction. Il découpe une prédiction en parts additives lisibles.
TreeExplainer optimisé pour XGBoost.TreeExplainer rapide.explainer = shap.TreeExplainer(xgb_model, data=X_train, model_output="probability") · data=X_train sert de jeu de fond — c'est sur lui qu'on calcule la prédiction moyenne (= expected value).shap_values = explainer.shap_values(X_test) → une matrice (n_samples, n_features) variable 1 variable 2 variable 3 ...
personne 1 +0.12 -0.03 +0.01
personne 2 -0.08 +0.10 0.00
personne 3 +0.02 -0.01 -0.05
Proche de zéro → la variable a très peu influencé cette prédiction.
L'expected value est simplement la prédiction moyenne du modèle sur les données de fond — E[f(X)] = np.mean(model.predict(X_background)).
model.predict_proba(X_train)[:,1].mean()
≈ 0.24 ← expected_value
(~24% des gens gagnent >50K dans X_train)
expected_value + Σ shap_values[personne] = model.predict_proba(personne)
Fortes valeurs de capital-gain → >50K. gender_Female pousse légèrement vers ≤50K — signal à auditer.
valeur SHAP
pour age • •
• • • • couleur = valeur d'une autre variable
0 -----------------
• • •
• •
basse → haute
valeur de age
Le force plot dit pourquoi cette personne précise a cette prédiction.
| Précaution | Ce que cela veut dire |
|---|---|
| Variables corrélées | Le crédit peut se répartir entre jumelles de manière floue |
| Coût de calcul | TreeExplainer est rapide — d'autres explainers peuvent être lents |
| Pas la causalité | Une forte valeur SHAP est une association, pas une cause |
| Instabilité locale | Des individus similaires → explications parfois différentes |
| Choix de l'explainer | Différents explainers se comportent différemment selon les modèles |
Utilisez SHAP comme un cadre structuré pour comprendre le modèle — pas comme une vérité absolue.
| Aspect | Partie 1 (binaire) | Partie 3 (multi-classes texte) |
|---|---|---|
| Variables | Colonnes tabulaires | Mots / tokens |
| Tâche | Binaire | 6 classes (tristesse · joie · peur · colère · surprise · dégoût) |
| Espace SHAP | Probabilités | Logits (scores bruts) |
| Unité d'explication | Une par prédiction | Une par classe, par prédiction |
TreeExplainer, shap_values, force plots. Deux concepts nouveaux seulement.
xgb.XGBClassifier(objective='multi:softprob', num_class=6)
scores bruts (logits) ──softmax──
probabilités sommant à 1
tristesse 3.1 tristesse 0.72
joie 0.7 joie 0.08
peur 1.0 peur 0.10
colère 0.2 colère 0.05
surprise -0.3 surprise 0.03
dégoût -0.6 dégoût 0.02
En multi-classes, TreeExplainer explique les scores bruts — les probabilités viennent après la softmax.
shap_values │ ├── classe 0: tristesse → array (n_samples, n_features) ├── classe 1: joie → array (n_samples, n_features) ├── classe 2: peur → array (n_samples, n_features) ├── classe 3: colère → array (n_samples, n_features) ├── classe 4: surprise → array (n_samples, n_features) └── classe 5: dégoût → array (n_samples, n_features)
shap_values[3][5] pour la personne 5, classe colère
shap_values[5, :, 3] équivalent
Des mots comme horrible, ingrat poussent le score tristesse vers le haut. D'autres tirent doucement de l'autre côté.
Un seul mot fort (profane) domine. Des mots apaisants comme sentir apparaissent de l'autre côté.
L'important n'est pas juste quels mots apparaissent — c'est quelle classe ils soutiennent dans cette explication.
XGBClassifier, afficher classification_report.Les valeurs SHAP sont locales et associatives — une prédiction, une personne, une contribution.
shap — shap.readthedocs.iolime · eli5 · captum (PyTorch)