Zpět na domů

Koliderový bias v data science: simulace efektu

Článek rozebírá collider bias — zkreslení korelací při filtrování podle kolideru. Jsou uvedeny Python-simulace na uniform a normal datech s vizualizací. Doporučení k vyhnutí se v analýze.

Collider bias: falešné spojitosti z filtrování dat
Advertisement 728x90

Collider bias: Jak filtrování dat vytváří falešné korelace

Kollider je proměnná C, na kterou vedou příčinné cesty z A a B: A → C ← B. Podmínění podle C (filtrace nebo stratifikace) otevírá falešnou souvislost mezi A a B.

Příklady z praxe:

  • Věk → Používání → Kvalita (přeživší předměty se zdají kvalitnější).
  • Inteligence → Přijetí na VŠ → Bohatství rodičů (mezi studenty bohatší vypadají méně inteligentní).
  • Talent → Úspěch → Pracovitost (úspěšní talentovaní se zdají lenivější).

V data science to vede ke špatným modelům: gradient boosting na filtrovaných datech dědí tento bias.

Google AdInline article slot

Simulace na rovnoměrných datech

Generujeme 1000 bodů A a B z uniform(0,100), nezávislé. Kollider flag = (A > 50) | (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"Korelace mezi A a B: {data['a'].corr(data['b']):.2f}")
print(f"Korelace tam, kde flag je pravdivý: {data[data['flag']]['a'].corr(data[data['flag']]['b']):.2f}")

Výsledek:

  • Celková výběrka: corr ≈ 0,00
  • Filtrovaná: corr ≈ -0,34

Vizualizace scatterplotu ukazuje, jak odstranění "nevyživších" bodů (modré) posouvá trend dolů.

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()

Po filtrování dává lmplot záporný sklon: pravý horní úhel "vyprázdněl", rovnováha je narušena.

Realistický scénář: normální rozdělení

Přecházíme na np.random.normal: A ~ N(50,5), B ~ N(30,5). Pravděpodobnostní kollider: normalizujeme, selection_prob = max(a_norm, b_norm)*1.5, clip(0,1), flag = rand < prob.

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"Korelace ve celém datasetu: {normal_data['a'].corr(normal_data['b']):.2f}")
print(f"Korelace, když je flag pravdivý: {normal_data[normal_data['flag']]['a'].corr(normal_data[normal_data['flag']]['b']):.2f}")

Výsledek:

Google AdInline article slot
  • Celková: corr ≈ 0,03
  • Filtrovaná: corr ≈ -0,09

Efekt je slabší, ale významný v A/B testech, farmách nebo ML.

Jak se v analýze vyhnout

  • Kreslete DAG: příčinné grafy (directed acyclic graphs) odhalují kolider.
  • Ne-filtrujte podle výsledku: analyzujte celou populaci nebo použijte IPCW (inverse probability censoring weighting).
  • Zkontrolujte korelace: porovnejte před a po stratifikaci.
  • Nástrojové proměnné: pro příčinný závěr.
  • Bayesovské sítě: explicitně modelují závislosti.

Důležité informace

  • Collider bias vzniká při podmínění na společné příčině – vytváří falešnou zápornou korelaci.
  • Simulace na uniform dává corr -0,34, na normal -0,09; efekt se škáluje.
  • Souvisí s chybou přeživšího, Berksónovým paradoxem, selekčním biasem.
  • Kontrola: nakreslete DAG před filtrováním.
  • V ML: filtrovaná data → zkreslené modely, podhodnocení/přehodnocení funkcí.

— Editorial Team

Advertisement 728x90

Číst dál