RyanNerd
라덕'Story
RyanNerd
  • 분류 전체보기 (70) N
    • Study Note (35) N
      • Python (3)
      • R (1)
      • Airflow (7)
      • 통계 (22) N
      • 머신러닝 (2) N
    • 빅데이터분석기사 (1)
      • 필기 (1)
    • Programmers (28)
      • Python (13)
      • SQL (15)
    • Project (3)
      • Django (3)
    • Mac (2)

블로그 메뉴

  • NaverBlog
  • 홈

최근 글

전체 방문자
오늘
어제
hELLO · Designed By 정상우.
RyanNerd

라덕'Story

Study Note/통계

눈에 보이지 않는 원인을 찾아라: 은닉 마르코프 모델 (HMM)

2025. 12. 19. 15:44

일반적인 마르코프 연쇄가 "눈에 보이는 상태의 변화"를 다룬다면, HMM은 "겉으로 드러난 결과(Observation)를 통해 숨겨진 원인(Hidden State)을 추론"하는 더욱 고차원적인 모델입니다.

 

우리는 살면서 겉으로 드러난 현상만 보고 그 이면의 진실을 파악해야 할 때가 많습니다.

환자의 '증상(기침, 열)'을 보고 '병명(감기, 폐렴)'을 진단하거나, 친구의 '목소리 톤'을 듣고 '기분'을 맞히는 것처럼요.

이처럼 관찰 가능한 결과($O$)를 통해 숨겨진 상태($S$)를 확률적으로 추론하는 알고리즘, 은닉 마르코프 모델(HMM)에 대해 알아보겠습니다.

 

1. 마르코프 연쇄 vs 은닉 마르코프 모델

① 마르코프 연쇄 (Markov Chain)

  • 모든 상태가 눈에 보입니다.
  • 예시: 오늘의 주가(상승) $\rightarrow$ 내일의 주가(하락) 예측.

② 은닉 마르코프 모델 (HMM)

  • 진짜 상태(State)는 은닉(Hidden)되어 보이지 않습니다.
  • 우리는 그 상태가 뱉어내는 출력값(Observation)만 볼 수 있습니다.
  • 구조:
    • 은닉 상태($S$): 날씨 (맑음, 비) - 직접 안 보임
    • 관측값($O$): 행동 (게임, 운동) - 눈에 보임
    • 전이 확률($A$): 어제 맑았으면 오늘 맑을 확률 ($S_{t-1} \rightarrow S_t$).
    • 방출(출력) 확률($B$): 맑을 때 게임을 할 확률 ($S_t \rightarrow O_t$).

2. 예제 시나리오: 영희의 추리 (날씨 vs 활동)

강의 자료(Slide 88)에 나온 상황을 풀어봅시다.

  • 상황: 영희는 철수와 멀리 떨어져 삽니다. 철수가 오늘 무엇을 했는지(게임/운동)만 들을 수 있고, 그 동네 날씨는 모릅니다.
  • 목표: 철수의 행동 패턴을 보고, 지난 3일간의 날씨 변화를 맞혀라! (디코딩 문제)

확률 설정 (모델 파라미터)

  1. 은닉 상태 (날씨): Sunny (맑음), Rainy (비)
  2. 관측값 (행동): Game (게임), Fitness (운동)
  3. 전이 확률 (날씨 변화):
    • 맑음 $\rightarrow$ 맑음: 0.8 / 맑음 $\rightarrow$ 비: 0.2
    • 비 $\rightarrow$ 맑음: 0.4 / 비 $\rightarrow$ 비: 0.6
  4. 방출 확률 (날씨별 행동):
    • 맑음일 때: 게임 0.1, 운동 0.9 (맑으면 주로 운동함)
    • 비올 때: 게임 0.8, 운동 0.2 (비 오면 주로 게임함)

3. 디코딩(Decoding)과 비터비(Viterbi) 알고리즘

관측된 행동이 [게임, 운동, 운동] 순서라고 합시다. 이때 날씨는 어땠을까요? 모든 경우의 수를 다 계산하면 너무 복잡합니다. 이때 우도(Likelihood)를 최대화하는 최적의 경로를 찾는 알고리즘이 바로 비터비(Viterbi) 알고리즘입니다.

 

