目录
HMM 的代码实现 和 部分课后练习运行结果
HMM code
import numpy as np
class HMM:
def __init__(self):
self.alphas = None
self.betas = None
self.forward_p = None
self.backend_p = None
self.deltas = None
self.psis = None
self.I = None
def forward_probability(self, Q, V, A, B, PI, O):
# 状态序列的大小
N = len(Q)
# 观测序列的大小
M = len(O)
# 初始化前向概率alphas
alphas = np.zeros((N, M))
T = M
# 遍历 1 -> T 时刻,计算前向概率alphas的值
for t in range(T):
index_of_O = V.index(O[t])
for i in range(N):
# alphas 的初值
if t == 0:
alphas[i][t] = PI[i] * B[i][index_of_O]
print("alpha1({}) = PI({})B{}(O1) = {}".format(i+1, i+1, i+1, alphas[i][t]))
# 递推计算alphas在 t=2 -> T 时刻的值
else:
# for j in range(N):
# alphas[i][t] = sum(alphas[j][t-1] * A[j][i]) * B[i][index_of_O]
alphas[i][t] = np.dot([alpha[t-1] for alpha in alphas], [a[i] for a in A]) * B[i][index_of_O]
print("alpha{}({}) = sigma(alpha{}(j) * aj{}) * b{}(O{})] = {}".format(t+1, i+1, t, i+1, i+1, t+1, alphas[i][t]))
self.alphas = alphas
self.forward_p = np.sum(alpha[M-1] for alpha in alphas)
def backend_probability(self, Q, V, A, B, PI, O):
# 状态序列的长度
N = len(Q)
# 观测序列的长度
M = len(O)
# 时刻 = 观测序列的长度
T = M
# 初始化后向概率betas
betas = np.zeros((N, M))
# 遍历计算 1 -> T 时刻的后向概率
for t in reversed(range(T)):
for i in range(N):
# betas的初始值
if t == T-1:
betas[i][t] = 1
print("beta8({}) = {}".format(i+1, betas[i][t]))
else:
index_of_O = V.index(O[t + 1])
AB = np.multiply(A[i], [b[index_of_O] for b in B])
betas[i][t] = np.dot(AB, [beta[t+1] for beta in betas])
print("beta{}({}) = ".format(t+1, i+1), end='')
print("sigma a{}j * bj(o{}) * beta{}(j) = ".format(i+1, t+1+1, t+1+1,), end='')
print("{}".format(betas[i][t]))
self.betas = betas
self.backend_p = np.dot(np.multiply(PI, [b[V.index(O[0])] for b in B]), [beta[0] for beta in betas])
def viterbi(self, Q, V, A, B, PI, O):
# 状态序列的长度
N = len(Q)
# 观察序列的长度
M = len(O)
# 时刻 = 观察序列的长度
T = M
# 初始化单个路径最大概率deltas和单个路径概率最大的前一个结点psis
deltas = np.zeros((N, M))
psis = np.zeros((N, M))
# 初始化最有路径序列
I = np.zeros((1, M))
for t in range(T):