이 포스트는 조건부 확률과 베이즈 정리 의 심화편이다. 조건부 확률, 곱셈 법칙, 전확률 정리, 베이즈 정리를 먼저 학습한 뒤 읽는 것을 권장한다.
독립성은 단순한 이론적 개념이 아니라, 현대 통계와 ML의 거의 모든 방법론을 지탱하는 가정이다:
- iid 가정: 대부분의 통계 추론(MLE, 가설 검정, 신뢰구간)은 표본이 “독립이고 동일한 분포(iid)”를 따른다고 가정한다. 독립이 깨지면 표준 오차, p-value, 신뢰구간이 모두 틀린다
- 나이브 베이즈: 특성(feature)들이 클래스가 주어졌을 때 조건부 독립이라는 가정 위에 성립한다. 이 가정이 없으면 결합 확률의 추정이 차원의 저주에 빠진다
- 인과 추론: “교란 변수(confounder)를 통제하면 처리와 결과가 조건부 독립”이라는 가정이 인과 효과 추정의 핵심이다
- 시계열: 잔차(residual)의 독립성을 검정하여 모델의 적합도를 판단한다. 잔차에 자기상관이 남아 있으면 모델이 불완전하다
독립성을 이해하지 못하면 “왜 이 방법이 작동하는가”를 설명할 수 없고, 독립성이 위반될 때 “왜 결과가 틀린가”를 진단할 수 없다.
1 독립성 (Independence)
1.1 두 사건의 독립
두 사건 \(A\) 와 \(B\) 가 독립(independent) 이면:
\[ P(A \cap B) = P(A)\,P(B) \]
동치 조건들 (\(P(A)>0\), \(P(B)>0\) 가정):
\[ P(A \mid B) = P(A) \iff P(B \mid A) = P(B) \iff P(A \cap B) = P(A)P(B) \]
독립의 의미: \(B\) 에 관한 정보가 \(A\) 의 확률을 전혀 바꾸지 않는다. \(A\) 와 \(B\) 는 서로 아무 정보도 제공하지 않는다.
1.2 독립 vs 서로소: 결정적 차이
| 서로소 (\(A \cap B = \emptyset\)) | 독립 (\(P(A\cap B)=P(A)P(B)\)) | |
|---|---|---|
| 정의 | 동시에 발생 불가 | 서로 정보 무관 |
| \(P(A\cap B)\) | \(0\) | \(P(A)P(B)\) |
| \(P(B)>0\) 이면 | \(P(A\mid B)=0\) | \(P(A\mid B)=P(A)\) |
| \(P(A),P(B)>0\) 이면 | 독립이 아님 | \(A\cap B\neq\emptyset\) 가능 |
서로소이고 \(P(A),P(B)>0\) 이면 반드시 종속(dependent): \[ P(A \cap B) = 0 \neq P(A)\,P(B) > 0 \]
서로소: “A와 B는 절대 함께 일어나지 않는다” → B가 일어나면 A가 불가능해짐 → 강한 종속
독립: “A와 B는 서로에 대해 아무것도 모른다” → B가 일어나도 A의 확률 그대로
예시 (주사위, \(\Omega=\{1,\ldots,6\}\)):
| 사건 쌍 | 관계 | 확인 |
|---|---|---|
| \(A=\{1,2,3\}\), \(B=\{4,5,6\}\) | 서로소, 종속 | \(P(A\cap B)=0\neq 1/4\) |
| \(A=\{1,2\}\), \(B=\{2,3,4,5\}\) | 종속 | \(P(A)P(B)=1/3\cdot2/3=2/9\neq P(\{2\})=1/6\) |
| \(A=\{1,2,3\}\), \(B=\{1,3,5\}\) | 독립 | \(P(A)P(B)=1/2\cdot1/2=1/4=P(\{1,3\})\) ✓ |
1.3 독립성 보존 법칙
\(A\) 와 \(B\) 가 독립이면: \[ A \text{ 와 } B^c \text{ 도 독립}, \quad A^c \text{ 와 } B \text{ 도 독립}, \quad A^c \text{ 와 } B^c \text{ 도 독립} \]
증명 (\(A\) 와 \(B^c\) 독립):
\[ P(A \cap B^c) = P(A) - P(A \cap B) = P(A) - P(A)P(B) = P(A)(1-P(B)) = P(A)P(B^c) \quad\blacksquare \]
2 상호 독립 (Mutual Independence)
2.1 정의
\(n\) 개의 사건 \(A_1, A_2, \ldots, A_n\) 이 상호 독립(mutually independent) 이면, 모든 부분집합 \(\{i_1, \ldots, i_k\} \subseteq \{1,\ldots,n\}\) (\(k \geq 2\))에 대해:
\[ P\!\left(\bigcap_{j=1}^k A_{i_j}\right) = \prod_{j=1}^k P(A_{i_j}) \]
이는 \(2^n - n - 1\) 개의 조건을 요구한다.
2.2 쌍별 독립 ≠ 상호 독립
\(\Omega = \{1,2,3,4\}\) (균등 분포, \(P(\{\omega\})=1/4\))
\[ A_1 = \{1,2\},\quad A_2 = \{1,3\},\quad A_3 = \{1,4\} \]
쌍별 독립 확인: \[ P(A_1)=P(A_2)=P(A_3)=\tfrac{1}{2} \] \[ P(A_1\cap A_2)=P(\{1\})=\tfrac{1}{4}=P(A_1)P(A_2) \checkmark \] \[ P(A_1\cap A_3)=\tfrac{1}{4}=P(A_1)P(A_3) \checkmark,\quad P(A_2\cap A_3)=\tfrac{1}{4}=P(A_2)P(A_3) \checkmark \]
상호 독립 실패: \[ P(A_1\cap A_2\cap A_3)=P(\{1\})=\tfrac{1}{4} \neq \tfrac{1}{8}=P(A_1)P(A_2)P(A_3) \]
머신러닝의 나이브 베이즈(Naive Bayes) 분류기는 특성들이 클래스 조건부로 상호 독립임을 가정한다. 이 가정이 “naive”인 이유는, 쌍별 독립도 상호 독립을 보장하지 않기 때문이다.
3 조건부 독립 (Conditional Independence)
3.1 정의
\(P(C)>0\) 일 때, \(A\) 와 \(B\) 가 \(C\) 에 대해 조건부 독립(conditionally independent) 이면:
\[ P(A \cap B \mid C) = P(A \mid C)\,P(B \mid C) \]
동치: \(P(A \mid B \cap C) = P(A \mid C)\) (\(P(B\cap C)>0\) 가정)
3.2 독립 ≠ 조건부 독립
두 방향 모두 반례가 존재한다.
3.2.1 방향 1: 비조건부 독립 → 조건부 독립 아님 (설명 인자 역설)
예시: 성별(\(C\))이 주어졌을 때 키와 체중의 관계
- 전체 집단에서 키(\(A\))와 체중(\(B\)): 강한 양의 상관 (종속)
- 성별을 통제하면: 여전히 종속일 수 있음
더 명확한 예: 동전 2개 동시 던지기
\(A\)=“1번 동전 앞면”, \(B\)=“2번 동전 앞면”, \(C\)=“같은 면이 나옴”
\(A\) 와 \(B\) 는 비조건부 독립: \(P(A\cap B)=1/4=P(A)P(B)\) ✓
\(C\) 가 주어지면: \[ P(A\mid C) = P(A\mid\{HH,TT\}) = P(\{HH\}\mid\{HH,TT\}) = \frac{1}{2} \] \[ P(A\cap B\mid C) = P(\{HH\}\mid\{HH,TT\}) = \frac{1}{2} \neq \frac{1}{4} = P(A\mid C)P(B\mid C) \]
\(C\) 조건 하에서 \(A\) 와 \(B\) 는 종속이 된다.
3.2.2 방향 2: 조건부 독립 → 비조건부 독립 아님 (심슨의 역설 배경)
예시: 두 회사의 불량률 데이터
| 공장 A 사용 | 공장 B 사용 | |
|---|---|---|
| 제품 X | 불량 1/10 | 불량 2/10 |
| 제품 Y | 불량 3/10 | 불량 4/10 |
각 제품 내에서 공장 선택(\(G\))과 불량 발생(\(D\))이 조건부 독립이더라도, 제품 비율이 다르면 전체 불량률에서 종속성이 생긴다.
| 상황 | 결론 |
|---|---|
| 비조건부 독립 | 조건부 독립을 보장하지 않음 |
| 조건부 독립 | 비조건부 독립을 보장하지 않음 |
| 조건부 독립 확인 | 통제(control)하는 변수를 명시해야 의미 있음 |
4 독립과 조건부 확률의 관계: 스크리닝 예시
의료 검사 예시: 희귀 질환의 스크리닝
- \(D\): 질환 존재, \(P(D) = 0.001\) (유병률)
- \(T^+\): 양성 판정
- 민감도(sensitivity): \(P(T^+ \mid D) = 0.99\)
- 특이도(specificity): \(P(T^- \mid D^c) = 0.99\), 즉 \(P(T^+ \mid D^c) = 0.01\)
전확률 정리로 \(P(T^+)\) 계산:
\[ P(T^+) = P(T^+\mid D)P(D) + P(T^+\mid D^c)P(D^c) = 0.99\times0.001 + 0.01\times0.999 = 0.01098 \]
베이즈 정리로 양성예측도(PPV) 계산:
\[ P(D \mid T^+) = \frac{0.99 \times 0.001}{0.01098} \approx 0.0902 \approx 9\% \]
“검사 정확도 99%”를 보고 양성이면 99% 확률로 질환이 있다고 생각하기 쉽다. 하지만 실제 PPV는 9% 다. 이유: 유병률 0.1%라는 기저율(base rate) 이 검사 정확도보다 훨씬 중요하다.
\[ P(D \mid T^+) \ne P(T^+ \mid D) \quad\text{— 조건의 순서가 결정적이다} \]
| 유병률 | PPV (민감도·특이도 99%) |
|---|---|
| 0.1% | 9.0% |
| 1% | 50.0% |
| 10% | 91.7% |
| 50% | 99.0% |
5 응용 분야
| 분야 | 조건부 확률·독립성의 역할 | 구체적 예시 |
|---|---|---|
| 베이지안 추론 | 사전→사후 갱신 | \(P(\theta \mid \text{data}) \propto P(\text{data}\mid\theta)P(\theta)\) |
| 나이브 베이즈 | 조건부 독립 가정 | 스팸 필터: \(P(S\mid w_1,\ldots,w_n)\propto P(S)\prod P(w_i\mid S)\) |
| 마르코프 연쇄 | 조건부 독립 (마르코프 성질) | \(P(X_{n+1}\mid X_n,\ldots,X_0)=P(X_{n+1}\mid X_n)\) |
| 인과 추론 | 조건부 독립으로 교란변수 통제 | d-분리(d-separation), 백도어 기준 |
| 임상시험 | 처치와 결과의 독립성 (무작위 배정) | 랜덤화 → 처치 \(\perp\) 잠재적 교란 |
| 암호학 | 암호문이 평문과 독립 | 완벽 비밀성: \(P(M\mid C)=P(M)\) |
6 코드 예시
6.1 Step 1: 순수 Python — 조건부 확률·독립성 직접 계산
from fractions import Fraction
from itertools import product as iproduct
# ── 표본공간 정의 ───────────────────────────────────────────────
Omega = list(range(1, 7)) # 주사위
P_elem = Fraction(1, 6) # 균등 분포
def P(event):
"""사건(집합)의 확률"""
return Fraction(len(event), len(Omega))
def P_cond(A, B):
"""P(A | B): 조건부 확률"""
AB = A & B
if len(B) == 0:
raise ValueError("P(B) = 0")
return Fraction(len(AB), len(B))
# 사건 정의
A = {2, 4, 6} # 짝수
B = {4, 5, 6} # 4 이상
C = {1, 2, 3} # 3 이하
# 조건부 확률
print("조건부 확률:")
print(f" P(A|B) = {P_cond(A,B)} = {float(P_cond(A,B)):.4f}") # P(짝수 | 4이상)
print(f" P(B|A) = {P_cond(B,A)} = {float(P_cond(B,A)):.4f}") # P(4이상 | 짝수)
print(f" P(A|C) = {P_cond(A,C)} = {float(P_cond(A,C)):.4f}") # P(짝수 | 3이하)
# 독립성 검정
def is_independent(A, B, Omega):
pA = Fraction(len(A), len(Omega))
pB = Fraction(len(B), len(Omega))
pAB = Fraction(len(A & B), len(Omega))
return pAB == pA * pB
print("\n독립성 검정:")
print(f" A{{짝수}}와 B{{4이상}} 독립: {is_independent(A, B, Omega)}") # False
print(f" A{{짝수}}와 C{{3이하}} 독립: {is_independent(A, C, Omega)}") # True (1/4 = 1/2 × 1/2)
# 독립성 확인
pA, pC, pAC = P(A), P(C), P(A & C)
print(f" P(A)×P(C) = {pA}×{pC} = {pA*pC}, P(A∩C) = {pAC}")
# ── 쌍별 독립 vs 상호 독립 검증 (Bernstein 반례) ──────────────────
Omega4 = {1,2,3,4}
A1, A2, A3 = {1,2}, {1,3}, {1,4}
P4 = lambda E: Fraction(len(E), 4)
print("\nBernstein 반례 (|Ω|=4, 균등):")
print(f" 쌍별 독립:")
print(f" P(A1∩A2)={P4(A1&A2)} == P(A1)P(A2)={P4(A1)*P4(A2)}? {P4(A1&A2)==P4(A1)*P4(A2)}")
print(f" P(A1∩A3)={P4(A1&A3)} == P(A1)P(A3)={P4(A1)*P4(A3)}? {P4(A1&A3)==P4(A1)*P4(A3)}")
print(f" P(A2∩A3)={P4(A2&A3)} == P(A2)P(A3)={P4(A2)*P4(A3)}? {P4(A2&A3)==P4(A2)*P4(A3)}")
print(f" 상호 독립:")
prod3 = P4(A1)*P4(A2)*P4(A3)
print(f" P(A1∩A2∩A3)={P4(A1&A2&A3)} == P(A1)P(A2)P(A3)={prod3}? {P4(A1&A2&A3)==prod3}")6.2 Step 2: scipy·numpy — 의료 스크리닝 + 독립성 검정
import numpy as np
from scipy.stats import chi2_contingency
# ── 베이즈 정리: 양성예측도(PPV) ───────────────────────────────────
def ppv(prevalence, sensitivity, specificity):
"""
P(D|T+) = P(T+|D)P(D) / P(T+)
"""
p_D = prevalence
p_Dc = 1 - prevalence
p_tp_given_D = sensitivity
p_tp_given_Dc = 1 - specificity
p_tp = p_tp_given_D * p_D + p_tp_given_Dc * p_Dc # 전확률 정리
ppv_val = (p_tp_given_D * p_D) / p_tp # 베이즈 정리
return ppv_val, p_tp
print("유병률에 따른 양성예측도 (민감도=특이도=99%):")
print(f"{'유병률':>10} {'P(T+)':>10} {'PPV':>10}")
print("-" * 32)
for prev in [0.001, 0.005, 0.01, 0.05, 0.1, 0.5]:
ppv_val, p_tp = ppv(prev, sensitivity=0.99, specificity=0.99)
print(f"{prev:>10.3f} {p_tp:>10.4f} {ppv_val:>10.4f}")
# ── 카이제곱 독립성 검정 ─────────────────────────────────────────
# 실제 데이터에서 두 범주형 변수의 독립성 검정
np.random.seed(42)
# 독립인 경우 (광고 유형 vs 성별 — 연관 없음)
n = 1000
gender = np.random.choice(['M','F'], size=n, p=[0.5, 0.5])
ad_type = np.random.choice(['A','B'], size=n, p=[0.5, 0.5]) # 성별과 무관하게 배정
from collections import Counter
cross = Counter(zip(gender, ad_type))
table_indep = np.array([
[cross[('M','A')], cross[('M','B')]],
[cross[('F','A')], cross[('F','B')]]
])
chi2, p, dof, _ = chi2_contingency(table_indep)
print(f"\n[독립 케이스] χ²={chi2:.3f}, p={p:.4f} → {'독립 기각 실패' if p>0.05 else '독립 기각'}")
# 종속인 경우 (광고 클릭 vs 구매 — 연관 있음)
table_dep = np.array([
[480, 120], # 클릭: 구매 480, 미구매 120
[100, 300], # 미클릭: 구매 100, 미구매 300
])
chi2, p, dof, expected = chi2_contingency(table_dep)
print(f"[종속 케이스] χ²={chi2:.3f}, p={p:.4f} → {'독립 기각 실패' if p>0.05 else '독립 기각 (연관성 있음)'}")
# ── 조건부 독립: 나이브 베이즈 스팸 필터 ─────────────────────────
from collections import defaultdict
# 훈련 데이터
emails = [
("스팸", ["무료", "당첨", "클릭", "무료"]),
("스팸", ["무료", "이벤트", "클릭"]),
("정상", ["회의", "일정", "확인"]),
("정상", ["보고서", "제출", "확인", "일정"]),
("정상", ["회의", "보고서", "검토"]),
]
# P(클래스) 계산
class_count = Counter(label for label, _ in emails)
n_emails = len(emails)
p_class = {c: v/n_emails for c, v in class_count.items()}
# P(단어 | 클래스) 계산 (라플라스 스무딩)
word_given_class = defaultdict(Counter)
for label, words in emails:
for w in words:
word_given_class[label][w] += 1
total_words = {c: sum(word_given_class[c].values()) for c in class_count}
vocab_size = len({w for _, ws in emails for w in ws})
def p_word_given_class(word, label, alpha=1):
"""P(word | label) — 라플라스 스무딩"""
return (word_given_class[label][word] + alpha) / (total_words[label] + alpha * vocab_size)
# 새 메일 분류: "무료 클릭 이벤트"
test_words = ["무료", "클릭", "이벤트"]
print("\n나이브 베이즈 스팸 분류 (조건부 독립 가정):")
scores = {}
for label in ["스팸", "정상"]:
score = np.log(p_class[label])
for w in test_words:
score += np.log(p_word_given_class(w, label))
scores[label] = score
print(f" log P({label}|메일) ∝ {score:.4f}")
pred = max(scores, key=scores.get)
print(f" → 예측: {pred}")7 관련 주제
선행 지식
- 조건부 확률과 베이즈 정리 — 조건부 확률 정의, 곱셈 법칙, 전확률 정리 (기초편)
- 확률론의 공리적 기초 — 콜모고로프 공리, 기본 성질
- 결과 열거법 — 트리 다이어그램으로 조건부 확률 시각화
후속 주제
- Bayes’ Rule — 베이즈 정리 심화
- Random Variable — 확률변수와 분포의 독립성
- Convergence in Probability — 독립 확률변수의 수렴 이론
관련 개념
- Binomial Distribution — 독립 베르누이 시행의 합
- MLE — 독립 표본 가정: \(L(\theta) = \prod_i f(x_i \mid \theta)\)
- Mixed Models — 비독립 데이터(반복 측정)의 모델링