A cél egy konkrét oksági kérdés: ha a Northstar-rendeléseket
priority_flag=1 (elsőbbségi kezelés) beavatkozással látnánk
el, mennyivel változna a késés valószínűsége a target_late
kimenetben. A megfigyelési egység egy rendelés. Az input a
orders.csv sémája: order_id,
customer_id, order_ts,
promised_days=7, quantity_sum,
basket_minor, shipping_fee_minor,
distance_km, priority_flag, továbbá utólag
ismert delivery_days és target_late. A
predikciós projekt céljától eltérően itt nem azt kérdezzük, hogy egy
rendelés várhatóan késni fog-e, hanem azt, hogy a
priority_flag megváltoztatása okoz-e késéscsökkenést.
A nyers megfigyelési asszociáció
nem automatikus oksági hatás. Ha például a nagyobb távolságú rendelések
gyakrabban kapnak prioritást, és a távolság a késést is növeli, akkor a
prioritásos csoport más distance_km-összetételű, mint a nem
prioritásos. Az induló feladat: mielőtt a módszertant látná, fogalmazzon
meg legalább egy ilyen közös okot, és mondja meg, milyen irányba
torzíthatja a nyers kockázati különbséget a distance_km, ha
a nagyobb távolság növeli mind a priority_flag esélyét,
mind a target_late esélyét.
Minden rendeléshez két potenciális kimenet tartozik:
Itt bináris, tehát nincs mértékegysége. A beavatkozás a ténylegesen megfigyelt kezelés. A fundamental problem of causal inference, hogy egy rendelésen a két érték közül egyszerre csak az egyik figyelhető meg; a megfigyelt kimenet:
A jobb oldal elemenkénti vektor: ha , az első tag marad; ha , a második. Egy kis kontrollpélda:
| megfigyelt | |||
|---|---|---|---|
| 0 | 0 | 1 | 0 |
| 1 | 1 | 1 | 1 |
| 0 | 0 | 0 | 0 |
| 1 | 1 | 0 | 0 |
A oszlopok hipotetikusak; a táblázatban csak és mérhető. Az egyéni oksági hatás , ami bináris kimenetnél , vagy lehet. Az átlagos oksági hatás, angolul average treatment effect, a populációban:
A fenti négy soron a potenciális különbségek: , , , , tehát a példabeli ATE ? Pontosabban ? Ellenőrizzük: soronként ; összeg , átlag . Ez jó emlékeztető: az egyéni hatások lehetnek nem nullák, de az átlag lehet nulla.
A beavatkozás (intervention) nem passzív megfigyelés, hanem
a kezelés külső beállítása; a jelölés
,
amit a potenciális kimeneti nyelvben
jelöl. Ha egy gráfban a priority_flag csomópontra
beavatkozunk, a belé mutató nyilak eltűnnek, mert a kezelést ezentúl nem
a távolság vagy a kosárérték határozza meg.
Egy egyszerű irányított aciklikus gráf, DAG, az ok-okozati feltevéseket rögzíti. A nyíl jelentése: közvetlen ok. Három szerepet kell élesen elkülöníteni.
A zavaró változó (confounder) közös ok: hat a
kezelésre és a kimenetre egyaránt. A rendelési példában a
distance_km zavaró, mert nagyobb távolságnál gyakrabban
választanak prioritást, és a távolság a késést is növeli; így a
priority_flag és a target_late közötti nyers
kapcsolat részben a távolságból származik. Gráfosan
és
.
Ha
megfigyelt, akkor a
hátsó ajtó út a
-re
való rétegzéssel vagy kiigazítással blokkolható. A rétegzett
kiigazítási, standardizálási formula bináris
esetén:
ahol a zavaró lehetséges értékeit futja be. A képlet a feltételes kockázatokat a zavaró populációs eloszlásával súlyozza; a becsült ATE a két standardizált érték különbsége. A itt a teljes mintabeli marginális arány, nem az -feltételes arány.
A mediátor (közvetítő változó) a kezelés és a
kimenet közötti ok-okozati lánc közbülső lépése:
.
Ha például az elsőbbségi kezelés korábbi dispatch_hour
csomagfeladást okoz, és ez csökkenti a késést, akkor a
dispatch_hour mediátor. A teljes oksági hatás tartalmazza a
mediátoron átmenő közvetett hatást is; ha a modellben a mediátorra is
feltételesítünk, blokkoljuk a lánc egy részét, ezért a becslés nem a
teljes hatás lesz. A teljes hatás becslésekor a mediátor tiltott
kontroll.
A collider (ütköző változó) két másik változó közös okozata: . Ha egy colliderre feltételesítünk, nem-oksági asszociáció nyílhat meg a két ok között. A klasszikus kis példa: legyen a panasz értéke , ha a rendelés prioritást kapott vagy késett; csak a panasznál megfigyelt rendeléseket látjuk. A szűrés után az és negatív asszociációt mutat, pedig a teljes populációban függetlenek lehetnek. A colliderre való feltételesítés tehát szelekciós torzítást okoz; ez is tiltott kontroll, kivéve ha kifejezetten a kiválasztási folyamatot akarjuk korrigálni, és a teljes cella ismert.
Az azonosíthatóság (identification) az a kérdés, hogy a megfigyelt eloszlásból — a DAG-feltevésekkel együtt — egyértelműen meghatározható-e a cél oksági mennyiség. A confounder-DAG esetén igen, ha mérve van, mert a kiigazítási formula azonosítja az értékeket. Ha van nem mért zavaró , amely -ra és -ra is hat, akkor az azonosítás nem teljes; a kiigazítás nem távolítja el a torzítást. A collider-szelekciós példában a cella hiányzik, ezért a teljes populáció ATE-je nem azonosítható a kiválasztott mintából. A regressziós kiigazítás (OLS a lineáris algebra és statisztika találkozásánál) akkor oksági, ha a DAG hátsó ajtó útjai blokkoltak és a modell funkcionális formája helyes; a p-érték önmagában nem azonosítási bizonyíték. A feltételes valószínűség (Esemény, feltételes valószínűség és Bayes) itt úgy tér vissza, hogy a megfigyelt nem azonos a beavatkozás utáni értékkel; a különbség éppen a közös okból származó torzítás.
A matematikai híd röviden: a regresszió a feltételes várható értéket becsli, de a feltételes várható érték csak akkor egyenlő a potenciális kimenet várható értékével, ha a feltételhalmaz blokkolja a hátsó ajtó utakat. Ellenkező esetben a jó illeszkedésű modell is torzított következtetést ad.
Az alábbi szimuláció két DAG-ot állít elő. Mindkettőben van
megfigyelt asszociáció
és
között, de az ok teljesen más: az elsőben zavaró okozza, a másodikban
collider-szelekció. A szimuláció a Python standard numerikus
könyvtáraival, numpy és pandas segítségével
fut; a seed rögzíti a véletlent. A kimenet szemléltető, nem ebben a
generálási módban futtatott mérés.
Az első DAG: , , és nincs nyíl; a valódi ATE 0.
A második DAG: , , ahol jelenti a megfigyelt panaszcellát; a megfigyelt minta csak . A valódi ATE 0, mert és független a teljes populációban.
import numpy as np
import pandas as pd
rng = np.random.default_rng(20261020)
n = 60_000
# 1. folyamat: confounder; valódi ATE = 0
# C -> A, C -> Y; nincs A -> Y
c1 = rng.binomial(1, 0.5, n)
a1 = rng.binomial(1, 0.2 + 0.4 * c1, n) # P(A=1|C=0)=0.2, P(A=1|C=1)=0.6
y1 = rng.binomial(1, 0.1 + 0.3 * c1, n) # P(Y=1|C=0)=0.1, P(Y=1|C=1)=0.4
df1 = pd.DataFrame({"A": a1, "Y": y1, "C": c1})
# Nyers kockázati különbség A=1 vs A=0
rd_raw_1 = (
df1.loc[df1.A == 1, "Y"].mean()
- df1.loc[df1.A == 0, "Y"].mean()
)
# Standardizálás a confounder C szerint
def standardized_rd(df):
cell = {}
for c in [0, 1]:
for a in [0, 1]:
cell[(a, c)] = df.loc[(df.C == c) & (df.A == a), "Y"].mean()
p_c = df.C.value_counts(normalize=True).sort_index()
e_y1 = cell[(1, 0)] * p_c[0] + cell[(1, 1)] * p_c[1]
e_y0 = cell[(0, 0)] * p_c[0] + cell[(0, 1)] * p_c[1]
return e_y1 - e_y0
rd_adj_1 = standardized_rd(df1)
# 2. folyamat: collider; valódi ATE = 0
# A és Y független; C = A OR Y, és csak C=1-et figyelünk meg
a2 = rng.binomial(1, 0.5, n)
y2 = rng.binomial(1, 0.5, n)
c2 = np.maximum(a2, y2) # C=1, ha A=1 vagy Y=1
df2_all = pd.DataFrame({"A": a2, "Y": y2, "C": c2})
df2_obs = df2_all[df2_all.C == 1]
rd_all_2 = (
df2_all.loc[df2_all.A == 1, "Y"].mean()
- df2_all.loc[df2_all.A == 0, "Y"].mean()
)
rd_obs_2 = (
df2_obs.loc[df2_obs.A == 1, "Y"].mean()
- df2_obs.loc[df2_obs.A == 0, "Y"].mean()
)
print("1. confounder: nyers RD =", round(rd_raw_1, 3),
"| C-re igazított RD =", round(rd_adj_1, 3))
print("2. collider: teljes populáció RD =", round(rd_all_2, 3),
"| C=1 megfigyelt RD =", round(rd_obs_2, 3))A várható, elméleti kimenet a megadott generáló valószínűségekből:
1. confounder: nyers RD = 0.125 | C-re igazított RD = 0.0
2. collider: teljes populáció RD = 0.0 | C=1 megfigyelt RD = -0.5
A szimulációs zaj miatt esetén a harmadik tizedesjegyben nagyságrendű eltérés elfogadható; a kimenetet helyi futtatással kell rögzíteni.
A confounder-folyamatban a nyers kockázati különbség várhatóan , pedig az -ból -ra nincs közvetlen hatás. Kézi kontroll: a DAG szerint és feltételesen függetlenek -től, ezért mindkét -rétegben ugyanaz a feltételes kockázat, és a standardizálás pontosan nullát ad. Az analitikus nyers érték is ellenőrizhető: a súlyozott feltételes valószínűségekből és , különbség .
A collider-folyamatban a teljes populációban és független, ezért az RD nulla; a szűrt mintában viszont a közös ok-okozat feltétele negatív asszociációt generál. A determinisztikus esetben a minta kontingenciatáblája a három lehetséges cellát egyenlő arányban tartalmazza, a cella hiányzik, ezért -nél arány , -nál , különbség . Ez a szám a kiválasztási torzítás, nem oksági hatás.
A labor-átadandó követelmény is ez: két folyamatot rajzolunk, amelyek erős, de okilag eltérően keletkező asszociációt adnak. Az elsőnél a következtetési korlát az, hogy a hatás csak akkor azonosítható, ha a zavaró mérve van; a másodiknál az, hogy a -re szűrt minta önmagában nem azonosítja a teljes ATE-t, mert a nullcellát nem látjuk.
Azonosítási feltételek: megfigyeléses kiigazítással oksági hatás csak konzisztencia, feltételes kicserélhetőség (nincs kezeletlen zavarás) és pozitivitás/overlap megfelelő változatai mellett azonosítható. A DAG önmagában nem bizonyítja, hogy ezek az empirikus esetben teljesülnek.
Értelmezés. Adott a DAG:
distance_km -> priority_flag,
distance_km -> target_late,
priority_flag -> dispatch_hour,
dispatch_hour -> target_late.
distance_km és mi a dispatch_hour
szerepe? (b) Mely változó(k) szerint kell igazítani, ha a
priority_flag teljes oksági hatását akarjuk a
target_late-re? (c) Mi történik, ha a regresszióban a
dispatch_hour is szerepel?Implementálás. Írjon szimulációt, amelyben
és
is van, nincs zavaró. Legyen
,
,
és
.
Használjon n=50_000 és seed=7 értéket.
Számítsa ki a nyers kockázati különbséget, az
-re
standardizált rétegzett becslést, és adja meg a teljes ATE elméleti
értékét.
Hibadiagnózis. Egy elemző az 1. feladat
DAG-jához illeszti a
smf.logit('target_late ~ priority_flag + dispatch_hour + distance_km', data=orders).fit()
modellt. A priority_flag együtthatójára
p<0.001 adódik, ezért azt állítja, hogy a prioritás
beavatkozás hatásos. Soroljon fel legalább két okot, amiért ez az
állítás nem következik a modellből, és javasoljon egy
ellenőrzést.
Megváltozott feltétel. A collider-példában most
a naplófájl a
eseteket is tartalmazza, tehát a teljes df2_all tábla
rendelkezésre áll. Módosítsa az elemzést úgy, hogy a teljes adaton
számol, és értelmezze az ATE-t. Mi változik a DAG-ban?
distance_km zavaró (confounder), mert hat a kezelésre
és a kimenetre is. A dispatch_hour mediátor, mert a
priority_flag rajta keresztül is hat a késésre. (b) A
teljes hatáshoz csak a zavarót kell blokkolni: distance_km
szerint rétegezni vagy regresszióban kontrollálni. (c) A
dispatch_hour kontrollja blokkolja a
priority_flag -> dispatch_hour -> target_late
közvetett utat, ezért a becslés a teljes hatásnál kisebb, jellemzően a
közvetlen hatáshoz közelebbi értéket ad; a teljes hatás becslésekor ez
tiltott kontroll.rng = np.random.default_rng(7)
n = 50_000
a3 = rng.binomial(1, 0.4, n)
m3 = rng.binomial(1, 0.3 + 0.4 * a3, n)
y3 = rng.binomial(1, 0.1 + 0.2 * a3 + 0.2 * m3, n)
df3 = pd.DataFrame({"A": a3, "M": m3, "Y": y3})
rd_raw_3 = (
df3.loc[df3.A == 1, "Y"].mean()
- df3.loc[df3.A == 0, "Y"].mean()
)
# M-re standardizált rétegzett becslés
cell3 = {}
for m in [0, 1]:
for a in [0, 1]:
cell3[(a, m)] = df3.loc[(df3.M == m) & (df3.A == a), "Y"].mean()
p_m = df3.M.value_counts(normalize=True).sort_index()
e_y1_m = cell3[(1, 0)] * p_m[0] + cell3[(1, 1)] * p_m[1]
e_y0_m = cell3[(0, 0)] * p_m[0] + cell3[(0, 1)] * p_m[1]
rd_adj_m = e_y1_m - e_y0_m
print("nyers RD =", round(rd_raw_3, 3),
"| M-re igazított RD =", round(rd_adj_m, 3))Az elméleti teljes ATE kiszámítása: , , tehát ATE . A nyers RD várt értéke , mert nincs zavaró; az -re igazított RD várt értéke , mert minden -rétegben a generáló képlet -együtthatója . A különbség a mediátoron átmenő közvetett hatás blokkolásából adódik. A tűrés az -es szimulációhoz körülbelül .
A hibák: (a) a dispatch_hour mediátor kontrollja
torzítja a teljes hatást; (b) a megfigyelési adat nem randomizált, ezért
a feltételes regressziós együttható csak akkor oksági, ha minden zavaró
mérve van és a logit modell jól specifikált; a p-érték a nullmodell
szerinti szélsőség, nem oksági azonosítás (IV.
ellenőrző pont: korrekt statisztikai állítás); lehetnek nem mért
zavarók. Ellenőrzésként randomizált kísérlet vagy a jövő alfejezetben
tárgyalt kísérleti protokoll szerinti allokáció használható.
A teljes df2_all mintán a nyers RD várhatóan
,
mert
és
függetlenek a generáló folyamatban. A collider-szelekció megszűnik, mert
a
cella is megfigyelt. A DAG-ban nincs többé a
-re
való feltételesítés, tehát az ATE azonosítható, és a becslés nulla. Az
azonosíthatóságot a teljes megfigyelés állítja helyre, nem a modell
bonyolultsága.
Jó prediktív pontosságból nem következik oksági azonosíthatóság. Az
első szimulációban a priority_flag-ből jobban jósolható a
target_late, mint a puszta alaparányból: az
csoportbeli késési arány
,
az
csoportbeli
,
szemben a
-ös
marginálissal. Egy modell, amely az
-t
használja, csökkenti a Brier-veszteséget, mégis a valódi beavatkozási
hatás nulla. A collider-mintában ugyanez a helyzet: a modell a
adaton hasznos prediktort talál, de a teljes populációban a kezelés nem
befolyásolja a kimenetet. A predikció a megfigyelt eloszlást tanulja; az
oksági kérdés a meg nem figyelt potenciális kimenetekről szól. A
regresszió (OLS a lineáris algebra és statisztika
találkozásánál) és a GLM (GLM: bináris és
számlálási cél) tehát nem teszik automatikusan okságivá a
következtetést; ehhez a DAG azonosítási feltételei kellenek.
Önellenőrzés: ellenőrizze, hogy a confounder-standardizálásnál a súlyokat a teljes mintából vette-e, nem az -feltételes csoportból. Ha a súlyokat felcseréli, a torzító összetételhatást újra bevezeti. A collider-példában pedig kérdezze meg: a cella a szűrés miatt hiányzik, vagy a valós mechanizmusban nem is lehetséges? A válasz eldönti, hogy a teljes ATE azonosítható-e.
A potenciális kimenet a beavatkozás utáni kimenetet írja le, a megfigyelt . A zavaró közös ok; rétegzéssel blokkolható, ha mérve van, és a kiigazítási formula a feltételes kockázatokat a zavaró marginális eloszlásával súlyozza. A mediátor és a collider tiltott kontroll a teljes hatás becslésekor: előbbi blokkolja a közvetett utat, utóbbi szelekciós asszociációt nyit. Azonosíthatóság nélkül a jó predikció sem oksági következtetés. Következő lépésként Randomizálás és kísérleti protokoll alfejezetben a randomizálást és a kísérleti protokollt építjük fel, amely a zavaró feltételezése nélkül teszi azonosíthatóvá az ATE-t.