베이지안 네트워크의 조건부 독립성과 정확 추론

베이지안 네트워크의 DAG 분해, 조건부 독립성과 d-분리, Variable Elimination·Junction Tree 정확 추론 방식을 정리한다.

2026-08-14 · 최초 발행 2024-04-29

DAG와 CPT로 합동분포를 다루는 방식

베이지안 네트워크는 변수 집합의 확률적 의존성을 방향성 비순환 그래프(DAG)로 나타내고, 각 노드에는 조건부확률표(CPT)를 둔다. 그래프는 어떤 변수가 다른 변수에 의존하는지를 표현하며, CPT는 그 의존 관계의 파라미터를 맡는다.

합동분포는 다음과 같이 각 변수와 부모 노드의 조건부 확률로 분해된다.

P(X1,…,Xn)=∏i P(Xi | Pa(Xi))

이 분해는 체인룰을 그대로 계산하는 대신 그래프 구조가 암시하는 조건부 독립성을 이용할 수 있게 한다. 증거 E가 주어졌을 때 질의 변수 Q의 사후확률 P(Q|E)를 구하는 일이 대표적인 추론 문제다. 추론 방식은 Variable Elimination과 Junction Tree 같은 정확 추론, Sampling과 Variational 방식의 근사 추론으로 나뉜다.

구조는 도메인 지식으로 직접 설계할 수도 있고, 점수기반 또는 제약기반 알고리즘으로 데이터에서 학습할 수도 있다. 어느 방식이든 DAG에는 사이클이 없어야 한다. 완전 데이터에서는 MLE나 베이지안 추정을 사용하고, 결측값이나 잠재 변수가 있으면 EM 알고리즘을 활용한다. Dirichlet 사전분포는 파라미터 스무딩에 사용된다.

독립성을 그래프 경로로 판정하는 법

조건부 독립성은 다음 관계로 표현한다.

X ⟂ Y | Z ⇔ P(X,Y|Z)=P(X|Z)P(Y|Z)

그래프 관점에서는 X와 Y 사이의 모든 경로가 Z에 의해 차단되는지를 본다. 이 판정을 형식화한 규칙이 d-분리다.

경로의 형태에 따라 조건을 다르게 해석해야 한다.

  • 연쇄(chain) A→B→C에서는 B를 조건으로 두면 A ⟂ C | B가 성립한다.
  • 분기(fork) A←B→C도 B를 조건으로 두면 A ⟂ C | B가 성립한다.
  • 충돌(collider) A→C←B에서는 조건 없이 A ⟂ B다. 다만 C 또는 C의 자손을 조건으로 두면 의존성이 생긴다. 이는 explaining away로 알려진 현상이다.

d-분리는 DAG G, 변수 집합 X와 Y, 조건집합 Z를 입력으로 받는다. X의 모든 노드에서 Y의 노드까지 이어지는 경로를 확인하고, 각 경로가 차단됐는지를 평가한다. 비-충돌 노드에서는 해당 노드가 Z에 포함될 때 경로가 막힌다. 충돌 노드에서는 그 노드나 자손이 Z에 포함되지 않을 때 경로가 막힌다. 모든 경로가 차단되면 X와 Y는 Z에 대해 d-분리되어 있으며, X ⟂ Y | Z로 판단한다.

질의 패턴에 따라 달라지는 정확 추론

Variable Elimination은 숨은 변수 H=V{Q∪E}를 제거하면서 합-곱 연산을 필요한 팩터 주변에 국소화한다. 먼저 d-분리로 관련 없는 노드와 팩터를 제외하고, min-fill 또는 min-degree 같은 휴리스틱으로 제거 순서를 정한다. 증거를 반영해 CPT를 축소한 뒤, 각 제거 변수 Zi와 관련된 팩터를 곱하고 Zi에 대해 합소거(Σ)한다. 마지막으로 남은 팩터를 곱해 정규화하면 P(Q|E)를 얻는다.