4. [실습] Python & R 코드 구현

철수가 3일 동안 [Game, Fitness, Fitness]를 했다고 가정하고, 날씨를 추론해 보겠습니다.

Python Code (Custom Viterbi)

라이브러리 없이 비터비 알고리즘의 로직을 직접 구현해 이해를 돕는 코드입니다.

 

import numpy as np
import pandas as pd

# 1. 모델 파라미터 정의
states = ['Sunny', 'Rainy']
observations = ['Game', 'Fitness']

# 초기 확률 (모른다고 가정하고 50:50)
start_prob = {'Sunny': 0.5, 'Rainy': 0.5}

# 전이 확률 (Transition Matrix)
trans_prob = {
    'Sunny': {'Sunny': 0.8, 'Rainy': 0.2},
    'Rainy': {'Sunny': 0.4, 'Rainy': 0.6}
}

# 방출 확률 (Emission Matrix)
emission_prob = {
    'Sunny': {'Game': 0.1, 'Fitness': 0.9},
    'Rainy': {'Game': 0.8, 'Fitness': 0.2}
}

# 2. 관측 시퀀스 (철수의 행동)
obs_seq = ['Game', 'Fitness', 'Fitness']

# 3. 비터비(Viterbi) 알고리즘 구현
def viterbi(obs, states, start_p, trans_p, emit_p):
    V = [{}] # 시간대별 확률 저장 (DP Tables)
    path = {}

    # (1) 초기화 (t=0)
    for y in states:
        V[0][y] = start_p[y] * emit_p[y][obs[0]]
        path[y] = [y]

    # (2) 재귀 단계 (t=1 ~ T)
    for t in range(1, len(obs)):
        V.append({})
        newpath = {}

        for y in states: # 현재 상태 y
            # 전 단계(y0)에서 현재(y)로 올 확률 중 최대값 찾기
            (prob, state) = max(
                (V[t-1][y0] * trans_p[y0][y] * emit_p[y][obs[t]], y0) for y0 in states
            )
            V[t][y] = prob
            newpath[y] = path[state] + [y]

        path = newpath

    # (3) 종료 (최대 확률 경로 선택)
    (prob, state) = max((V[len(obs) - 1][y], y) for y in states)
    return prob, path[state]

# 4. 결과 실행
prob, result_path = viterbi(obs_seq, states, start_prob, trans_prob, emission_prob)

print(f"관측된 행동: {obs_seq}")
print(f"추론된 날씨: {result_path}")
print(f"경로 확률: {prob:.6f}")

 

R Code (HMM 패키지)

R에서는 HMM 패키지를 사용하면 아주 간단하게 해결됩니다.

# install.packages("HMM")
library(HMM)

# 1. HMM 모델 초기화 (initHMM)
# States: 은닉 상태, Symbols: 관측값
hmm_model <- initHMM(
  States = c("Sunny", "Rainy"),
  Symbols = c("Game", "Fitness"),
  startProbs = c(0.5, 0.5),
  transProbs = matrix(c(0.8, 0.2,   # Sunny -> Sunny, Rainy
                        0.4, 0.6),  # Rainy -> Sunny, Rainy
                      nrow=2, byrow=TRUE),
  emissionProbs = matrix(c(0.1, 0.9, # Sunny -> Game, Fitness
                           0.8, 0.2), # Rainy -> Game, Fitness
                         nrow=2, byrow=TRUE)
)

# 2. 관측 시퀀스 정의
observations <- c("Game", "Fitness", "Fitness")

# 3. 비터비 알고리즘 실행 (viterbi)
# 가장 가능성 높은 은닉 상태 경로를 반환합니다.
hidden_states <- viterbi(hmm_model, observations)

cat("관측된 행동:", observations, "\n")
cat("추론된 날씨:", hidden_states, "\n")

 

 

코드 실행 결과 및 해석

해석:

  1. 첫날 Game을 했습니다. 비 올 때 게임할 확률(0.8)이 맑을 때(0.1)보다 압도적으로 높으므로 첫날은 비(Rainy)였을 것입니다.
  2. 둘째 날 Fitness를 했습니다. 비 $\rightarrow$ 맑음으로 바뀔 확률(0.4)이 맑음 $\rightarrow$ 맑음 유지(0.8)보다는 낮지만, 운동은 맑을 때 할 확률(0.9)이 매우 높습니다. 따라서 날씨가 맑음(Sunny)으로 개었다고 봅니다.
  3. 셋째 날도 Fitness입니다. 맑음 상태가 유지되었을 확률이 높습니다 (Sunny).

