1 정의
인과 DAG(Directed Acyclic Graph)는 변수를 노드(node)로, 직접 인과 효과를 방향 화살표(edge)로 나타내는 그래프이다.
- Directed: 화살표에 방향이 있다 (\(L \to A\)는 \(L\)이 \(A\)에 인과 효과를 가짐)
- Acyclic: 순환이 없다 (변수가 직접적·간접적으로 자기 자신을 유발하지 않음)
- 공통 원인(common cause)이 측정되지 않았더라도 그래프에 포함되어야 한다
- 역학: Causal Diagram, Causal DAG
- IT: Causal Graph (주로 인과 발견(causal discovery)에서 사용)
| 역학 용어 | IT 용어 | 비고 |
|---|---|---|
| Causal DAG | Causal Graph | 인과 다이어그램 |
| Confounder Path | Backdoor Path | 교란 경로 |
| Collider | Collider | 충돌자 |
| d-separation | d-separation | 조건부 독립 판별 |
| Backdoor Criterion | Backdoor Criterion | 교란 보정 충분 조건 |
| Mediator | Mediator | 매개 변수 |
2 개념 및 원리
2.1 DAG의 기본 요소
노드: 변수 (처리 \(A\), 결과 \(Y\), 교란 \(L\), 충돌자 \(C\) 등)
화살표: \(V \to W\)는 \(V\)가 \(W\)에 직접 인과 효과를 가진다는 의미. 화살표가 없으면 직접 효과가 없다고 가정한다.
경로 (Path): 두 변수 사이를 화살표를 따라 (방향 무시하고) 연결하는 일련의 간선.
2.2 세 가지 기본 구조
(1) 인과 사슬 (Causal Chain) A → B → Y
(2) 분기 (Fork / Common Cause) A ← L → Y
(3) 충돌자 (Collider) A → L ← Y
| 구조 | 주변 연관 | \(L\)로 조건부 시 |
|---|---|---|
| (1) 인과 사슬 \(A \to B \to Y\) | \(A\)와 \(Y\) 연관 | \(B\)로 조건부 → 연관 차단 |
| (2) 분기 \(A \leftarrow L \to Y\) | \(A\)와 \(Y\) 연관 | \(L\)로 조건부 → 연관 차단 |
| (3) 충돌자 \(A \to L \leftarrow Y\) | \(A\)와 \(Y\) 독립 | \(L\)로 조건부 → 연관 개방 |
핵심 규칙: 충돌자를 제외한 변수를 조건부하면 경로를 차단한다. 충돌자를 조건부하면 오히려 경로를 개방한다.
2.3 d-분리 (d-separation)
두 변수가 d-분리되면, 해당 조건부 하에서 통계적으로 독립이다.
경로가 차단(blocked)되는 조건:
- 경로에 비충돌자(non-collider)가 있고, 그 변수를 조건부한 경우
- 경로에 충돌자가 있고, 그 충돌자(또는 그 후손)를 조건부하지 않은 경우
모든 경로가 차단되면 두 변수는 d-분리 → 조건부 독립
예시 (Figure 6.1: \(L \to A \to Y\), \(L \to Y\)):
- 경로 1: \(A \to Y\) (인과 경로) — 항상 개방
- 경로 2: \(A \leftarrow L \to Y\) (교란 경로) — \(L\)로 조건부 시 차단
\(L\)로 조건부하면 교란 경로가 차단되고 인과 경로만 남는다 → 교환가능성 달성.
2.4 교란의 그래프적 정의
DAG에서 \(A\)와 \(Y\) 사이에 인과 경로가 아닌 개방된 경로(backdoor path)가 존재하면 교란이 있다.
Backdoor Criterion (Pearl, 1993):
변수 집합 \(\mathbf{Z}\)가 다음을 만족하면, \(\mathbf{Z}\)로 조건부하여 \(A\)의 \(Y\)에 대한 인과 효과를 식별할 수 있다:
- \(\mathbf{Z}\)의 어떤 변수도 \(A\)의 후손이 아니다
- \(\mathbf{Z}\)가 \(A\)에서 \(Y\)로의 모든 backdoor path를 차단한다
2.5 충돌자 편향 (Collider Bias)
A → L ← Y
\(A\)와 \(Y\)가 \(L\)의 공통 원인이면, \(L\)을 조건부하면 \(A\)와 \(Y\) 사이에 가짜 연관(spurious association)이 생긴다.
예시: 유전형 \(A\)와 흡연 \(Y\)가 심장병 \(L\)의 원인이다. 심장병 환자(\(L=1\))만 분석하면, 유전형이 없는 사람 중 흡연자 비율이 높아진다 — \(A\)와 \(Y\)는 원래 독립인데, \(L\)로 조건부하면 연관이 생긴다.
충돌자의 후손을 조건부해도 같은 문제가 발생한다 (Hernán & Robins, 2020, Ch.6).
3 직관적 설명
3.1 “파이프” 비유: 연관의 흐름
DAG의 경로를 파이프라고 생각하자. 연관(association)은 파이프를 통해 “흐른다.”
- 인과 사슬 (\(A \to B \to Y\)): 물이 \(A\)에서 \(Y\)로 흐른다. \(B\)를 잠그면(조건부) 흐름이 멈춘다.
- 분기 (\(A \leftarrow L \to Y\)): \(L\)에서 양쪽으로 흐른다. \(L\)을 잠그면 흐름이 멈춘다.
- 충돌자 (\(A \to L \leftarrow Y\)): \(L\)이 벽이다 — 양쪽에서 온 물이 \(L\)에서 만나지만 통과하지 않는다. \(L\)을 “열면”(조건부) 오히려 물이 역류한다.
3.2 “공통 결과의 함정”: IT에서의 충돌자 편향
대학 입시(\(L\))에서 운동 능력(\(A\))과 학업 성적(\(Y\))이 모두 합격에 기여한다고 하자. 대학 내부(합격자)만 분석하면, 운동 잘하는 학생일수록 성적이 낮은 것처럼 보인다 — Berkson’s paradox.
IT 예시: “활성 사용자”(\(L\))가 되려면 사용 빈도(\(A\))가 높거나 고가 구매(\(Y\))가 있어야 한다. 활성 사용자만 분석하면, 사용 빈도와 구매 금액 사이에 음의 상관이 생긴다 — 원래 독립인데도.
3.3 왜 DAG를 그려야 하는가?
DAG 없이 인과 추론을 시도하면:
- 어떤 변수를 보정해야 하는지 직관에 의존 → 과도한 보정(충돌자 보정)의 위험
- 어떤 경로가 교란 경로인지, 인과 경로인지 구분 불가
- 매개 변수를 보정하면 직접 효과만 추정하게 되는 문제를 인식 못함
“그래프를 그리기 전에 결론을 내리지 마라.” — Hernán & Robins (2020, Ch.6)
4 왜 필요한가
4.1 변수 선택의 실패 사례
| 실수 | DAG에서의 구조 | 결과 |
|---|---|---|
| 교란 변수를 보정하지 않음 | Backdoor path 개방 | 인과 효과 편향 추정 |
| 충돌자를 보정함 | Collider path 개방 | 가짜 연관 생성 (선택 편향) |
| 매개 변수를 보정함 | 인과 경로 차단 | 직접 효과만 추정 (총 효과 상실) |
| 처리의 후손을 보정함 | 인과 경로 일부 차단 | 과소추정 |
4.2 비즈니스에서의 DAG 활용
| 상황 | DAG 활용 | 결과 |
|---|---|---|
| 추천 알고리즘 효과 분석 | 사용자 활동 → 추천 노출 → 구매 다이어그램 | 어떤 변수를 보정해야 하는지 명확 |
| 마케팅 채널 기여도 | 채널 노출 → 인지 → 방문 → 구매 | 매개 vs. 교란 구분 |
| 이탈 원인 분석 | 기능 사용 → 만족도 → 이탈 | 직접 효과 vs. 간접 효과 분리 |
5 응용 분야
| 분야 | 역학/의학 | IT/비즈니스 | DAG 역할 |
|---|---|---|---|
| 교란 식별 | 흡연-커피-폐암 | 사용 패턴-추천-구매 | Backdoor path 식별 |
| 선택 편향 분석 | 입원 환자 편향 | 활성 사용자 편향 | Collider 구조 발견 |
| 매개 분석 | 약물 → 바이오마커 → 질병 | 기능 → 행동 → 전환 | Direct vs. indirect effect |
| 인과 발견 | 유전체학 | 추천 시스템 피처 관계 | PC, FCI 알고리즘 |
| 도구변수 타당성 | 멘델리안 무작위화 | 쿠폰 무작위 노출 | IV 가정 검증 |
6 예시
6.1 역학: 심장 이식 연구의 DAG
설정:
- L: 질병 중증도
- A: 심장 이식
- Y: 사망
- U: 흡연 여부 (미관측)
DAG:
L → A
L → Y
U → A
U → Y
A → Y
Backdoor paths (A에서 Y로):
(1) A ← L → Y → L로 보정하면 차단
(2) A ← U → Y → U가 미관측이면 차단 불가
결론: U가 미관측이면 L만으로 교환가능성 달성 불가
6.2 IT: 추천 알고리즘 효과 분석의 DAG
설정:
- L: 사용자 과거 행동 (관측)
- A: 추천 알고리즘 노출
- Y: 구매
- M: 클릭 (매개 변수)
- C: "활성 사용자" 라벨 (충돌자)
DAG:
L → A (과거 행동이 추천에 영향)
L → Y (과거 행동이 구매에 영향)
A → M → Y (추천 → 클릭 → 구매)
A → Y (추천 → 직접 구매)
A → C, Y → C (활성 사용자는 추천 노출과 구매 모두의 결과)
분석 시 주의:
✅ L로 보정: backdoor path 차단
❌ M으로 보정: 인과 경로 차단 (총 효과 아닌 직접 효과만 추정)
❌ C로 보정: 충돌자 편향 발생
7 코드 예시
7.1 DAG 구조에 따른 편향 시뮬레이션
import numpy as np
import pandas as pd
np.random.seed(42)
n = 10000
# === 구조 1: 교란 (Fork) ===
# L → A, L → Y, A → Y
L = np.random.binomial(1, 0.5, n)
A_fork = np.random.binomial(1, 0.3 + 0.4 * L)
true_ate = 0.10
Y_fork = np.random.binomial(1, np.clip(0.2 + 0.3 * L + true_ate * A_fork, 0, 1))
naive_fork = Y_fork[A_fork == 1].mean() - Y_fork[A_fork == 0].mean()
adj_fork = 0
for l in [0, 1]:
p_l = (L == l).mean()
y1 = Y_fork[(L == l) & (A_fork == 1)].mean()
y0 = Y_fork[(L == l) & (A_fork == 0)].mean()
adj_fork += (y1 - y0) * p_l
print("=== 구조 1: 교란 (Fork) L → A, L → Y ===")
print(f" True ATE: {true_ate:.3f}")
print(f" Naive: {naive_fork:.3f} (교란 포함)")
print(f" L 보정 후: {adj_fork:.3f} (교란 제거)")
# === 구조 2: 충돌자 편향 (Collider) ===
# A → C ← Y, A ⊥⊥ Y
A_coll = np.random.binomial(1, 0.5, n)
Y_coll = np.random.binomial(1, 0.3, n) # A와 Y는 독립
C = np.random.binomial(1, np.clip(0.1 + 0.3 * A_coll + 0.3 * Y_coll, 0, 1))
naive_coll = Y_coll[A_coll == 1].mean() - Y_coll[A_coll == 0].mean()
# C=1로 조건부 (충돌자 보정 — 잘못된 보정)
c1 = (C == 1)
biased_coll = Y_coll[c1 & (A_coll == 1)].mean() - Y_coll[c1 & (A_coll == 0)].mean()
print("\n=== 구조 2: 충돌자 (Collider) A → C ← Y ===")
print(f" True ATE: 0.000 (A ⊥⊥ Y)")
print(f" Naive: {naive_coll:.3f} (올바름 — A⊥Y)")
print(f" C=1 보정 후: {biased_coll:.3f} (충돌자 편향!)")
# === 구조 3: 매개 변수 보정 (Mediator) ===
# A → M → Y
A_med = np.random.binomial(1, 0.5, n)
M = np.random.binomial(1, np.clip(0.3 + 0.3 * A_med, 0, 1))
Y_med = np.random.binomial(1, np.clip(0.2 + 0.4 * M, 0, 1))
total_effect = Y_med[A_med == 1].mean() - Y_med[A_med == 0].mean()
# M으로 보정하면 총 효과가 아닌 직접 효과만 남음
adj_med = 0
for m in [0, 1]:
p_m = (M == m).mean()
y1 = Y_med[(M == m) & (A_med == 1)].mean()
y0 = Y_med[(M == m) & (A_med == 0)].mean()
adj_med += (y1 - y0) * p_m
print("\n=== 구조 3: 매개 변수 보정 (Mediator) A → M → Y ===")
print(f" 총 효과 (total): {total_effect:.3f}")
print(f" M 보정 후: {adj_med:.3f} (직접 효과만 — 총 효과 상실)")7.2 d-분리 판별 함수
def check_d_separation_simple(dag_edges, path, conditioned_on):
"""
간단한 d-분리 판별 (교육 목적).
path: 변수 목록 (e.g., ['A', 'L', 'Y'])
dag_edges: 방향 간선 집합 (e.g., {('L', 'A'), ('L', 'Y')})
conditioned_on: 조건부할 변수 집합
Returns: (blocked, reason)
"""
for i in range(1, len(path) - 1):
prev_node = path[i - 1]
curr_node = path[i]
next_node = path[i + 1]
# 화살표 방향 확인
into_curr = (prev_node, curr_node) in dag_edges or (next_node, curr_node) in dag_edges
arrows_in = sum([
(prev_node, curr_node) in dag_edges,
(next_node, curr_node) in dag_edges
])
is_collider = arrows_in == 2 # 양쪽에서 화살표가 들어옴
if is_collider:
if curr_node not in conditioned_on:
return True, f"충돌자 {curr_node}가 조건부되지 않음 → 경로 차단"
else: # non-collider
if curr_node in conditioned_on:
return True, f"비충돌자 {curr_node}가 조건부됨 → 경로 차단"
return False, "경로 개방 (차단되지 않음)"
# 테스트
edges = {('L', 'A'), ('L', 'Y'), ('A', 'Y')}
# Backdoor path: A ← L → Y
blocked, reason = check_d_separation_simple(edges, ['A', 'L', 'Y'], set())
print(f"A-L-Y (조건부 없음): blocked={blocked}, {reason}")
blocked, reason = check_d_separation_simple(edges, ['A', 'L', 'Y'], {'L'})
print(f"A-L-Y (L 조건부): blocked={blocked}, {reason}")
# Collider: A → Y ← L
edges2 = {('A', 'Y'), ('L', 'Y')}
blocked, reason = check_d_separation_simple(edges2, ['A', 'Y', 'L'], set())
print(f"A-Y-L (조건부 없음): blocked={blocked}, {reason}")
blocked, reason = check_d_separation_simple(edges2, ['A', 'Y', 'L'], {'Y'})
print(f"A-Y-L (Y 조건부): blocked={blocked}, {reason}")8 관련 주제
이전/다음
- 05 — 효과 수정과 상호작용
- 07 — 교란 (다음)
같은 카테고리
- 인과 추론 프레임워크 총정리 — DAG를 포함한 인과 추론 방법론 비교
- Directed Acyclic Graphs — 상세 DAG 주제 (d-분리, backdoor/frontdoor criterion)
다른 카테고리
9 참고 문헌
- Hernán, M. A. & Robins, J. M. (2020). Causal Inference: What If, Ch.6. Chapman & Hall/CRC.
- Pearl, J. (1995). Causal diagrams for empirical research. Biometrika, 82(4), 669-688.
- Pearl, J. (2009). Causality: Models, Reasoning, and Inference (2nd ed.). Cambridge University Press.
- Greenland, S., Pearl, J. & Robins, J. M. (1999). Causal diagrams for epidemiologic research. Epidemiology, 10(1), 37-48.