독립성 (Independence)

독립의 엄밀한 정의, 상호독립·조건부독립, 그리고 의료 스크리닝 예시

조건부 확률과 베이즈 정리의 심화편. 독립의 수학적 정의와 서로소와의 결정적 차이, 쌍별 독립 vs 상호 독립(Bernstein 반례), 조건부 독립의 미묘함 — 실무 코드와 함께 엄밀히 다룬다.

Statistics
저자

Kwangmin Kim

공개

2026년 03월 27일

선행 지식

이 포스트는 조건부 확률과 베이즈 정리 의 심화편이다. 조건부 확률, 곱셈 법칙, 전확률 정리, 베이즈 정리를 먼저 학습한 뒤 읽는 것을 권장한다.


왜 독립성이 통계학과 ML의 핵심인가

독립성은 단순한 이론적 개념이 아니라, 현대 통계와 ML의 거의 모든 방법론을 지탱하는 가정이다:

  • iid 가정: 대부분의 통계 추론(MLE, 가설 검정, 신뢰구간)은 표본이 “독립이고 동일한 분포(iid)”를 따른다고 가정한다. 독립이 깨지면 표준 오차, p-value, 신뢰구간이 모두 틀린다
  • 나이브 베이즈: 특성(feature)들이 클래스가 주어졌을 때 조건부 독립이라는 가정 위에 성립한다. 이 가정이 없으면 결합 확률의 추정이 차원의 저주에 빠진다
  • 인과 추론: “교란 변수(confounder)를 통제하면 처리와 결과가 조건부 독립”이라는 가정이 인과 효과 추정의 핵심이다
  • 시계열: 잔차(residual)의 독립성을 검정하여 모델의 적합도를 판단한다. 잔차에 자기상관이 남아 있으면 모델이 불완전하다

독립성을 이해하지 못하면 “왜 이 방법이 작동하는가”를 설명할 수 없고, 독립성이 위반될 때 “왜 결과가 틀린가”를 진단할 수 없다.

1 독립성 (Independence)

1.1 두 사건의 독립

정의: 독립 (Statistical Independence)

두 사건 \(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 서로소: 결정적 차이

독립(independent) ≠ 서로소(mutually exclusive/disjoint)
서로소 (\(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 쌍별 독립 ≠ 상호 독립

반례: 쌍별 독립이지만 상호 독립이 아닌 경우 (Bernstein, 1946)

\(\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 관련 주제

선행 지식

후속 주제

관련 개념

  • Binomial Distribution — 독립 베르누이 시행의 합
  • MLE — 독립 표본 가정: \(L(\theta) = \prod_i f(x_i \mid \theta)\)
  • Mixed Models — 비독립 데이터(반복 측정)의 모델링

Subscribe

Enjoy this blog? Get notified of new posts by email: