《실전 인과추론 시리즈 ⑤ - G-Computation 해부하기》

 

 

 

✨ 시작 질문

 

“한 환자가 혈압약을 먹고 나서 혈압이 내려갔다면,
그 환자가 약을 먹지 않았다면 어땠을까?”

 

 

이 질문은 단순해 보이지만, 인과추론에서는 가장 본질적인 의문이다.

 

그런데 여기엔 현실적인 제약이 있다.

우리는 한 환자에 대해 오직 하나의 결과만 관찰할 수 있기 때문이다.

 

  • 약을 먹은 환자 → 결과: 혈압이 낮아졌다 ✅
  • 그런데 약을 먹지 않았을 때의 그 환자 결과는 관찰 불가능하다 ❌

 

이처럼 동일한 개인의 두 개의 결과를 동시에 알 수 없는 상황을

반사실적(counterfactual) 문제라고 한다.

 

 

🔍 왜 어렵나?

 

다음 중 어떤 설명이 진짜일까?

 

  • ✅ 약을 먹었기 때문에 혈압이 낮아졌다
  • ❌ 원래 혈압이 내려가던 사람이 약도 챙겨먹은 것뿐이다

 

우리가 약의 ‘효과(effect)’를 알고 싶다면,

진짜로 약이 없었더라면 결과가 어땠는지를 추정해야 한다.

하지만 현실에선 그 장면을 절대 볼 수 없다.

 

 

👉 그래서 필요한 게 G-Computation이다

 

G-Computation은 관측 가능한 데이터에서

‘약을 먹지 않았더라면 어땠을까?’를 시뮬레이션하는 도구다.

 

예를 들어 이렇게 해석할 수 있다:

 

  • 실제로 약을 먹은 환자에게
     → “약을 안 먹었더라면”을 가정하고 결과를 예측
  • 실제로 약을 안 먹은 환자에게
     → “약을 먹었더라면”을 가정하고 결과를 예측
  • 그 둘의 평균 차이를 구하면
     → 모든 환자에게 약이 미친 인과효과(ATE)가 된다

 

📌 핵심은 결과(Y)를 잘 예측할 수 있는 모델이 있다면,

실제로 관찰되지 않은 결과(counterfactual)도 예측할 수 있다는 아이디어다.

 

 

💬 한 줄 요약

G-Computation은 관측된 결과만으로는 알 수 없는 ‘다른 세계의 나’를 상상해서 인과효과를 계산하는 방법이다.

 

 


 

✅ G-Computation이 적합한 상황

 

상황 이유
🔢 Outcome이 연속형 변수일 때 예측 모형이 정밀하게 결과값을 추정할 수 있음
(예: 혈압, 체중, 혈당 수치 등)
🎯 Confounder가 대부분 관측 가능할 때 인과추론의 전제 조건 중 하나인
“No unmeasured confounding”을 만족시킬 수 있음
🧠 모델을 통해 해석력을 확보하고 싶을 때 선형회귀, RandomForest 등으로
구조적으로 결과에 영향을 미치는 요인을 파악 가능
🔄 다양한 시나리오에서
counterfactual을 시뮬레이션하고 싶을 때
특정 환자가 치료를 받았을 때/받지 않았을 때
결과를 모두 가정할 수 있음
💡 모델링 자유도가 중요한 연구 설계일 때 머신러닝 적용이나 비선형 예측이 쉬운 접근 방식임

 

 


 

⛔ G-Computation이 어려운 상황

 

상황 이유
⚠️ 중요한 confounder가 누락된 경우 모델이 아무리 좋아도 인과효과 추정은 왜곡됨
🧩 Outcome이 이분형인데
클래스 불균형이 심할 때
예측 모델이 제대로 학습되지 않아 ATE 추정도 왜곡 가능
📉 Outcome이 예측이 어려운 비선형 구조일 때 선형 모델 기반으로는 misspecification 위험 증가
🎲 Randomization 기반 분석이 더 타당한 경우 예: RCT 기반 데이터는
IPTW나 단순 비교가 더 직관적일 수 있음

 

 


 

✍ 구현 단계

 

🔹 Step 1: 데이터 정비

  • 입력 데이터:
    • A: 치료 변수 (1=처치, 0=비처치)
    • Y: 결과 변수 (연속형 또는 이진)
    • X: 공변량들 (confounder: 나이, 성별, 질병력 등)
  • ⚠️ Confounder는 반드시 빠짐없이 포함해야 함
    • 누락된 confounder가 있으면 결과는 편향됨.

 

🔹 Step 2: Outcome Model 학습

  • 전체 데이터를 이용해 결과 Y를 A와 X로 예측하는 모델을 학습함.
    • 선형 회귀, 로지스틱 회귀, 랜덤 포레스트, XGBoost 등 사용 가능
    • 이 모델은 “이 환자가 처치를 받았을 때 결과가 어떻게 될까?”를 예측해주는 함수
  • 예: Y = f(A, X)
model = LinearRegression().fit(X=[treatment, age, bmi, ..., other confounders], y=outcome)

 

