지지플랏의 DataScience

(5) Chapter 4: 유용한 선형회귀 Part2: FWL 방법론 본문

Data Science/실무로 통하는 인과추론 with 파이썬

(5) Chapter 4: 유용한 선형회귀 Part2: FWL 방법론

지지플랏 2024. 9. 30. 12:05
반응형

지난 글에서는 온라인통제 실험상에서의 인과추론과 선형회귀모델을 적용하는 방법에 대해서 알아보았다. 이번 글은 선형회귀가 어떻게 무작위 배정을한 것처럼 보이게 할 수 있는지 원리와 그 기반에 되는 직교화의 개념, FWL 방법론에 대해서 작성해본다!


 

1. 글목차

  • 조건부 독립성
  • 직교화: 기하학 관점
  • 선형회귀관점에서의 직교화: FWL
  • 더미변수를 이용한 회귀 분석
  • 심슨의 역설

2. 본문

지난 글에서는 무작위 배정을 통한 교란변수의 통제가 중요하다는 것을 알았다. 하지만, RCT가 불가능하거나 어려운 상황 예컨데, 은행에서 고객들의 대출을 빌려주는 상황에서는 어떻게 처치변수(신용한도)가 채무불이행(결과변수)에 미치는 영향을 정량화 할 수 있을까?  실무로 통하는 인과추론 책 4단원에서는 선형회귀를 통한 방법론을 설명하고 있다. 

4단원을 한마디로 요약하자면 다음과 같다.

조건부 독립성이 유지될 때 직교화를 이용해서 처치가 무작위로 배정된 것처럼 보이게 할 수 있다는 점 이 방법은 FWL 정리를 이용해 적용한다. 

한글로 적혀있는데 도통 무슨 말인지 모르겠다.. 하나씩 파헤쳐보고자 한다.

2.1. 조건부 독립성

 

조건부 독립성이란 두 변수 $T$와 $Y$가 어떤 제 3의 변수 $X$가 주어 졌을 때 독립이라는 뜻이다. 수학적으로는 다음과 같이 표현된다. 

$T \perp Y | X $

  • $T$: 처치 변수, 실험하려는 요소
  • $Y$: 결과 변수, 관측하려는 요소
  • $X$: 혼란 변수, 처치와 결과에 영향을 줄 것으로 생각되는 변수

조건부 독립성이 성립하면 처치 변수 $X$가$T$와 $Y$사이의 모든 상관관계를 설명한다고 볼 수 있다. 다시 말해, 혼란 변수가 되는 $X$를 통제한다면 $T$와 $Y$의 인과 관계를 정확하게 추정할 수 있다는 이야기이다.

 

2.2. 직교화(Orthogonalization): 기하학 관점

직교화의 선형회귀 효과를 이해하기 전에 기하학관점에서 이해해보자. 우리가 생각하는 변수들은 모두 벡터 공간에서 벡터로 이해될 수 있다.(ex $Y, X, T$) 이 벡터들은 n차원의 공간에 존재하며, n은 관측치의 개수이다. 

회귀 분석에서 우리가 수행하는 것은 벡터 투영이다. 예를들어 결과 변수 $Y$를 교란 변수 벡터 $X$에 회귀 한다는 것은 $Y$를 $X$벡터 방향으로 직교 투영(Orthogonal Projection) 시킨다는 의미이며 식으로는 다음과 같이 표현한다. 

(선형대수의 필요성..)

$ \hat{Y} = X(X^{T}X)^{-1}X^{T}Y$

여기서 $\hat{Y}$는 $Y$의 벡터가 $X$벡터의 공간에 투여된 결과이다. 이 벡터는 $Y$가 $X$로 설명될 수 있는 부분만을 나타내는 것이다.

 

반면 잔차 벡터 $e$는 $Y$가 $X$에 투영되지 않는 부분으로 정의된다. 

$e = Y - \hat{Y}$

