(스터디) 실무로 통하는 인과추론 with 파이썬 - PART 3
[실무로 통하는 인과추론 with 파이썬]을 읽고 내용을 정리한다.
(스터디) 실무로 통하는 인과추론 with 파이썬 - PART 2에서 이어집니다.
PART 3. 이질적 효과와 개인화
6장 이질적 처치효과
실험 대상 i마다 처치 효과 Γi가 다를 수 있다. 어떤 대상이 처치에 더 잘 반응하는지 아는 것은 처치 대상을 결정하는 데 중요한 역할을 한다.
ex) 할인에 더 민감한 고객이라면 할인 쿠폰을 주면 유익하지만, 그렇지 않다면 쿠폰의 효과가 없을 수 있다.
평균 처치효과 ATE | |
이산형일 때 |
연속형일 때 |
조건부 평균 처치효과 CATE : X에 대한 조건부는 각 실험 대상이 공변량 X로 정의된 특성에 따라 처치효과가 다를 수 있음을 의미한다. |
|
머신러닝의 목적: 결과(Y) 예측 <> CATE의 목적: 결과에 미치는 처치(X)의 효과 추정
ATE와 마찬가지로, CATE도 회귀변수를 통해 추정할 수 있다.
→ 처치와 공변량 간의 상호작용을 모델에 포함하여, 해당 공변량에 따라 효과가 어떻게 변하는지 모델이 학습할 수 있게 한다.
- 공변량을 정의한다.
- 해당 공변량과 처치의 상호작용 항을 포함한다.
- 모델을 추정하고, 예측된 기울기를 매개변수 추정값으로부터 추출한다.
- 데이터셋을 train과 test로 나누어서 train에서는 회귀모델을, test에서는 예측모델을 수행하여 CATE 예측을 평가한다.
랜덤화된 데이터가 없으면 추정할 수 있는 그룹 효과로서의 CATE 개념이 유효하지 않다. (CATE 추정할 때는 랜덤화된 데이터가 무엇보다 중요하다.)
7장 메타러너
메타러너(metalearner):
- 기존 예측 머신러닝 알고리즘을 활용해서 처치효과를 추정하는 방법
- ATE 추정에 사용할 수 있지만, 일반적으로는 CATE 추정에 주로 사용한다. (고차원 데이터를 잘 처리하기 때문)
S 러너: 가장 기본적인 방식으로, 단일 머신러닝 모델을 사용하여 추정한다. 처치효과를 직접 출력하지는 않고, 반사실 예측값을 구한다. → 다양한 처치에서의 예측이 가능하다. (T 러너, X 러너와 달리 연속형 처치에서도 사용 가능) 처치효과를 0으로 편향시키려는 경향이 있다.
from lightgbm import LGBMRegressor
X = ["month", "weekday", "is_holiday", "competitors_price"]
T = "discounts"
y = "sales"
np.random.seed(123)
s_learner = LGBMRegressor()
s_learner.fit(train[X+[T]], train[y]);
T 러너: 잠재적 결과 Yt를 추정하기 위해 모든 처치에 대해 하나의 결과 모델 μt(x)를 적합시킨다. 단순하여 구현이 쉽다는 장점이 있지만, 상황에 따라 정규화 편향이 발생하기 쉽다.
from lightgbm import LGBMRegressor
np.random.seed(123)
m0 = LGBMRegressor()
m1 = LGBMRegressor()
m0.fit(train.query(f"{T}==0")[X], train.query(f"{T}==0")[y])
m1.fit(train.query(f"{T}==1")[X], train.query(f"{T}==1")[y]);
t_learner_cate_test = test.assign(
cate=m1.predict(test[X]) - m0.predict(test[X])
)
X 러너: T 러너보다 복잡하다. 실험군과 대조군의 표본 크기 차이가 클 경우, X 러너의 성능이 훨씬 좋다.
from sklearn.linear_model import LogisticRegression
from lightgbm import LGBMRegressor
# 성향점수 모델
ps_model = LogisticRegression(penalty='none')
ps_model.fit(train[X], train[T])
# 첫 번째 단계 모델
train_t0 = train.query(f"{T}==0")
train_t1 = train.query(f"{T}==1")
m0 = LGBMRegressor()
m1 = LGBMRegressor()
np.random.seed(123)
m0.fit(train_t0[X], train_t0[y],
sample_weight=1/ps_model.predict_proba(train_t0[X])[:, 0])
m1.fit(train_t1[X], train_t1[y],
sample_weight=1/ps_model.predict_proba(train_t1[X])[:, 1]);
# 두 번째 단계 모델
tau_hat_0 = m1.predict(train_t0[X]) - train_t0[y]
tau_hat_1 = train_t1[y] - m0.predict(train_t1[X])
m_tau_0 = LGBMRegressor()
m_tau_1 = LGBMRegressor()
np.random.seed(123)
m_tau_0.fit(train_t0[X], tau_hat_0)
m_tau_1.fit(train_t1[X], tau_hat_1);
# CATE 추정 단계
ps_test = ps_model.predict_proba(test[X])[:, 1]
x_cate_test = test.assign(
cate=(ps_test*m_tau_0.predict(test[X]) +
(1-ps_test)*m_tau_1.predict(test[X])
)
)
S 러너 | T 러너 | X 러너 |
S 러너는 단순히 특성 중의 하나로 처치를 포함하는 머신러닝 모델이다. |
T 러너가 각자 T = 1, T = 0에서 머신러닝 모델을 학습한다. 예측 시점에 두 모델을 모두 사용해서 실험군과 대조군의 차이를 추정한다. |
X 러너는 두 가지 단계에서 머신러닝 모델과 성향점수 모델을 학습한다. 예측 시, 두 번째 단계의 모델과 성향점수 모델만 활용한다. |
이중/편향 제거 머신러닝 또는 R 러너:
ATE 편향 문제를 해결하기 위해 나온 방법으로, FWL 정리의 정제된 버전으로 볼 수 있다.
결과와 처치의 잔차를 구성할 때 머신러닝 모델을 사용하는 방법
관측되지 않은 교란 요인이 없다면, 다음과 같은 직교화 과정으로 ATE를 구할 수 있다.
- 머신러닝 회귀 모델 μy 를 사용하여 특성 로 결과 추정
- 머신러닝 회귀 모델 μt를 사용하여 특성 로 처치 추정
- 잔차 Y~=Y−μy(X)와 T~=T−μt(X) 계산
- 결과의 잔차를 처치 잔차에 회귀 → Y~=α+τT~에서 는 인과 매개변수 ATE이며, OLS를 사용하여 추정할 수 있다.
과적합 문제 발생시 잔차 회귀 결과가 0에 편향될 수 있다. → 교차 예측과 아웃 오브 폴드 잔차
교차 예측과 아웃 오브 폴드 잔차: 데이터를 K개의 폴드로 분할하고, 그중 K-1개의 폴드에서 모델을 추정한 후 남겨진 폴드에서 잔차를 얻는다. 전체 데이터셋에 대한 잔차를 얻기 위해 동일한 과정을 K번 반복한다. 이러한 방식을 사용하면 모델이 과적합되더라도 잔차를 의도적으로 0으로 만들지 않는다.
y_star = y_res/t_res
w = t_res**2
cate_model = LGBMRegressor().fit(train[X], y_star, sample_weight=w)
test_r_learner_pred = test.assign(cate = cate_model.predict(test[X]))