시간과 메모리 복잡도는 O(n·exp(w))이며, w는 선택 순서의 유도폭(≈트리폭)이다. 단일 또는 소수 질의에서는 구현이 비교적 단순하고 상태를 유지하지 않는다는 점이 장점이다. 반면 제거 순서가 좋지 않으면 중간 팩터가 커질 수 있다.

Junction Tree는 그래프를 클리크 트리로 바꾼 뒤 메시지 패싱으로 전역 칼리브레이션을 수행한다. 같은 자식의 부모를 연결하고 방향을 제거하는 도덕화(moralization)부터 시작한다. 이어 코드 없는 4-사이클을 제거하는 삼각화(triangulation)를 수행하며, 이 단계에도 min-fill 휴리스틱을 적용할 수 있다. 최대 클리크를 추출하고 러닝 인터섹션 조건을 만족하는 junction tree를 구성한 뒤, 클리크 포텐셜에 증거를 반영한다. 수집과 분배 단계의 메시지 패싱이 끝나면 임의 변수나 클리크의 주변분포를 질의할 수 있다.

Junction Tree의 비용은 최대 클리크 크기에 지배된다. 초기 구성 비용과 메모리 부담은 크지만, 다중 질의나 반복되는 증거 스트림에서는 칼리브레이션 결과를 재사용할 수 있고 전역 일관성을 유지한다.

VEJT입력: BN 구조+CPT, 질의 Q,증거 E전처리: d-분리로 무관노드/팩터 제거알고리즘 선택순서선택(min-fill/min-degree)증거로 팩터 축소관련 팩터제거 변수에 대해 합소거남은 팩터 곱/정규화출력: P(Q|E)도덕화→삼각화클리크/세퍼레이터 구성포텐셜 초기화/증거 반영메시지 패싱(수집→분배)칼리브레이션출력: 주변분포/다중 질의
항목 Variable Elimination Junction Tree
성능(단일/다중 질의) 단일 질의 유리, 오버헤드 작음 초기 구축 비용 큼, 다중 질의/반복 증거에 유리
확장성(트리폭 의존) 유도폭에 지배, 순서 최적화 중요 최대 클리크 크기에 지배, 삼각화 품질 중요
일관성(글로벌 칼리브레이션) 질의별 독립 계산, 상태 미유지 전역 칼리브레이션으로 일관성 유지
안정성(수치/희소성) 로그-스페이스·스케일링 필요 메시지 정규화로 안정성 상대적 우수
운영 편의(구현·튜닝) 구현 용이, 메모리 사용 예측 용이 구현 복잡, 메모리 피크 관리 필요

증거가 계속 들어오는 운영 환경

의료 진단과 의사결정 지원에서는 증상, 검사, 질병 사이의 관계를 모델링하고 증거가 갱신될 때 사후확률을 제공할 수 있다. 그래프 구조가 남아 있으므로 판단 근거를 설명하는 데도 활용된다.

금융 리스크와 사기 탐지에서는 거래 패턴, 고객 속성, 장치 정보를 함께 다룰 수 있다. d-분리를 활용한 전처리는 추론 대상에서 무관한 변수를 제외해 지연을 줄이는 데 쓰인다.

설비 이상탐지와 근본원인 분석(RCA)에서는 센서 계측 간 인과 연결을 표현하고, Junction Tree로 다중 질의와 연속 증거 스트림을 처리할 수 있다. AIOps에서는 경보의 상관관계와 전파를 모델링하며, explaining away를 통해 노이즈 경보를 걸러내거나 변경 영향 분석에 적용한다.

d-분리 기반 가지치기는 유효 변수 수를 줄여 실행시간과 메모리 사용을 지수적으로 감소시킬 수 있으며, 이때 트리폭 w의 감소가 지배적이다. Variable Elimination은 단일 질의에서 대안 대비 수~수십 배 속도 개선이 가능하지만, 모델 희소성과 순서 품질에 의존한다. Junction Tree는 다중 질의와 스트리밍 증거 환경에서 총 처리량 향상에 적합하다.

구조와 파라미터가 분리되어 있으므로 유지보수 과정에서 모듈형 업데이트가 가능하고, 지식과 데이터를 함께 반영할 수 있다. 투명한 의존성 구조는 설명가능성을 제공하며, “만약 A가 달랐다면?” 같은 반사실적 질문도 지원한다.