요약하자면 직교 투영을 통해 변수 간의 상관성을 제거하고 특정 벡터가 다른 벡터에 의해 설명되지 않은 순수한 부분을 구하게 된다. 이과정에서 벡터 공간에서 직교화(orthogonalization)가 이루어지는 것이다. 

위 부분은 다음 블로그를 참고하면 좀 더 정석적으로 알 수 있다.

https://angeloyeo.github.io/2020/08/24/linear_regression.html

 

선형회귀 - 공돌이의 수학정리노트 (Angelo's Math Notes)

 

angeloyeo.github.io

 

 

2.3. 선형회귀 관점에서의 직교화: FWL 

요약하자면 FWL(Frisch-Waugh-Lovell Theorem)은 다음 3단계를 거쳐 진행된다.

  1. 편향 제거 단계: 처치 $T$를 교란 요인 $X$에 대해 회귀하여 처치 잔차 $\widetilde{T} = T - \hat{T}$를 구한다.
  2. 잡음 제거 단계: 결과 $Y$를 교란 요인 $X$에 대해 회귀하여 결과 잔차 $\widetilde{Y} = Y - \hat{Y}$를 구한다.
  3. 결과 모델 단계: 결과 잔치 $\widetilde{Y}$ 를 처치 찬차 $\widetilde{T}$에 대해서 회귀하여 $T$가 $Y$에 미치는 인과효과의 추정을 구한다. 

 

다시말해 직교화는 선형 회귀에서 독립 변수들 사이의 상관성을 제거하는 과정이다. 이를 통해 특정 변수가 다른 변수로부터 독립적으로 보이게 하여 처치가 마치 무작위로 배정된 것 처럼 만드는 방법이다. 이는 FWL 정리를 사용해 두 단계로 구현할 수 있다.

import numpy as np
from sklearn.linear_model import LinearRegression

# 가상의 데이터 생성
np.random.seed(42)
n = 100
T = np.random.rand(n, 1)  # 처치 변수
X = np.random.rand(n, 1)  # 교란 변수
Y = 5 * T + 3 * X + np.random.randn(n, 1)  # 결과 변수, T와 X의 조합으로 생성됨

# 1단계: Y를 X에 회귀시켜 잔차 계산 (X가 Y에 미치는 영향을 제거)
model_Y_X = LinearRegression().fit(X, Y)
Y_residual = Y - model_Y_X.predict(X)

# 2단계: T를 X에 회귀시켜 잔차 계산 (X가 T에 미치는 영향을 제거)
model_T_X = LinearRegression().fit(X, T)
T_residual = T - model_T_X.predict(X)

# 3단계: Y의 잔차를 T의 잔차에 회귀하여 T의 순수한 효과 추정
model_residuals = LinearRegression().fit(T_residual, Y_residual)
beta_T_estimate = model_residuals.coef_

print(f"T의 순수한 효과 (beta_T 추정치): {beta_T_estimate[0][0]:.4f}")

위 단계에서 1, 2 단계가 직교화 과정이다. 

  • 1단계: $Y$를 $X$에 회귀 시켜서 잔차 계산. 결과 변수에서 교란 변수의 영향을 제거하는 역할을 한다.
  • 2단계: $T$를 $X$에 회귀 시켜서 잔차 계산. 처치 변수에서 교란 변수의 영향을 제거하는 역할을 한다. 

 잔차끼리 회귀를 수행하는 3단계는 직교화된 변수들 사이에서 처치 변수의 순수한 인과적 효과를 추정하는 과정이다.$Y$ 의 잔차는 X로 설명할 수 없는 Y의 변동 부분만 남게되며, $T$의 잔차는 $X$로 설명할 수 없는 $T$의 변동만 남게 된다

 

2.4. 더미변수를 이용한 회귀분석

책에 있는 예제를 가져와보자. 지출을 예측하기 위해서 신용한도를 처치변수로 추론하는 모델이며, 추후 임금을 통해 보정하는 방식으로 이루어진다.

  • $Y$: 결과변수 - 신용불량
  • $T$: 처치변수 - 신용한도
  • $X$: 혼란변수 - 임금

1. 데이터 불러오기

import pandas as pd
import graphviz as gr
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import statsmodels.formula.api as smf
risk_data_rnd = pd.read_csv("./data/risk_data_rnd.csv")
risk_data_rnd.head()

 

2. 단순회귀 적합하기

plt_df = (risk_data_rnd
          .assign(size=1)
          .groupby("credit_limit")
          .agg({"default": "mean", "size":sum})
          .reset_index())

plt.figure(figsize=(10,4))
sns.scatterplot(data=plt_df,
                x="credit_limit",
                y="default",
                size="size",
                sizes=(1,100))
sns.regplot(data = plt_df,
            x="credit_limit",
            y="default",
            ci = None)
plt.ylim(-0.1,0.3)

plt.title("Default Rate by Credit Limit")
plt.show()

model = smf.ols("default ~ credit_limit", data=risk_data_rnd).fit()
model.summary().tables[1]

 

먼저 신용한도와 신용불량을 단순 회귀 모델을 적합하면  계수가 음수가 나온다. 그대로 해석하면 신용한도가 높을 수록 채무불이행률은 낮아진다는 것이다. 하지만 이 부분은 현재 교란변수를 보정하지 않았기 때문에 올바르지 않은 결과일 확률이 높다. 

따라서 임금을 이용하여 보정변수로 사용할 수 있으며, 이를 위해 credit_score 1을 binning하여 적합할 수 있다. 먼저 구간 별로 히스토그램을 그리면 다음과 같다.

plt.figure(figsize=(15,6))
sns.histplot(data=risk_data_rnd,
             x="credit_limit",
             hue="credit_score1_buckets",
             kde=True,
             palette="Paired",
             alpha = 0.5);
plt.title("Conditional random experiment")
plt.show()

이후 credit_score 구간별로 더미화한뒤 적합한 결과는 다음과 같다.

risk_data_dummies = (risk_data_rnd
                     .join(pd.get_dummies(risk_data_rnd["credit_score1_buckets"],
                                          prefix="sb",
                                          drop_first=True)))

model = smf.ols(
    "default ~ credit_limit + sb_200+sb_400+sb_600+sb_800+sb_1000",
    data=risk_data_dummies
).fit()

model.summary().tables[1]

다중 회귀식 해석에 따라, 다른 credit_score을 고정시켰을때(조건부 확률일 때) 채무불이행률은 신용한도와 양수의 관계를 가진다.  단위가 작은것은 신용한도가 0 ~ 1000단위이며 채무불이행률은 0과 1값을 가지기 때문에 단위차임을 확인할 수 있다. 

위 binning을 바탕으로 임금별로 선형회귀를 각각 적합하면 다음과 같다. 

plt_df = (risk_data_rnd
          .assign(risk_prediction = model.fittedvalues)
          .groupby(["credit_limit", "credit_score1_buckets"])
          ["risk_prediction"]
          .mean()
          .reset_index())

plt.figure(figsize=(10,4))
sns.lineplot(data=plt_df,
             x="credit_limit", 
             y="risk_prediction", 
             hue="credit_score1_buckets", 
             palette = 'Set1');
plt.title("Fitted values by group")
plt.legend(loc='center left', bbox_to_anchor=(1, 0.5))
plt.show()

 

2.5. 심슨의 역설(Simpson's paradox)

위 사례를 보면서 언뜻 심슨의 역설이 생각났다. 심슨의 역설이란, 전체 데이터를 분석했을 때 경향과 그룹으로 나누어 분석했을 때의 경향이 서로 반대되는 상황을 말한다. 영국의 통계학자 에드워드 심슨이 정리한 역설이다.

 

위 내용을 보았을때, 회귀 분석에서 교란변수($X$)를 독립변수로 추가하는 것은 심슨의 역설을 해소하고, 처치 변수($T$)와 결과 변수($Y$)간의 정확한 인과관계 추론을 하는데 중요한 역할을 한다는 것을 알 수 있다. 

 

3. 출처와 링크

 

 

 

반응형