경로 확률(Path Probability)은 비터비(Viterbi) 알고리즘이 찾아낸 "가장 유력한 은닉 상태의 시나리오가 실제로 발생했을 확률"을 의미합니다.

쉽게 말해, "철수가 [게임, 운동, 운동]을 했을 때, 날씨가 [비, 맑음, 맑음]이었을 확률이 수학적으로 10.368%다"라는 뜻입니다.

왜 이 숫자가 나왔는지, 이전에 설정한 파라미터를 가지고 역추적해서 계산해 드리겠습니다. 딱 떨어지는 숫자의 비밀을 알면 훨씬 이해가 쉽습니다.

 

0.103680의 탄생 과정 (Step-by-Step)

우리가 찾은 최적의 날씨 경로(Rainy → Sunny → Sunny)를 따라가며 확률을 곱해봅시다.

1단계: 첫날 (비가 옴 → 게임을 함)

  • 초기 확률(비): 0.5
  • 방출 확률(비 → 게임): 0.8
  • 계산: $0.5 \times 0.8 = \mathbf{0.4}$

2단계: 둘째 날 (비가 그치고 맑아짐 → 운동을 함)

  • 이전 단계 확률: 0.4
  • 전이 확률(비 → 맑음): 0.4
  • 방출 확률(맑음 → 운동): 0.9
  • 계산: $0.4 \times 0.4 \times 0.9 = \mathbf{0.144}$

3단계: 셋째 날 (맑음 유지 → 운동을 함)

  • 이전 단계 확률: 0.144
  • 전이 확률(맑음 → 맑음): 0.8
  • 방출 확률(맑음 → 운동): 0.9
  • 계산: $0.144 \times 0.8 \times 0.9 = \mathbf{0.10368}$

결과: 0.10368 (이 값이 출력된 0.103680과 정확히 일치합니다!)

 

Insight

HMM은 의료 분야에서 "질병의 진행 단계 추적"에 매우 유용하게 쓰입니다.

  • 은닉 상태($S$): 질병의 진행 단계 (1, 2, 3) - 검사를 매일 할 수 없으니 은닉됨.
  • 관측값($O$): 혈액 검사 수치, 환자의 통증 호소 빈도 - 매일 관찰 가능.
  • 적용: 환자의 주기적인 혈액 검사 데이터($O$)를 HMM에 넣으면, 현재 질병이 악화되고 있는지 유지되고 있는지($S$)를 확률적으로 계산하여 조기 경보를 울릴 수 있습니다.

보이는 것(데이터)을 통해 보이지 않는 것(환자의 진짜 상태)을 읽어내는 기술, 그것이 바로 HMM입니다.

 

 

'Study Note > 통계' 카테고리의 다른 글

어려운 적분은 가라, 뽑아서 푼다! MCMC와 메트로폴리스-헤이스팅스  (0) 2025.12.19
확률은 변한다? 베이즈 통계와 켤레 사전 확률  (1) 2025.12.19
최적의 선택을 찾아라: 마르코프 의사결정 과정 (MDP)  (0) 2025.12.19
어제는 잊어라, 오직 오늘만 본다: 마르코프 연쇄 (Markov Chain)  (0) 2025.12.19
PCA와 비슷하지만 다른, 요인분석(Factor Analysis)의 모든 것  (0) 2025.12.19
    'Study Note/통계' 카테고리의 다른 글
    • 어려운 적분은 가라, 뽑아서 푼다! MCMC와 메트로폴리스-헤이스팅스
    • 확률은 변한다? 베이즈 통계와 켤레 사전 확률
    • 최적의 선택을 찾아라: 마르코프 의사결정 과정 (MDP)
    • 어제는 잊어라, 오직 오늘만 본다: 마르코프 연쇄 (Markov Chain)
    RyanNerd
    RyanNerd
    라이언 덕후의 일상 스토리~

    티스토리툴바