隐马尔科夫模型——前向后向算法python实现
描述:隐马尔科夫模型的三个基本问题之一:概率计算问题。给定模型λ=(A,B,π)和观测序列O=(o1,o2,...,oT),计算在模型λ下观测序列O出现的概率P(O|λ)
概率计算问题有三种求解方法:
直接计算法(时间复杂度为O(TN^T),计算量非常大,不易实现)
前向算法:A:状态转移概率矩阵;B:观测概率矩阵;Pi:初始状态概率向量;O:观测序列
1 def forward(A, B, Pi, O): 2 """计算前向概率""" 3 m = np.shape(A)[0] 4 n = np.shape(O)[0] 5 alpha = np.zeros((n, m)) 6 7 for i in range(m): 8 alpha[0][i] = Pi[0][i]*B[i][0] 9 10 for t in range(1, n): 11 for i in range(m): 12 sum = 0 13 for j in range(m): 14 sum += alpha[t-1][j]*A[j][i] 15 alpha[t][i] = sum * B[i][O[t]-1] 16 17 return alpha 18 19 def calc_forward(alpha): 20 """前向算法计算观测序列O出现的概率""" 21 p = 0 22 m = np.shape(alpha)[0] 23 for i in range(m): 24 p += alpha[-1][i] 25 26 return p
后向算法:A:状态转移概率矩阵;B:观测概率矩阵;Pi:初始状态概率向量;O:观测序列
1 # 方法一 2 def backward1(A, B, Pi, O): 3 """计算后向概率""" 4 m = np.shape(A)[0] 5 n = np.shape(O)[0] 6 beta = np.zeros((n, m)) 7 sum_beta = np.zeros((m, m)) 8 9 for i in range(m): 10 beta[n-1][i] = 1 11 12 for t in range(n-1, 0, -1): 13 for i in range(m): 14 for j in range(m): 15 sum_beta[i, j] = A[i, j]*B[j, O[t]-1]*beta[t, j] 16 beta[t-1][:] = sum_beta.sum(1) 17 18 return beta 19 20 # 方法二 21 def backward(A, B, Pi, O): 22 """计算后向概率""" 23 m = np.shape(A)[0] 24 n = np.shape(O)[0] 25 beta = np.zeros((n, m)) 26 sum_beta = np.zeros((m, m)) 27 28 for i in range(m): 29 beta[n-1][i] = 1 30 31 for t in range(n-1, 0, -1): 32 for i in range(m): 33 sum_beta[i, :] = A[i, :]*B[:, O[t]-1]*beta[t, :] 34 beta[t-1][:] = sum_beta.sum(1) 35 36 return beta 37 38 def calc_backward(beta, Pi, B): 39 """后向算法计算观测概率O出现的概率""" 40 r = Pi[0]*B[:, 0]*beta[0, :] 41 p = r.sum() 42 43 return p