今天学习了《统计学习分析》的第10章-隐马尔科夫模型,一堆公式看的云里雾里,虽然基本上都可以看明白,但为了理解的更深,还是看看别人已经总结好的文章比较好,省了时间,同时效果更好。下面贴出我看的几篇博客:
-
如何通过一些简单的例子理解隐马尔科夫模型?
如何用简单易懂的例子解释隐马尔可夫模型? -
如何从理论上理解隐马尔科夫模型的基本内容?
智能算法之隐马尔可夫模型(HMM) -
隐马尔科夫的实现
import numpy as np
class HMM:
"""
Order 1 Hidden Markov Model
Attributes
----------
A : numpy.ndarray
State transition probability matrix
B: numpy.ndarray
Output emission probability matrix with shape(N, number of output types)
pi: numpy.ndarray
Initial state probablity vector
Common Variables
----------------
obs_seq : list of int
list of observations (represented as ints corresponding to output
indexes in B) in order of appearance
T : int
number of observations in an observation sequence
N : int
number of states
"""
def __init__(self, A, B, pi):
self.A = A
self.B = B
self.pi = pi
def _forward(self, obs_seq):
N = self.A.shape[0]
T = len(obs_seq)
F = np.zeros((N,T))
F[:,0] = self.pi * self.B[:, obs_seq[0]]
for t in range(1, T):
for n in range(N):
F[n,t] = np.dot(F[:,t-1], (self.A[:,n])) * self.B[n, obs_seq[t]]
return F
def _backward(self, obs_seq):
N = self.A.shape[0]
T = len(obs_seq)
X = np.zeros((N,T))
X[:,-1:] = 1
for t in reversed(range(T-1)):
for n in range(N):
X[n,t] = np.sum(X[:,t+1] * self.A[n,:] * self.B[:, obs_seq[t+1]])
return X
def observation_prob(self, obs_seq):
""" P( entire observation sequence | A, B, pi ) """
return np.sum(self._forward(obs_seq)[:,-1])
def state_path(self, obs_seq):
"""
Returns
-------
V[last_state, -1] : float
Probability of the optimal state path
path : list(int)
Optimal state path for the observation sequence
"""
V, prev = self.viterbi(obs_seq)
# Build state path with greatest probability
last_state = np.argmax(V[:,-1])
path = list(self.build_viterbi_path(prev, last_state))
return V[last_state,-1], reversed(path)
def viterbi(self, obs_seq):
"""
Returns
-------
V : numpy.ndarray
V [s][t] = Maximum probability of an observation sequence ending
at time 't' with final state 's'
prev : numpy.ndarray
Contains a pointer to the previous state at t-1 that maximizes
V[state][t]
"""
N = self.A.shape[0]
T = len(obs_seq)
prev = np.zeros((T - 1, N), dtype=int)
# DP matrix containing max likelihood of state at a given time
V = np.zeros((N, T))
V[:,0] = self.pi * self.B[:,obs_seq[0]]
for t in range(1, T):
for n in range(N):
seq_probs = V[:,t-1] * self.A[:,n] * self.B[n, obs_seq[t]]
prev[t-1,n] = np.argmax(seq_probs)
V[n,t] = np.max(seq_probs)
return V, prev
def build_viterbi_path(self, prev, last_state):
"""Returns a state path ending in last_state in reverse order."""
T = len(prev)
yield(last_state)
for i in range(T-1, -1, -1):
yield(prev[i, last_state])
last_state = prev[i, last_state]
def baum_welch_train(self, obs_seq):
N = self.A.shape[0]
T = len(obs_seq)
forw = self._forward(obs_seq)
back = self._backward(obs_seq)
# P( entire observation sequence | A, B, pi )
obs_prob = np.sum(forw[:,-1])
if obs_prob <= 0:
raise ValueError("P(O | lambda) = 0. Cannot optimize!")
xi = np.zeros((T-1, N, N))
for t in range(xi.shape[0]):
xi[t,:,:] = self.A * forw[:,[t]] * self.B[:,obs_seq[t+1]] * back[:, t+1] / obs_prob
gamma = forw * back / obs_prob
# Gamma sum excluding last column
gamma_sum_A = np.sum(gamma[:,:-1], axis=1, keepdims=True)
# Vector of binary values indicating whether a row in gamma_sum is 0.
# If a gamma_sum row is 0, save old rows on update
rows_to_keep_A = (gamma_sum_A == 0)
# Convert all 0s to 1s to avoid division by zero
gamma_sum_A[gamma_sum_A == 0] = 1.
next_A = np.sum(xi, axis=0) / gamma_sum_A
gamma_sum_B = np.sum(gamma, axis=1, keepdims=True)
rows_to_keep_B = (gamma_sum_B == 0)
gamma_sum_B[gamma_sum_B == 0] = 1.
obs_mat = np.zeros((T, self.B.shape[1]))
obs_mat[range(T),obs_seq] = 1
next_B = np.dot(gamma, obs_mat) / gamma_sum_B
# Update model
self.A = self.A * rows_to_keep_A + next_A
self.B = self.B * rows_to_keep_B + next_B
self.pi = gamma[:,0] / np.sum(gamma[:,0])
具体可见 隐马尔可夫模型的实现类
读完这几篇博客,算了比较深的了解了隐马尔科夫模型,有兴趣的可以看一下。这里整理,以便后面回顾。
怀揣一颗感恩的心!
1万+

被折叠的 条评论
为什么被折叠?