모델 크기와 수치 안정성을 함께 관리하기

구조 학습이나 설계 단계에서는 금지 엣지와 강제 엣지 같은 도메인 제약을 두어 탐색 공간을 줄일 수 있다. 사이클 검증은 반드시 필요하다. 희귀 이벤트에는 Dirichlet prior를 이용한 베이지안 스무딩을 적용해 0-확률로 인한 차단을 막는다.

Variable Elimination에서는 min-fill과 min-degree 순서를 탐색하고, 증거를 흡수한 뒤 로컬 제거 순서를 다시 정할 수 있다. 팩터 캐싱도 반복 계산을 줄이는 방법이다. Junction Tree에서는 삼각화 품질이 성능을 결정하므로 클리크 크기를 모니터링해야 한다. 메시지 정규화와 로그-스페이스는 언더플로를 줄이는 데 사용한다.

대규모 모델은 부분모델 분해(하이어라키)와 늦은 결합 전략을 고려할 수 있다. 검증 단계에서는 합동분포의 정상화와 로컬 독립성(d-분리)을 단위 테스트하고, 변동성이 큰 노드에는 민감도 분석을 적용한다.

pgmpy로 확인하는 작은 네트워크

전제조건: Python 3.10+, pgmpy 0.1.24+, NumPy 설치

# pip install pgmpy==0.1.24
from pgmpy.models import BayesianNetwork
from pgmpy.factors.discrete import TabularCPD
from pgmpy.inference import VariableElimination, BeliefPropagation

# 1) 모델 정의: A->C<-B, B->D
model = BayesianNetwork([('A','C'), ('B','C'), ('B','D')])

cpd_A = TabularCPD('A', 2, [[0.7], [0.3]])              # P(A=0)=0.7, P(A=1)=0.3
cpd_B = TabularCPD('B', 2, [[0.6], [0.4]])              # P(B=1)=0.4
# P(C|A,B): 순서 A,B
cpd_C = TabularCPD('C', 2,
                   [[0.95, 0.8, 0.7, 0.1],             # P(C=0|A,B)
                    [0.05, 0.2, 0.3, 0.9]],            # P(C=1|A,B)
                   evidence=['A','B'], evidence_card=[2,2])
# P(D|B)
cpd_D = TabularCPD('D', 2,
                   [[0.9, 0.3],                         # P(D=0|B=0), P(D=0|B=1)
                    [0.1, 0.7]],                        # P(D=1|B=0), P(D=1|B=1)
                   evidence=['B'], evidence_card=[2])

model.add_cpds(cpd_A, cpd_B, cpd_C, cpd_D)
model.check_model()  # 유효성 검사

# 2) Variable Elimination: P(A | D=1)
ve = VariableElimination(model)
res_ve = ve.query(variables=['A'], evidence={'D': 1})
print("VE P(A|D=1):", res_ve['A'].values)

# 3) Junction Tree (Belief Propagation): 동일 질의
bp = BeliefPropagation(model)
bp.calibrate()
res_bp = bp.query(variables=['A'], evidence={'D': 1})
print("JT P(A|D=1):", res_bp['A'].values)

사이클이 있으면 예외가 발생하며, CPD 차원이나 정규화가 맞지 않으면 check_model이 실패한다. 대규모 모델에서는 언더플로 방지를 위해 로그-스페이스와 스케일링을 사용한다. 다중 질의와 증거 변화가 빈번한 경우에는 BeliefPropagation을 칼리브레이션 유지 상태로 운용할 수 있다.

베이지안 네트워크에서 추론 효율은 그래프가 드러내는 조건부 독립성, d-분리 기반 가지치기, 그리고 트리폭에 좌우되는 정확 추론 방식의 조합으로 결정된다. 즉시 처리할 단일 질의에는 Variable Elimination이, 여러 질의와 지속적인 증거 입력에는 Junction Tree가 맞는다.

베이지안 네트워크조건부 독립성d-분리확률 그래프 모델추론 알고리즘