🔹 Step 3: Counterfactual Dataset 생성

  • 각 환자에 대해 A=1로 가정한 데이터셋, A=0으로 가정한 데이터셋을 각각 생성
df_cf1 = df.copy()
df_cf1['treatment'] = 1

df_cf0 = df.copy()
df_cf0['treatment'] = 0

 

🔹 Step 4: 예측값 계산

  • 학습된 outcome model을 통해 각 환자에 대해
    • Y^1 = f(1, X)
    • Y^0 = f(0, X)
      를 각각 예측
y_hat1 = model.predict(df_cf1)
y_hat0 = model.predict(df_cf0)

 

🔹 Step 5: ATE 계산

  • 전체 집단에 대해 예측된 결과의 평균 차이를 계산
     ATE (Average Treatment Effect) 추정
ATE = np.mean(y_hat1 - y_hat0)

 

🔹 Step 6 (Optional): Cross-Fitting (교차검증)

  • 데이터 과적합 방지를 위해 K-fold cross-fitting을 수행
  • 각각의 fold에서 모델을 학습하고, test fold에 counterfactual을 적용해 ATE를 반복 계산
  • 평균 ATE를 최종 결과로 보고, 불확실성도 함께 평가 가능

 

🧠 예측 기반 인과추론의 핵심은?

  1. Outcome을 예측할 수 있는 충분히 정교한 모델
  2. 모델은 bias보다는 robustness를 추구해야
  3. confounder는 반드시 포함, mediator는 제외
  4. “예측 잘한다고 인과 잘 아는 건 아니다”라는 점을 늘 의식하기

 

🧠  추가 시각화 혹은 검정

  • SHAP/Partial Dependence Plot으로 X변수가 Y에 미치는 영향 시각화
  • Bootstrapping으로 신뢰구간 추정
  • 다양한 ML 모델로 비교 (예: XGBoost, Random Forest, Lasso 등)

Partial Dependence Plot


💬 요약

  1. 모델 학습: 결과 Y를 예측하는 함수 f(A, X) 학습
  2. Counterfactual 생성: 같은 환자에게 A=1, A=0을 각각 가정
  3. 평균 차이 계산: 전체 집단에 대해 두 예측값의 평균 차이 → ATE

 

 


 

📌 Outcome Model vs Treatment Model

 

  • G-Computation은 Outcome 모델에 기반한다:
    → “결과가 어떻게 나올지를 예측”
  • 반면, Propensity Score 방법Treatment 모델:
    → “누가 처치를 받을 확률이 높은지를 예측”

 

비교 G-Computation Propensity Score
모델 중심 결과 모델 처치 모델
접근 방식 결과를 시뮬레이션 처치 확률로 가중치 부여
민감성 결과 예측 정확도에 민감 PS 추정 정확도에 민감
확장성 머신러닝, 앙상블 적용 쉬움 가중치 적용이 핵심

 

 


 

🔍 Outcome model 성능은 어떻게 평가할까?

 

🔍 예측 vs 인과 추론: 평가 기준이 다르다

G-Computation은 결과 예측 모델(outcome model)을 바탕으로 인과효과를 추정한다.

따라서 흔히 사용하는 AUC, RMSE 등의 예측 정확도 지표는 도움이 되지만, 그것만으로 충분하지 않다.

 

왜냐하면:

  • 모델의 예측이 맞더라도 인과 구조를 잘못 추정하면 ATE는 틀릴 수 있고
  • 반대로 예측 정확도는 낮더라도 인과 구조가 올바르면 ATE는 정확할 수 있다

 

📌 따라서 인과추론을 위한 모델 성능 평가는

bias + variance trade-off, robustness to misspecification, confounder 포함 여부에 기반해야 한다.

 

 

✅ 실무 팁:

 

  • 예측 모델은 너무 복잡하지 않게 (과적합 피하기)
  • 교차검증으로 평균 효과의 변동성 확인
  • 가능한 여러 알고리즘을 사용해 결과 일관성 확인 (ensemble)

 

 


 

❗ 주의사항

 

  • 모델 성능이 낮으면 추정치도 왜곡
  • 모든 confounder가 포함되어야 한다
    (confounding을 통제하지 않으면 인과효과 추정이 무의미)
  • Outcome 모델이 misspecified되면 큰 bias 발생

 

🧠 Outcome model이 불안정할 땐?

 

G-Computation은 outcome model에 전적으로 의존하므로, 다음과 같은 상황에서는 위험하다:

  • confounder가 누락되어 있을 때
  • 모델이 결과의 비선형 패턴을 포착하지 못할 때
  • 특정 변수에 대한 처리효과가 비일관적일 때 (effect heterogeneity)

 

이런 상황에서는 다음 대안을 고려하자:

대안 요약 특이점
DR Estimation G-Computation + IPTW 결합 둘 중 하나만 맞아도 일관된 추정 가능
Causal Forest 효과가 집단마다 다를 때 추정 조건부 평균 인과효과(CATE) 추정 가능
TMLE targeting 단계로 bias 감소 통계학+머신러닝의 접점

 

 


 

🏥 임상 예시: 항고혈압제 효과

 

고혈압 환자에게 항고혈압제를 투여했을 때
→ 모든 환자에 대해 “약을 복용했을 때 vs 안 했을 때” 결과를 상상해보자.

 

 

  • A: 약 복용 여부 (1: 복용, 0: 미복용)
  • Y: 6개월 후 수축기 혈압
  • X: 나이, 성별, 초기 혈압, 체중 등

 

📌 G-Computation은 다음을 수행한다:

 

  1. Y ~ f(A, X) 형태의 회귀모델 학습 (예: 선형회귀, 랜덤포레스트 등)
  2. 모든 환자에 대해
    • A=1인 경우의 예측값 → Y^1
    • A=0인 경우의 예측값 → Y^0
  3. 평균차이 계산 → ATE 추정

 


 

🧪 Python 실전 코드 예시 (Linear Regression 기반)

import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression

# 데이터 예시
df = pd.DataFrame({
    'treatment': [1, 0, 1, 0, 1],
    'age': [65, 70, 55, 60, 58],
    'baseline_bp': [150, 160, 145, 155, 148],
    'outcome': [130, 140, 125, 138, 128]
})

X = df[['treatment', 'age', 'baseline_bp']]
y = df['outcome']

# 모델 학습
model = LinearRegression().fit(X, y)

# Counterfactual 생성
X1 = df.copy()
X1['treatment'] = 1
X0 = df.copy()
X0['treatment'] = 0

# 예측
y1 = model.predict(X1)
y0 = model.predict(X0)

# ATE 계산
ate = np.mean(y1 - y0)
print("Estimated ATE:", ate)

 

 


 

 

🔁 Cross-Fitting으로 과적합 방지

from sklearn.model_selection import KFold

kf = KFold(n_splits=2, shuffle=True, random_state=42)
ates = []

for train_idx, test_idx in kf.split(df):
    train = df.iloc[train_idx]
    test = df.iloc[test_idx]

    model = LogisticRegression()
    model.fit(train[X_cols], train['event'])

    test1 = test.copy(); test1['treatment'] = 1
    test0 = test.copy(); test0['treatment'] = 0

    y1 = model.predict_proba(test1[X_cols])[:, 1]
    y0 = model.predict_proba(test0[X_cols])[:, 1]
    ates.append(np.mean(y1 - y0))

print(f"Cross-Fitted ATE: {np.mean(ates):.3f}")

 

 


 

📦 확장: 머신러닝과 G-Computation의 결합

 

최근에는 G-Computation과 머신러닝 기법을 결합한 방법들이 주목받고 있다.

 

모델 특징
Super Learner 여러 ML 알고리즘을 앙상블
BART (Bayesian Additive Regression Trees) 비선형 인과 추정
TMLE (Targeted Maximum Likelihood Estimation) G-Computation + Propensity Score + targeting

 

이러한 모델들은 G-Computation의 추론력은 유지하면서도

유연한 함수 형태와 높은 예측 정확도를 확보할 수 있게 해준다.

 

 


 

🔍 G-Computation vs IPTW vs TMLE 비교

 

접근법 특징 장점 단점
G-Computation 결과 예측 모델로 인과 추정 직관적, 머신러닝 활용 쉬움 모델 오차에 민감
Propensity Score 처치 확률 조정 해석 용이, RCT 유사 가중치 민감, 효율성↓
TMLE 통계학+ML 접점 double robust, 정교함 구현 복잡

 

항목 G-Computation IPTW TMLE
사용 모델 Outcome model Treatment model 둘 다
Robustness 낮음 낮음 높음
추정 대상 ATE ATE ATE
장점 구현 쉬움 전체 모집단 반영 Doubly Robust
단점 모델 오류 민감 extreme weight 복잡한 구현

 

 

✅ G-Computation이 잘 맞는 상황은?

  • outcome이 연속형이고 예측이 잘 되는 경우 (e.g., 혈압, 체중)
  • confounder가 대부분 관측된 경우
  • 개별 환자 수준 counterfactual을 보고 싶은 경우

 

 


 

⚠️  실무 체크리스트

 

항목 체크 내용
모델 선택 회귀 vs ML, 해석력 vs 성능
변수 선택 Confounder만 포함, mediator 제외
검정 방법 cross-validation, external validation
효과 해석 ATE = 전체 평균 효과
비교 방법 PSM, IPTW 등과 병렬 분석 권장

 

 


 

📌 최종 정리

 

항목 설명
G-Computation 정의 결과 예측 모델을 기반으로 counterfactual을 생성, 인과효과 추정
핵심 장점 전체 인과효과(ATE)를 직관적으로 추정 가능
필요한 조건 적절한 outcome model, 모든 confounder 포함, no unmeasured confounding
확장성 머신러닝 기반 모델과 쉽게 결합 가능
실무 팁 교차검증 필수, mediator 제외, 변수 선택 신중