1 정의
“\(T\) 와 \(Y\) 사이의 인과 관계는, \(T\) 로 들어오는 화살표로 시작하는 차단되지 않은 noncausal path 가 적어도 하나 있으면 confounded 다. 모든 confounding 을 제거하려면, 이러한 모든 path 를 차단해야 한다.”
(Buisson, 2021, Ch.5; Pearl, 2009)
수식 표기:
\[ \text{BC : 모든 backdoor path 가 controlled 변수 집합 } \mathbf{Z} \text{ 로 차단됨} \]
여기서 backdoor path = \(T\) 로 들어오는 화살표 (\(\to T\)) 로 시작하는 noncausal path.
“Backdoor” = “뒷문”.
T (cause of interest) ──→ Y (effect of interest) ← Front door
↑
│ (← arrows into T)
Confounder ← Back door
│
→ Y
Confounder 는 T 의 뒷문 으로 들어와 Y 에 도달하는 비-인과 경로를 만든다.
BC 는 이 뒷문들을 막는 도구. 앞문 (causal path) 은 그대로 두면서 뒷문만 차단.
→ DCC 의 “모든 cause 통제” 보다 정밀. 뒷문만 막음.
2 개념 및 원리 — BC 의 전제 정의
2.1 Path 의 분류
E-BUI3-3 에서 도입한 정의 재방문:
- Path: 두 변수 사이 화살표로 연결된 sequence (방향 무관, 변수 중복 없음)
- Causal Path: 모든 화살표가 같은 방향 (chain). \(T\) 의 영향이 \(Y\) 로 전달되는 경로.
- Noncausal Path: 적어도 하나의 fork 또는 collider 포함.
C-Mart 사례에서 NumberOfCustomers 와 BottledWaterSales 사이 path 7 개:
- NumberOfCustomers → IceCreamSales → BottledWaterSales (causal — chain)
- NumberOfCustomers → BurgerSales → FrenchFrySales → BottledWaterSales (causal — chain)
- NumberOfCustomers → BurgerSales → FrenchFrySales ← Mindset → BottledWaterSales (noncausal — fork at FrenchFry… 잠깐, FrenchFry 가 collider here. noncausal due to collider)
- (이하 5개 더, 모두 collider 또는 fork 포함 → noncausal)
→ 7 path 중 2 개만 causal. 나머지 5 개는 noncausal — 통제 결정 시 점검 대상.
Causal path: \(T\) 가 \(Y\) 에 인과적 영향 을 주는 경로. 이 경로의 효과는 \(T\) 의 진짜 효과의 일부이므로 차단하면 안 됨.
Noncausal path: \(T\) 와 \(Y\) 사이 상관을 만들지만 인과 아님 의 경로. 이 경로의 효과는 confounding bias 이므로 차단해야 함.
→ BC 의 핵심: causal path 는 보존, noncausal path 만 차단.
DCC 의 “mediator 제외” 가 같은 의미 — chain 의 mediator 통제는 causal path 차단이므로 금지.
2.2 Blocked vs Unblocked Path
Path 가 blocked (차단됨) 인 조건:
- Path 위의 비-collider 변수가 회귀에 통제됨, OR
- Path 위의 collider 가 회귀에 통제되지 않음 (그리고 그 collider 의 후손도 통제되지 않음)
Path 가 unblocked (차단되지 않음) 인 조건:
- Path 위에 통제된 비-collider 변수가 없음, AND
- Path 위의 모든 collider 가 통제됨 (또는 그 후손이 통제됨)
→ Collider 와 비-collider 의 통제 효과가 정반대.
Path = 강. 변수의 통제 = 댐.
비-collider 의 통제: 강에 댐을 세움 → 정보 흐름 차단. Collider 의 통제: 본래 막혀 있던 지하 통로를 뚫음 → 정보 흐름 개방.
[비-collider 통제]
T ── A ── Y
↓ (통제)
T ── [A] ── Y ← 차단됨
[Collider 통제]
T ── C ── Y
(양쪽 화살표가 C 로)
↓ (통제)
T ←── C ──→ Y ← 새 경로 개방
→ 변수의 역할 (collider vs 비-collider) 에 따라 통제 효과가 정반대. CD 가 정확해야 결정.
2.3 BC 의 알고리즘
1. T 로 들어오는 화살표 모두 식별 (T 의 직접 원인)
2. 각 직접 원인에서 시작하는 path 모두 열거 (T 부터 Y 까지)
3. 각 path 가 causal 인지 noncausal 인지 분류
4. Noncausal path 가 자연스럽게 차단되었는지 점검:
- Path 위에 collider 가 있으면서 그 collider 가 통제 안 되면 → 자연 차단
- 그 외에는 unblocked → 통제 변수 추가 필요
5. Unblocked noncausal path 를 차단하는 최소 통제 변수 집합 찾기
→ 알고리즘적이지만 손으로는 시간 걸림. dowhy 같은 라이브러리 사용 권장.
3 C-Mart 사례 — BC 적용 자세히
3.1 Block 1 — BC
CD:
NumberOfCustomers ──→ IceCreamSales ──→ BottledWaterSales
──→ BurgerSales ──→ FrenchFrySales ──→ BottledWaterSales
Backdoor (T 로 들어오는 화살표): NumberOfCustomers → IceCreamSales
이 path 를 따라가는 backdoor:
IceCreamSales ← NumberOfCustomers → BurgerSales → FrenchFrySales → BottledWaterSales
분류:
- noncausal? Yes (NumberOfCustomers 에서 fork)
- 자연 차단? No (collider 없음, 통제 안 함)
- → unblocked → 통제 필요
차단 방법: path 위 비-collider (NumberOfCustomers, BurgerSales, FrenchFrySales) 중 하나 통제.
Buisson 의 권장: T 의 직접 원인 (NumberOfCustomers) 우선.
이유: 이 변수가 다른 backdoor path 에도 동시에 존재할 가능성이 높음 → 한 변수로 여러 path 차단.
NumberOfCustomers 통제 시:
- Path 1 차단 (위에서 시연)
- 다른 path (NumberOfCustomers 가 시작인 모든 path) 도 자동 차단
- “직접 원인” 한 개로 그 변수의 모든 영향을 회귀에 흡수
만약 BurgerSales 또는 FrenchFrySales 만 통제하면:
- Path 1 은 차단되지만
- NumberOfCustomers 의 다른 backdoor (있다면) 는 미처리
- 분석가가 각 path 일일이 점검해야
→ “T 의 직접 원인 우선” 이 분석 작업을 줄임.
3.2 Block 2 — BC
CD:
AverageCustomerAge ──→ IceCreamSales
──→ SodaSales (collider)
CustomerHealthMindset ──→ BottledWaterSales
──→ SodaSales (collider)
──→ FrenchFrySales (collider, Block 1 과 결합)
Backdoor path:
IceCreamSales ← AverageCustomerAge → SodaSales ← CustomerHealthMindset → BottledWaterSales
분류:
- noncausal? Yes (AverageAge 에서 fork, SodaSales 에서 collider, HealthMindset 에서 fork)
- 자연 차단? Yes (SodaSales 가 collider, 통제 안 함 → 자동 차단)
- → blocked → 통제 불필요
→ Block 2 의 미관측 변수 (AverageAge, HealthMindset) 가 회귀에 없어도 OK. SodaSales 의 collider 가 path 를 자연스럽게 막음.
→ DCC 와 결정적 차이. DCC 는 두 미관측 변수의 부재로 적용 불가하지만, BC 는 collider 자연 차단으로 우회.
만약 분석가가 “SodaSales 도 추가하면 좋지 않을까” 라고 통제하면:
- Collider 가 통제됨 → path 가 unblocked 됨
- 가짜 confounding 발생
- IceCreamSales → BottledWaterSales 추정 편향
→ Collider 식별 + 회피가 BC 의 핵심.
4 M-Pattern — Forks-Collider-Forks 구조
4.1 정의
Block 2 의 path 를 시각화:
AverageAge HealthMindset
╲ ╱
╲ ╱
IceCream BottledWater
↘
SodaSales
(collider)
또는 재배열:
AverageAge HealthMindset
│ │
│ │
└──→ SodaSales ←──┘ (collider)
│ │
↓ ↓
IceCreamSales BottledWaterSales
이 모양이 알파벳 “M” 을 닮음 → M-pattern.
분석가의 자연스러운 직감: “SodaSales 가 IceCream 과 BottledWater 와 상관이 있으니 confounder 같다. 통제하자.”
함정:
- SodaSales 는 “confounder 처럼 보이지만” 사실 collider
- 통제하면 가짜 confounding 발생
이 함정은 흔함. M-pattern 의 시각적 인식 + collider 식별 능력이 분석가의 무기.
→ CD 를 그릴 때 M 모양이 보이면 “조심” 신호.
4.2 실제 사례 — Smoking · Seatbelt · Lung Cancer
The Book of Why (Pearl & Mackenzie, 2018) 에서 인용된 실제 사례.
토바코 회사가 안전벨트 사용 통계를 사용해 흡연의 폐암 효과를 축소 추정하려 했다.
그들의 회귀 모형:
\[ \text{LungCancer} = \beta_S \cdot \text{Smoking} + \beta_B \cdot \text{SeatbeltUse} + \cdots \]
근거:
- “안전벨트 사용은 건강 의식의 indicator. 통제하면 건강 행동 보정 가능.”
- “회귀에 더 많은 변수 = 더 정확한 추정.”
결과: \(\beta_S\) 가 의도적으로 작게 나타남. 흡연의 효과가 축소되어 보임.
문제: 안전벨트 사용은 collider 였다.
HealthConsciousness RiskTolerance
│ │
│ │
└──→ SeatbeltUse ←─┘ (collider!)
│ │
↓ ↓
LungCancer Smoking
- HealthConsciousness 가 강하면 안전벨트 ↑, 폐암 ↓ (운동·식이)
- RiskTolerance 가 강하면 안전벨트 ↓, 흡연 ↑
SeatbeltUse 가 두 trait 의 collider. 통제하면 두 trait 사이 가짜 음의 상관 → Smoking 과 LungCancer 사이 가짜 음의 상관 (collider bias).
→ “통제 변수를 더 추가하면 더 정확” 의 단순 직감이 통계학적으로 잘못됨을 보여주는 고전 사례.
이 사례는 학술 논쟁뿐 아니라 비즈니스에 직접 적용:
- 고객 분석: 회원 등급은 collider 가 될 수 있음 (구매 + 활동의 결과)
- HR 분석: 승진은 collider (성과 + 사내 정치)
- 의료 데이터: 입원은 collider (병1 + 병2)
이런 collider 변수를 회귀에 추가하면 가짜 상관 발생.
→ 분석가가 항상 자문: “이 변수가 collider 인가?”
5 CD 의 부정확성에 대한 BC 의 취약성
만약 마케팅 팀이 CD 를 잘못 그렸다면:
실제: HealthMindset ──→ SodaSales
잘못: SodaSales ──→ HealthMindset
이 한 화살표 방향 오류가 SodaSales 의 역할을 collider 에서 mediator 로 바꿈.
BC 적용 결과:
- 잘못된 CD 에서: SodaSales 가 mediator 로 보이므로 통제하면 path 차단된다고 잘못 판단
- 실제로는: SodaSales 가 collider 이므로 통제하면 path 가 개방됨
→ 분석가가 CD 의 정확성을 점검하지 않으면 BC 는 잘못된 처방을 줌.
DCC 였다면? “Cause of T or Y” 모두 통제 — 화살표 방향에 덜 민감 (SodaSales 가 cause of T 또는 Y 가 아니므로 어느 방향이든 통제 안 함).
| CD 정확성 | DCC | BC |
|---|---|---|
| 완전 정확 | 작동 (over-control) | 작동 (효율적) |
| 화살표 방향 일부 오류 | 작동 (robust) | 잘못 작동 가능 |
| 변수 일부 누락 | 부분 작동 | 부분 작동 |
| Mediator 잘못 식별 | 잘못 작동 (over-adjustment) | 잘못 작동 |
→ DCC 는 “구조적 오류” 에 robust, BC 는 “구조적 오류” 에 fragile.
분석가의 선택: CD 가 잘 검증되었으면 BC, 아니면 DCC. 두 결과를 비교하면 더 안전.
6 응용 — BC 의 다양한 사례
6.1 SaaS Onboarding
CD:
PastExp JobRole Cohort SignupChannel
↓ ↓ ↓ ↓
└────→ Tutorial ──→ Retention
└────────────────────↗ (PastExp 도 직접)
└────────────────────↗
(Cohort 는 Tutorial 과 무관, Retention 만 영향 가정)
T = Tutorial, Y = Retention.
Tutorial 의 직접 원인: PastExp, JobRole, SignupChannel. Retention 의 직접 원인: Tutorial, PastExp, JobRole, Cohort, SignupChannel.
Backdoor path:
- Tutorial ← PastExp → Retention (noncausal, fork) → 통제 필요
- Tutorial ← JobRole → Retention (noncausal, fork) → 통제 필요
- Tutorial ← SignupChannel → Retention (noncausal, fork) → 통제 필요
Cohort 는 Tutorial 의 원인 아니므로 backdoor 가 아님 → BC 통제 불필요.
DCC 라면 Cohort 도 통제. BC 가 더 정밀 — Cohort 는 Y 만 영향이므로 confounder 아님.
6.2 E-commerce 추천
CD:
PastFrequency SearchIntent ConversionContext
↓ ↓ ↓
└──→ Recommendation ──→ Purchase
└──→ ────────────────↗
└──→ ────────────────↗
(ConversionContext 만 Purchase, Recommendation 무관)
Backdoor: Recommendation ← PastFrequency → Purchase, Recommendation ← SearchIntent → Purchase.
→ PastFrequency, SearchIntent 통제. ConversionContext 는 BC 통제 불필요.
7 코드 예시 — BC 자동 식별 + 시뮬레이션
7.1 BC 자동 식별 (dowhy 활용)
from dowhy import CausalModel
import pandas as pd
import numpy as np
# 가상 C-Mart 데이터 생성
np.random.seed(42)
n = 5000
# 미관측 변수
age = np.random.normal(35, 10, n)
mindset = np.random.normal(0, 1, n)
# 관측 변수
n_customers = np.random.normal(100, 30, n)
ice_cream = 0.3 * n_customers + 0.05 * (45 - age) + np.random.normal(0, 5, n)
burger = 0.5 * n_customers + np.random.normal(0, 5, n)
fries = 0.6 * burger + 0.2 * mindset + np.random.normal(0, 5, n)
soda = 0.2 * n_customers + 0.05 * (45 - age) + 0.2 * mindset + np.random.normal(0, 5, n)
water = (
0.0 * ice_cream # 진짜 인과 효과 = 0
+ 0.4 * fries
+ 0.5 * mindset
+ np.random.normal(0, 5, n)
)
df = pd.DataFrame({
"ice_cream": ice_cream, "water": water,
"n_customers": n_customers, "burger": burger,
"fries": fries, "soda": soda,
})
# CausalModel — CD 를 GraphViz 표기로
graph_dot = """
digraph {
n_customers -> ice_cream;
n_customers -> burger;
burger -> fries;
fries -> water;
n_customers -> soda;
ice_cream -> water;
}
"""
model = CausalModel(
data=df,
treatment="ice_cream",
outcome="water",
graph=graph_dot,
)
# Identify effect (BC 자동 적용)
identified = model.identify_effect()
print("=== BC 의 식별 결과 ===")
print(identified)
# Backdoor variables 확인
print(f"\nBackdoor 변수: {identified.get_backdoor_variables()}")dowhy 가 자동으로 처리하는 것
dowhy 는:
- CD 를 입력받음
- 모든 path 자동 열거
- Backdoor path 식별
- Collider 식별 + 자연 차단 점검
- 최소 통제 변수 집합 반환
분석가의 작업: CD 입력 + 결과 검토.
→ 비즈니스 분석 파이프라인에 표준화.
7.2 M-pattern 시뮬레이션
import statsmodels.api as sm
# M-pattern: Age, Mindset → SodaSales (collider)
np.random.seed(42)
n = 5000
age = np.random.normal(0, 1, n)
mindset = np.random.normal(0, 1, n)
# Soda 는 collider
soda = 0.5 * age + 0.5 * mindset + np.random.normal(0, 0.5, n)
# IceCream, Water 는 각각 한쪽 trait 만 의존 (직접 인과 0)
ice_cream = 0.7 * age + np.random.normal(0, 0.5, n)
water = 0.7 * mindset + np.random.normal(0, 0.5, n)
# 진짜 IceCream → Water 인과 효과 = 0
df_m = pd.DataFrame({
"ice_cream": ice_cream, "water": water,
"age": age, "mindset": mindset, "soda": soda,
})
# 회귀 1: 단순
m1 = sm.OLS(df_m["water"], sm.add_constant(df_m["ice_cream"])).fit()
print(f"=== 단순: water ~ ice_cream ===")
print(f" beta = {m1.params['ice_cream']:.3f} (진짜 0)")
# 회귀 2: BC 적용 (collider soda 통제 안 함, age, mindset 미관측 가정)
print(f"\n=== BC: 통제 변수 없음 (collider 자연 차단) ===")
print(f" beta = {m1.params['ice_cream']:.3f}")
print(f" → BC 가 collider 자연 차단 활용해 미관측 변수 통제 불필요")
# 회귀 3: 잘못된 통제 (soda 추가)
m3 = sm.OLS(df_m["water"], sm.add_constant(df_m[["ice_cream", "soda"]])).fit()
print(f"\n=== 잘못: water ~ ice_cream + soda ===")
print(f" beta = {m3.params['ice_cream']:.3f} ← collider bias!")예상 결과:
- 단순 (BC 처방): \(\beta \approx 0\) (정확, collider 자연 차단)
- Soda 추가: \(\beta \approx -0.3\) (가짜 음의 상관 — collider bias)
같은 데이터, 같은 진짜 효과 (0), 그러나 통제 변수 선택에 따라 0 vs -0.3.
→ Collider 통제는 “분석을 망치는 가장 빠른 방법”. BC 가 이를 회피하는 도구.
7.3 DCC vs BC 비교 시뮬레이션
# 같은 시나리오에서 DCC vs BC
print("\n=== DCC vs BC 비교 ===")
# 미관측 변수 처리: 시뮬레이션에서는 관측되었다고 가정 (현실에서는 불가)
df_full = df_m.copy() # age, mindset 모두 관측
# DCC: cause of T (age) + cause of Y (mindset) 통제
m_dcc = sm.OLS(df_full["water"], sm.add_constant(df_full[["ice_cream", "age", "mindset"]])).fit()
print(f"\nDCC: water ~ ice_cream + age + mindset")
print(f" beta = {m_dcc.params['ice_cream']:.3f}, SE = {m_dcc.bse['ice_cream']:.3f}")
# BC: 통제 변수 없음 (collider 자연 차단)
m_bc = sm.OLS(df_full["water"], sm.add_constant(df_full["ice_cream"])).fit()
print(f"\nBC: water ~ ice_cream (only)")
print(f" beta = {m_bc.params['ice_cream']:.3f}, SE = {m_bc.bse['ice_cream']:.3f}")
print("\n→ DCC, BC 모두 정확한 추정. 단 BC 가 변수 더 적음.")
print("→ 미관측 시나리오 (age, mindset 관측 불가): BC 만 적용 가능.")이 시나리오에서:
- DCC 는 age, mindset 의 데이터 필요
- BC 는 collider (soda) 의 자연 차단 활용해 미관측 변수 우회
미관측 변수가 있는 현실에서 BC 가 결정적 우위.
그러나 BC 의 비용: CD 가 정확해야 함. CD 가 틀리면 BC 가 잘못된 결과.
→ CD 검증 + BC 적용. CD 검증 부족하면 DCC 로 안전 확보.
8 Conclusion — DCC vs BC 종합
DCC 와 BC 는 동일한 목적 (confounding 제거) 의 다른 도구.
| 상황 | 권장 |
|---|---|
| CD 가 잘 검증됨, 변수 모두 관측 | BC (효율적) |
| CD 가 부분 부정확, 일부 변수 미관측 | DCC (안전) |
| Collider 의 자연 차단 활용 가능 | BC (BC 만 가능) |
| 분석가가 CD 에 자신 없음 | DCC (robust) |
| 두 결과 비교하고 싶음 | 둘 다 적용 (대조) |
→ 두 규칙을 alternative tool 로 사용. 한 규칙만 고집 안 함.
추천 default:
- CD 짓기 + 검증 (E-BUI4)
- DCC + BC 둘 다 적용 — 두 결과 비교
- 일치하면 결과 신뢰
- 불일치하면 CD 재검토 (특히 collider 식별)
이 default 가 분석의 안전성과 정밀성을 동시에 확보.
9 관련 주제
9.1 Ch.5 의 형제 글 (Ch.5 완결)
- E-BUI5-0 Deconfounding overview — DCC vs BC 도입
- E-BUI5-1 DCC 분리적 원인 기준 — DCC 자세히
9.2 이전 챕터
- E-BUI3-3 충돌 변수와 경로 — Collider · Path 도입
- E-BUI4-3 데이터 검증과 반복 정제 — Ch.4: CD 짓기
9.3 후속 챕터
- E-BUI6-0 결측 데이터 처리 overview — Ch.6: 결측 데이터
- E-BUI8-0 Theory of Change 실험 설계 overview — Ch.8: 실험으로 confounding 제거
9.4 Hernan 정통 cross-link
- Causal_Inference/06 DAG와 인과 다이어그램 — DAG·d-separation·SWIG
- Causal_Inference/07 교란 — Backdoor criterion 의 학술적 처리
- Causal_Inference/08 선택 편향 — Collider bias 의 학술적 처리
9.5 카테고리 진입점
- Experimentation 학습 로드맵 — 11 Phase × 7 교재 매핑