๐ ์ธ๊ณผ์ถ๋ก ๊ฐ์ธ ๊ณต๋ถ์ฉ ํฌ์คํธ ๊ธ์ ๋๋ค. ์ถ์ฒ๋ ์ฒจ๋ถํ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํด์ฃผ์ธ์!
โป ์ ๋ฆฌ 1
โป ์ ๋ฆฌ 2
๐ ์ ๋ฆฌ
• ์ฑํฅ์ ์ = Treatment ๋ฅผ ๋ฐ์ ํ๋ฅ
• ์ฑํฅ์ ์๊ฐ ์๋ค๋ฉด Confounder ๋ฅผ ์ง์ ์ ์ดํ ํ์๊ฐ ์์ผ๋ฉฐ, ์ฑํฅ์ ์๋ฅผ ํต์ ํ๋ ๊ฒ๋ง์ผ๋ก ์ถฉ๋ถํ๋ค.
โ Example
โฏ ์ฃผ์
• ํ์๋ค์ด ํ๊ต์์ ์ฑ์ฅ ๋ง์ธ๋์ ์ ๋ํ ์ธ๋ฏธ๋๋ฅผ ์ฐธ์ฌํ๊ณ ๊ต์ก์ ๋ฐ์ ํ์๋ค์ด ํ์ ์ ์ผ๋ก ์ด๋ ํ ์ฑ์ทจ๊ฐ ์์๋์ง ์ธก์ ํ๊ธฐ ์ํด ์ธ๋ฏธ๋ ์์ ์ ๋ฐ์ ํ์๋ค์ ๋ํ์ํ์ ์ถ์ ํ๋ค.
โฏ ๋ฐ์ดํฐ์
• school_achievement : ํ์คํ๋ ์ฑ์ทจ๋ (ํ์คํ ๋จ = ๋ณ์๊ฐ ํ์คํธ์ฐจ๋ก ์ธก์ ๋จ)
• success_expect : ์๊ธฐ๊ฐ๋ฐ ์ฑ๊ณต ๊ธฐ๋๋ (๋ฏธ๋ ์ฑ๊ณต์ ๋ํ ์์ฒด ๊ธฐ๋ ํ๊ฐ) → ๋ฌด์์ ํ ๋น ์ด์ ์ ์ธก์ ๋ ์ ํ ์ฑ๊ณผ์ ๋ํ proxy ๋ณ์๋ก ํ์ฉ
• intervention : ์ธ๋ฏธ๋ ์์ ์ฐธ๊ฐ ์ฌ๋ถ
• ๋ฌด์์ ์ฐ๊ตฌ์ด๊ธด ํ๋, ์ฐธ์ฌ์ ๊ธฐํ๋ ๋ฌด์์๋ก ์ด๋ฃจ์ด์ก์์๋ ์ฐธ์ฌ ์์ฒด๋ ๊ทธ๋ ์ง ์์ ์ ์๋ค. ์๊ธฐ๊ณ๋ฐ ์ฑ๊ณต ๊ธฐ๋๋๊ฐ ๋์ ํ์๋ค์ ์ฑ์ฅ ๋ง์ธ๋ ์ธ๋ฏธ๋์ ์ฐธ์ฌํ ๊ฐ๋ฅ์ฑ์ด ๋๊ธฐ ๋๋ฌธ์ด๋ค. ์๋์ ๊ฐ์ด ์ฑ๊ณต ๊ธฐ๋๋ ๋ณ ํ๊ท ์ธ๋ฏธ๋ ์ฐธ์๋ฅ ์ ํ์ธํด๋ณด๋ฉด ๊ธฐ๋๋๊ฐ ๋์ ์๋ก ์ฐธ์ฌ์จ์ด ์ฌ๋ผ๊ฐ๋ ๊ฒ์ ๋ฐ์ดํฐ๋ก๋ ํ์ธํด ๋ณผ ์ ์๋ค โจ ํธํฅ์ด Positive
data.groupby("success_expect")["intervention"].mean()
โฏ ์ฒ์นํจ๊ณผ
• ํ๊ท๋ถ์์ ํตํด E[Y(0) | T=1] ๊ณผ E[Y(0) | T=0] ์ ๊ฐ์ด ์ด๋ป๊ฒ ์ฐจ์ด ๋๋์ง ํ์ธํด๋ณด์
smf.ols("achievement_score ~ intervention", data=data).fit().summary().tables[1]
• ๊ฐ์ ์ด ์๋ ๊ฒฝ์ฐ์ ์๋ ๊ฒฝ์ฐ๋ฅผ ๋จ์ํ ๋น๊ตํ๋ฉด Treatment ๋ฅผ ๋ฐ๋ ์ฌ๋์ ์ฑ์ทจ๋ ์ ์๊ฐ ํ๊ท ๋ณด๋ค 0.3185 ๋์์ ์ ์ ์๋ค (0.4723 - 0.1538)
• ํ์คํ๋ ๋ณ์์ด๊ธฐ ๋๋ฌธ์ Treatment ๋ฅผ ๋ฐ์ ๊ทธ๋ฃน์ ๋ฐ์ง ์์ ๊ทธ๋ฃน๋ณด๋ค 0.3185๋งํผ ํ์คํธ์ฐจ๊ฐ ํฌ๋ค๊ณ ํด์ํด ๋ณผ ์ ์๋ค.
โก Propensity score
โฏ ์ฑํฅ ์ ์
• Confounder X ๋ค์ ๋ํด ์ง์ ์ ์ผ๋ก ์ ์ดํ์ง ์์๋ ์กฐ๊ฑด๋ถ ๋ ๋ฆฝ์ ๋ฌ์ฑํ ์ ์๋ค๋ ์์ด๋์ด์์ ์์
โช (Y1, Y0) ⊥ T | X
• ์ฑํฅ์ ์ : Treatment ์ ์กฐ๊ฑด๋ถ ํ๋ฅ P(T|X) ์ด๋ค. P(x) ๋ก ๊ธฐ์ ํ๊ธฐ๋ ํ๋ค.
• ์ฑํฅ์ ์๋ฅผ ํ์ฉํ๋ฉด Treatment ์ ๋ํ ์ ์ฌ์ ๊ฒฐ๊ณผ๋ก๋ถํฐ ๋ ๋ฆฝ์ฑ์ ์ป๊ธฐ ์ํด Confounder X ์ ์ฒด๋ฅผ ์กฐ๊ฑดํ ํ ํ์๊ฐ ์๋ค. ์ฑํฅ์ ์ ํ๋๋ง ์ ์ดํ๋ ๊ฒ์ผ๋ก๋ ์ถฉ๋ถํ๋ค.
• ๋ณ์ X๋ฅผ Treatment T ๋ก ๋ณํํ๋ ์ผ์ข ์ ํจ์๋ผ๊ณ ์๊ฐํ ์ ์๋ค. ์ฆ, ์ฑํฅ์ ์๋ X์ Treatment T ์ฌ์ด์ ์ค๊ฐ ์ง์ ์ ๋ง๋ ๋ค.
• Treatment ๋ฅผ ๋ฐ์ ๊ทธ๋ฃน๊ณผ ๋ฐ์ง ์์ Control ๊ทธ๋ฃน์์ ๊ฐ๊ฐ ํ ๋ช ์ฉ Treatment ๋ฅผ ๋ฐ์ ํ๋ฅ ์ ๊ฐ๋๋ก ์ ํํ๋ค๋ฉด ๋น๊ต ๊ฐ๋ฅํด์ง๋ค. ๋ง์ฝ ๋ ๋ช ์ Treatment๋ฅผ ๋ฐ์ ํ๋ฅ ์ด ์ ํํ๊ฒ ๊ฐ๋ค๋ฉด, ๊ทธ๋ค ์ค 1๋ช ์ Treatment๋ฅผ ๋ฐ๊ณ ๋๋จธ์ง ํ ๋ช ์ด Treatment๋ฅผ ๋ฐ์ง ๋ชปํ ์ ์ผํ ์ด์ ๋ ์ฐ์ฐ์ผ๋ก ๋ฐ์ํ ๊ฒฐ๊ณผ์ด๋ค. (๋ฌด์์ ์กฐ๊ฑด ์ฑ๋ฆฝ)
โฏ ์ํ์ ํด์
• P(x) = E[T|X]
• (Y1, Y0) ⊥ T | P(x) ๊ฐ E[T | P(x),X] = E[Y | P(x)] ์ธ์ง ๋ณด์ด๋ฉด ๋๋ค.
• P(x) ๋ฅผ ์กฐ๊ฑด์ผ๋ก ๋๋ฉด X๊ฐ T์ ๋ํ ์ถ๊ฐ์ ์ธ ์ ๋ณด๋ฅผ ์ค ์ ์์์ ์๋ฏธํ๋ค.
โข Propensity weighting
โฏ IPTW
• Treatment๋ฅผ ๋ฐ์ ๋ชจ๋ ์ฌ๋์ Treatment์ ์ญํ๋ฅ ๋ก ์ธก์ ํ์ฌ Treatment๋ฅผ ๋ฐ์ ๊ฐ๋ฅ์ฑ์ด ๋งค์ฐ ๋ฎ์ ์ฌ๋๋ค์๊ฒ ๋์ ๊ฐ์ค์น๋ฅผ ์ฃผ๋ ๋ฐฉ๋ฒ
โป treatment๋ฅผ ๋ฐ์ ํ๋ฅ ์ด ์์ ๊ทธ๋ฃน์๋ ๋ ๋ง์ weight์ ์ฃผ์ด์ ํ๋ฅ ์ ๋ ํค์ฐ๊ณ , treatment๋ฅผ ๋ฐ์ ํ๋ฅ ์ด ํฐ ๊ทธ๋ฃน์๋ weight๋ฅผ ์๊ฒ ์ฃผ์ด์ ํ๋ฅ ์ ๋ฎ์ถ๋ค. treatment๋ฅผ ๋ฐ์ ํ๋ฅ ์ ๋น์ทํ๊ฒ ๋ง๋ค์ด ์ฃผ๊ฒ ๋ค๋ ๊ฒ weighting ๋ฐฉ๋ฒ์ด๋ค.
• ํ๋์ ์ : Treatment ๋ฅผ ๋ฐ์ง ์๋ ๊ทธ๋ฃน, ๋นจ๊ฐ์ ์ : Treatment ๋ฅผ ๋ฐ์ ๊ทธ๋ฃน
• ์ผ์ชฝ ํ๋จ ๊ทธ๋ํ : P(x) ์ฑํฅ์ ์
• IPTW ์ ์ฉ ์ดํ ๊ทธ๋ํ๋ฅผ ๋ณด๋ฉด ๋นจ๊ฐ์์ด ๋ ๋์ ๊ฐ์ค์น๋ฅผ ๋ฐ์์์ ํ์ธํด ๋ณผ ์ ์๋ค.
โฃ Propensity score estimation
โฏ ์ฑํฅ์ ์ ์ถ์
• ์ฑํฅ์ ์๋ฅผ ์ถ์ ํ ๋, ์ผ๋ฐ์ ์ธ ๋ฐฉ๋ฒ์ ๋ก์ง์คํฑ ํ๊ท๋ฅผ ํ์ฉํ๋ ๊ฒ์ด์ง๋ง, ๊ทธ๋๋์ธํธ ๋ถ์คํ ๊ณผ ๊ฐ์ ๋ค๋ฅธ ๊ธฐ๊ณํ์ต ๋ฐฉ๋ฒ์ ํ์ฉํ ์๋ ์๋ค.
• ๋ก์ง์คํฑ ํ๊ท๋ฅผ ์ฌ์ฉํ ๋๋ ๋ฐ์ดํฐ ์ธํธ์ ๋ฒ์ฃผํ ๋ณ์๋ฅผ ๋๋ฏธ๋ก ๋ณํํด์ผ ํ๋ค.
categ = ["ethnicity", "gender", "school_urbanicity"]
cont = ["school_mindset", "school_achievement", "school_ethnic_minority", "school_poverty", "school_size"]
data_with_categ = pd.concat([
data.drop(columns=categ), # dataset without the categorical features
pd.get_dummies(data[categ], columns=categ, drop_first=False)# categorical features converted to dummies
], axis=1)
print(data_with_categ.shape)
# (10391, 32)
• ๋ก์ง์คํฑ ํ๊ท๋ฅผ ์ฌ์ฉํด ์ฑํฅ์ ์๋ฅผ ์ถ์ ํด๋ณด๋ฉด ์๋์ ๊ฐ๋ค.
from sklearn.linear_model import LogisticRegression
T = 'intervention'
Y = 'achievement_score'
X = data_with_categ.columns.drop(['schoolid', T, Y])
ps_model = LogisticRegression(C=1e6).fit(data_with_categ[X], data_with_categ[T])
data_ps = data.assign(propensity_score=ps_model.predict_proba(data_with_categ[X])[:, 1])
data_ps[["intervention", "achievement_score", "propensity_score"]].head()
• ๊ฐ์ค์น๋ฅผ ์์ฑํ์ฌ Treated/Untreated sample size ๋ฅผ ํ์ธํ ์ ์๋ค.
weight_t = 1/data_ps.query("intervention==1")["propensity_score"]
weight_nt = 1/(1-data_ps.query("intervention==0")["propensity_score"])
print("Original Sample Size", data.shape[0])
print("Treated Population Sample Size", sum(weight_t))
print("Untreated Population Sample Size", sum(weight_nt))
• ๋ํ ์ฑํฅ์ ์๋ฅผ ์ฌ์ฉํด Confounder ์ ์ฆ๊ฑฐ๋ฅผ ์ฐพ์ ์ ์๋ค. ๋ชจ์ง๋จ์ ์ธ๋ถํ๊ฐ ๋ค๋ฅธ ๊ฒ๋ณด๋ค ์ฑํฅ ์ ์๊ฐ ๋ ๋๋ค๋ฉด ๋ฌด์์๊ฐ ์๋ ๊ฒ์ด Treatment๋ฅผ ์ ๋ฐํ๊ณ ์์์ ์๋ฏธํ๋ค.
sns.boxplot(x="success_expect", y="propensity_score", data=data_ps)
plt.title("Confounding Evidence");
• Treatment๋ฅผ ๋ฐ์ ๊ทธ๋ฃน์ Treatment๋ฅผ ๋ฐ์ง ์์ ๊ทธ๋ฃน ์ฌ์ด์ ์ค๋ณต์ด ์๋์ง ํ์ธํ๊ธฐ ์ํด ์ฑํฅ ์ ์์ ์ค์ฆ์ ๋ถํฌ๋ฅผ ํ์ธํด ๋ณผ ์ ์๋ค.
sns.distplot(data_ps.query("intervention==0")["propensity_score"], kde=False, label="Non Treated")
sns.distplot(data_ps.query("intervention==1")["propensity_score"], kde=False, label="Treated")
plt.title("Positivity Check")
plt.legend();
โช Treatment ๊ฐ ๊ท ํ์ ์ผ๋ก ์ฒ๋ฆฌ๋์์์ ํ์ธ
• ATE ์ถ์
weight = ((data_ps["intervention"]-data_ps["propensity_score"]) /
(data_ps["propensity_score"]*(1-data_ps["propensity_score"])))
y1 = sum(data_ps.query("intervention==1")["achievement_score"]*weight_t) / len(data)
y0 = sum(data_ps.query("intervention==0")["achievement_score"]*weight_nt) / len(data)
ate = np.mean(weight * data_ps["achievement_score"])
print("Y1:", y1)
print("Y0:", y0)
print("ATE", np.mean(weight * data_ps["achievement_score"]))
โช Treatment ๋ฐ์ ๊ฐ์ธ์ด Treatment๋ฅผ ๋ฐ์ง ์์ ๋๋ฃ๋ณด๋ค ์ฑ์ทจ๋ ๋ฉด์์ 0.38 ํ์ค ํธ์ฐจ๊ฐ ๋ ๊ฒ์ผ๋ก ๊ธฐ๋ํด์ผ ํ๋ค.
โช ์๋ฌด๋ Treatment๋ฅผ ๋ฐ์ง ์์ ๊ฒฝ์ฐ ์ผ๋ฐ์ ์ธ ์ฑ์ทจ ์์ค์ด ํ์ฌ๋ณด๋ค 0.12 ํ์ค ํธ์ฐจ ๋ฎ์ ๊ฒ์ผ๋ก ์์ํด์ผ ํจ
โช ๋งจ ์ฒ์ ์ป์ 0.47 ๊ณผ ๋น๊ตํ๋ฉด X๋ฅผ ํต์ ํ๋ ๊ฒ์ด ๋ณด๋ค Robust ํ ๊ฒฐ๊ณผ์์ ํ์ธํด ๋ณผ ์ ์๋ค.
• P(x) ์ถ์ ๊ณผ์ ์ error ๋ฅผ ์ค๋ช ํ๊ธฐ ์ํด ๋ถ์คํธํธ๋ฉ์ ์ฌ์ฉํ์ฌ ATE ์ถ์ ๊ฐ์ ๋ถํฌ๋ฅผ ์๋์ ๊ฐ์ด ์ ์ํด ๋ณผ ์๋ ์๋ค.
โค Propensity score ์ ์ผ๋ฐ์ ์ธ ๋ฌธ์
• ์ฑํฅ ์ ์ ์ถ์ ์ ํ๋ ๋ฐ ์์ด ์ ํ๋๋ฅผ ๋์ด๋ ค๊ณ ํ ์๋ ์๋ค. ๊ทธ๋ฌ๋ ์ฌ์ค, ์ฑํฅ ์ ์์ ์์ธก๋ ฅ์ ์ต๋ํํ๋ฉด ์ธ๊ณผ ์ถ๋ก ๋ชฉํ๊ฐ ์์๋ ์๋ ์๋ค. ์ฑํฅ ์ ์๋ Treatment์ ํ๋ฅ ์ ์ ์์ธกํ ํ์๊ฐ ์๋ค. ๋จ์ง ๋ชจ๋ confounder ๋ณ์๋ฅผ ํฌํจํ๊ธฐ๋ง ํ๋ฉด ๋๋ค.
• Treatment๋ฅผ ์์ธกํ๋ ๋ฐฉ์์ด ์๋๋ผ Confounder๋ฅผ ์ ์ดํ๋ โโ๋ฐฉ์์ผ๋ก ์์ธก์ ๊ตฌ์ฑํด์ผ ํ๋ค. Treatment ํ๋ฅ ์ ์์ธกํ๋๋ฐ ์๋ฌด๋ฐ ์ํฅ์ ๋ฏธ์น์ง ์๋ ๋ณ์๋ฅผ ํฌํจํ๋ฉด ์ถ์ ๊ฐ์ ๋ถ์ฐ์ด ์ฆ๊ฐํ๋ค.
• ์ฑํฅ ์ ์๊ฐ ์์ ๋ X๋ฅผ ํต์ ํ ํ์๊ฐ ์๋ค. ์ฑํฅ ์ ์๋ ํน์ง ๊ณต๊ฐ์ ๋ํ ์ผ์ข ์ ์ฐจ์ ์ถ์๋ฅผ ์ํํ๋ ๊ฒ์ผ๋ก ์๊ฐํ ์ ์๋ค. ์ด๋ฌํ ์ด์ ๋ก ์ฑํฅ ์ ์๋ฅผ ๋ค๋ฅธ ๋ชจ๋ธ์ ์ ๋ ฅ ๊ธฐ๋ฅ์ผ๋ก ์ทจ๊ธํ ์ ์๋๋ฐ, ํ๊ท๋ชจ๋ธ์ ๋๋ฆฐ ์์๋ฅผ ์ดํด๋ณด๋ฉด
smf.ols("achievement_score ~ intervention + propensity_score", data=data_ps).fit().summary().tables[1]
์ด์ ์ ์ป์ 0.47๋ณด๋ค ๋ฎ๊ฒ ATE ๋ฅผ 0.39๋ก ์ถ์ ํจ์ ํ์ธํด ๋ณผ ์ ์๋ค.
'1๏ธโฃ AIโขDS > ๐ฅ Casual inference' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[The Brave and True] 13. Difference-in-Differences (0) | 2023.07.20 |
---|---|
[The Brave and True] 12. Doubly Robust Estimation (0) | 2023.07.14 |
[The Brave and True] 10. Matching (0) | 2023.07.11 |
[The Brave and True] 9. Non Compliance and LATE (0) | 2023.07.04 |
[The Brave and True] 8. Instrumental variables (0) | 2023.07.03 |
๋๊ธ