Retour à l'accueil

Biais de collider en science des données : simulation de l'effet

L'article décompose le biais de collider — distorsion des corrélations lors du filtrage par collider. Simulations Python sur données uniformes et normales avec visualisation fournies. Recommandations pour l'évitement en analyse.

Biais de collider : fausses connexions dues au filtrage des données
Advertisement 728x90

Biais de collision : comment le filtrage des données crée des corrélations fausses

Un biais de collision se produit lorsqu'une variable C est influencée par deux autres variables A et B via des chemins causaux : A → C ← B. Conditionner sur C — qu'il s'agisse d'un filtrage ou d'une stratification — génère une corrélation artificielle entre A et B.

Exemples concrets :

  • Âge → Utilisation → Qualité (les objets survivants semblent plus qualitatifs).
  • QI → Admission à l’université → Richesse familiale (parmi les étudiants, les plus riches semblent moins intelligents).
  • Talent → Succès → Éthique du travail (les individus talentueux ayant réussi semblent plus paresseux).

En science des données, cela conduit à des modèles trompeurs : les algorithmes comme le gradient boosting appliqués à des données filtrées héritent de ce biais.

Google AdInline article slot

Simulation avec des données uniformes

Nous générons 1 000 points indépendants pour A et B selon une loi uniforme sur [0, 100]. Le marqueur de collision est activé si A > 50 ou B > 50.

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
from statsmodels.nonparametric.smoothers_lowess import lowess

NUMBER_OF_VALUES = 1000
A_RANGE = (0, 100)
B_RANGE = (0, 100)
A_THRESHOLD = 50
B_THRESHOLD = 50

a = np.random.uniform(*A_RANGE, NUMBER_OF_VALUES)
b = np.random.uniform(*B_RANGE, NUMBER_OF_VALUES)
data = pd.DataFrame({'a': a, 'b': b})
data['flag'] = (data['a'] > A_THRESHOLD) | (data['b'] > B_THRESHOLD)
print(f"Corrélation entre A et B : {data['a'].corr(data['b']):.2f}")
print(f"Corrélation lorsque flag est vrai : {data[data['flag']]['a'].corr(data[data['flag']]['b']):.2f}")

Résultats :

  • Jeu de données complet : corr ≈ 0,00
  • Sous-ensemble filtré : corr ≈ -0,34

La visualisation en nuage de points montre comment l’élimination des points non survivants (bleus) déplace la tendance vers le bas.

Google AdInline article slot
sns.scatterplot(data=data, x='a', y='b', hue='flag', palette={True: 'red', False: 'blue'}, alpha=0.5)
sns.regplot(data=data, x='a', y='b', scatter=False, color='black')
plt.show()

Après filtrage, le graphique lmplot affiche une pente négative : le quadrant supérieur droit devient vide, rompant l’équilibre.

Scénario réaliste : distribution normale

On utilise maintenant np.random.normal : A ~ N(50,5), B ~ N(30,5). La collision est probabiliste : on normalise les valeurs, calcule la probabilité de sélection comme max(a_norm, b_norm)*1,5, on clippe entre [0,1], puis on attribue le marqueur selon un tirage aléatoire.

a = np.random.normal(loc=50, scale=5, size=NUMBER_OF_VALUES)
b = np.random.normal(loc=30, scale=5, size=NUMBER_OF_VALUES)
normal_data = pd.DataFrame({'a': a, 'b': b})
a_norm = (normal_data['a'] - normal_data['a'].min()) / (normal_data['a'].max() - normal_data['a'].min() + 1e-6)
b_norm = (normal_data['b'] - normal_data['b'].min()) / (normal_data['b'].max() - normal_data['b'].min() + 1e-6)
selection_prob = np.maximum(a_norm, b_norm) * 1.5
selection_prob = np.clip(selection_prob, 0, 1)
normal_data['flag'] = np.random.random(len(normal_data)) < selection_prob
print(f"Corrélation dans le jeu complet : {normal_data['a'].corr(normal_data['b']):.2f}")
print(f"Corrélation lorsque flag est vrai : {normal_data[normal_data['flag']]['a'].corr(normal_data[normal_data['flag']]['b']):.2f}")

Résultats :

Google AdInline article slot
  • Jeu de données complet : corr ≈ 0,03
  • Sous-ensemble filtré : corr ≈ -0,09

L’effet est plus faible mais reste significatif dans les tests A/B, les études terrain ou les pipelines d’apprentissage automatique.

Comment éviter le biais de collision dans l’analyse

  • Dessinez des DAGs : utilisez des graphes acycliques orientés pour identifier les collisions avant toute analyse.
  • Évitez le filtrage basé sur le résultat : analysez la population complète ou appliquez un poids inverse de probabilité de censure (IPCW).
  • Comparez les corrélations avant et après stratification : observez les écarts entre groupes.
  • Utilisez des variables instrumentales : pour l’inférence causale quand un biais est suspecté.
  • Exploitez les réseaux bayésiens : modélisez explicitement les dépendances et relations conditionnelles.

Points clés

  • Le biais de collision survient lorsqu’on conditionne sur une cause commune, créant des corrélations négatives artificielles.
  • La simulation avec des données uniformes donne une corrélation ≈ -0,34 ; avec des données normales, ≈ -0,09 — l’effet dépend de la structure des données.
  • Ce phénomène est lié au biais de survie, au paradoxe de Berkson et au biais de sélection.
  • Dessinez toujours un DAG avant de filtrer les données.
  • En apprentissage automatique : les données filtrées produisent des modèles biaisés, entraînant une sous- ou surestimation de l’importance des caractéristiques.

— Editorial Team

Advertisement 728x90

Lire ensuite