本节理论笔记见:语音识别入门第四节:隐马尔可夫模型(HMM)
前向算法核心代码如下:
a = np.zeros((T, N))
a[0, :] = [pi[k] * B[k][O[0]] for k in range(N)]
for t in range(1, T, 1):
a[t, :] = [sum([a[t-1][j] * A[j][i] for j in range(N)]) * B[i][O[t]]for i in range(N)]
prob = sum(a[T-1])
后向算法核心代码如下:
beta = np.ones((T, N))
for t in range(T - 2, -1, -1):
beta[t, :] = [sum([A[i][j] * B[j][O[t+1]] * beta[t+1][j] for j in range(N)]) for i in range(N)]
prob = sum([pi[i] * B[i][O[0]] * beta[0][i] for i in range(N)])
Viterbi算法核心代码如下:
delta = np.zeros((T, N))
psi = np.zeros((T, N))
delta[0, :] = [pi[i] * B[i][O[0]] for i in range(N)]
for t in range(1, T, 1):
delta[t, :] = [max([delta[t - 1][j] * A[j][i] * B[i][O[t]] for j in range(N)]) for i in range(N)]
psi[t, :] = [np.argmax([delta[t - 1][j] * A[j][i] for j in range(N)]) for i in range(N)]
best_prob = max(delta[T - 1])
best_path[T-1] = np.argmax(delta[T - 1])
for t in range(T - 2, -1, -1):
best_path[t] = int(psi[t + 1][best_path[t + 1]])
完整代码如下:
# Author: Kaituo Xu, Fan Yu
import numpy as np
def forward_algorithm(O, HMM_model):
"""HMM Forward Algorithm.
Args:
O: (o1, o2, ..., oT), observations
HMM_model: (pi, A, B), (init state prob, transition prob, emitting prob)
Return:
prob: the probability of HMM_model generating O.
"""
pi, A, B = HMM_model
T = len(O)
N = len(pi)
prob = 0.0
# Begin Assignment
a = np.zeros((T, N))
a[0, :] = [pi[k] * B[k][O[0]] for k in range(N)]
for t in range(1, T, 1):
a[t, :] = [sum([a[t-1][j] * A[j][i] for j in range(N)]) * B[i][O[t]]for i in range(N)]
prob = sum(a[T-1])
# Put Your Code Here
# End Assignment
return prob
def backward_algorithm(O, HMM_model):
"""HMM Backward Algorithm.
Args:
O: (o1, o2, ..., oT), observations
HMM_model: (pi, A, B), (init state prob, transition prob, emitting prob)
Return:
prob: the probability of HMM_model generating O.
"""
pi, A, B = HMM_model
T = len(O)
N = len(pi)
prob = 0.0
# Begin Assignment
beta = np.ones((T, N))
for t in range(T - 2, -1, -1):
beta[t, :] = [sum([A[i][j] * B[j][O[t+1]] * beta[t+1][j] for j in range(N)]) for i in range(N)]
prob = sum([pi[i] * B[i][O[0]] * beta[0][i] for i in range(N)])
# Put Your Code Here
# End Assignment
return prob
def Viterbi_algorithm(O, HMM_model):
"""Viterbi decoding.
Args:
O: (o1, o2, ..., oT), observations
HMM_model: (pi, A, B), (init state prob, transition prob, emitting prob)
Returns:
best_prob: the probability of the best state sequence
best_path: the best state sequence
"""
pi, A, B = HMM_model
T = len(O)
N = len(pi)
best_prob, best_path = 0.0, {}
# Begin Assignment
delta = np.zeros((T, N))
psi = np.zeros((T, N))
delta[0, :] = [pi[i] * B[i][O[0]] for i in range(N)]
for t in range(1, T, 1):
delta[t, :] = [max([delta[t - 1][j] * A[j][i] * B[i][O[t]] for j in range(N)]) for i in range(N)]
psi[t, :] = [np.argmax([delta[t - 1][j] * A[j][i] for j in range(N)]) for i in range(N)]
best_prob = max(delta[T - 1])
best_path[T-1] = np.argmax(delta[T - 1])
for t in range(T - 2, -1, -1):
best_path[t] = int(psi[t + 1][best_path[t + 1]])
# End Assignment
return best_prob, best_path
if __name__ == "__main__":
color2id = { "RED": 0, "WHITE": 1 }
# model parameters
pi = [0.2, 0.4, 0.4]
A = [[0.5, 0.2, 0.3],
[0.3, 0.5, 0.2],
[0.2, 0.3, 0.5]]
B = [[0.5, 0.5],
[0.4, 0.6],
[0.7, 0.3]]
# input
observations = (0, 1, 0)
HMM_model = (pi, A, B)
# process
observ_prob_forward = forward_algorithm(observations, HMM_model)
print(observ_prob_forward)
observ_prob_backward = backward_algorithm(observations, HMM_model)
print(observ_prob_backward)
best_prob, best_path = Viterbi_algorithm(observations, HMM_model)
print(best_prob, best_path)