HMM代码实现
按照網(wǎng)上的代碼,自己敲了一下,改了一點點,理解加深了一下。
還有訓(xùn)練HMM的EM算法沒看懂,下次接著看;
?
參考連接:http://www.cnblogs.com/hanahimi/p/4011765.html
?
1 # -*- coding: utf-8 -*- 2 3 ''' 4 function: 根據(jù)網(wǎng)上的代碼,學(xué)習(xí)實現(xiàn) HMM,前向計算概率,后向預(yù)測狀態(tài)序列,學(xué)習(xí)算法參數(shù) 5 date: 2017.8.9 6 ''' 7 8 import numpy as np 9 10 class HMM(object): 11 """docstring Ann, Bnm, piln HMM""" 12 def __init__(self, Ann, Bnm, piln): 13 self.A = Ann 14 self.B = Bnm 15 self.pi = piln 16 self.N = self.A.shape[0] #狀態(tài)的種類個數(shù) 17 self.M = self.B.shape[1] #觀測序列的長度 18 19 #打印hmm的信息 20 def printHmm(self): 21 print("=======================================") 22 print('hmm content N = ', self.N, ' M = ', self.M) 23 for i in range(self.N): 24 if i == 0: 25 print('hmm.A ', self.A[i,:],'hmm.B', self.B[i,:]) 26 else: 27 print(' ', self.A[i,:], ' ', self.B[i,:]) 28 print('hmm.pi', self.pi) 29 print('========================================') 30 31 ''' 32 function: 維特比算法 33 input: A,B,pi,O 34 output: P(o|lambda) 最大的時候,狀態(tài)的路徑序列 35 ''' 36 def viterbi(self, O): 37 T = len(O) #觀察序列的長度 38 39 #初始化,這里從0~T-1 40 #delta t行 n列,代表有t個時間點,每個時間點可能有n種狀態(tài) 41 delta = np.zeros((T, self.N), np.float) #二維數(shù)組記錄計算的所有概率,包括了最有的點 42 phi = np.zeros((T, self.N), np.int) #記錄概率最大路徑的前一個狀態(tài) 43 I = np.zeros(T, np.int) #這里如果不顯示表明類型為 np.int,就是float? 44 for i in range(self.N): 45 delta[0,i] = self.pi[i] * self.B[i,O[0]] #t = 0時刻,各個狀態(tài)的起始概率 46 phi[0,i] = 0 #t=0時刻前綴狀態(tài)都是0 47 48 #遞推 49 for t in range(1,T): #從 1 開始 50 for i in range(self.N): 51 delta[t,i] = self.B[i,O[t]] * np.array([delta[t-1,j]*self.A[j,i] \ 52 for j in range(self.N)]).max() 53 phi[t,i] = np.array([delta[t-1, j]*self.A[j,i] for j in range(self.N)]).argmax() 54 #結(jié)束 55 prob = delta[T-1,:].max() #T-1時刻是最后時刻,哪個狀態(tài)在最后時刻概率最大就是最優(yōu)路徑的起始點 56 I[T-1] = phi[T-1,:].argmax() #最優(yōu)路徑的起點狀態(tài)編號 57 #狀態(tài)序列獲取 58 for t in range(T-2, -1, -1): #從 T-1 到 -1(不包括-1),間隔是-1,即遞減 59 I[t] = phi[t+1, I[t+1]] 60 return I, prob 61 62 ''' 63 function: 前向算法計算擦觀察序列 O 出現(xiàn)的概率 64 input: A,B,pi,O 65 output: prob 66 ''' 67 def forward(self, O): 68 T = len(O) 69 alpha = np.zeros((T, self.N), np.float) #暫存計算的所有概率,按照時間點向前推進 70 #初始化 71 for i in range(self.N): 72 alpha[0,i] = self.pi[i] * self.B[i, O[0]] 73 74 #迭代計算 75 for t in range(T-1): 76 for i in range(self.N): #這里B[i,O[t]]也可以放在for的外面乘 77 alpha[t+1,i] = np.array([alpha[t, j]*self.A[j,i]*self.B[i,O[t+1]] for \ 78 j in range(self.N)]).sum() 79 80 #終止 81 prob = np.array([alpha[T-1, j] for j in range(self.N)]).sum() 82 return prob 83 84 ''' 85 function: 后向算法,計算觀測序列出現(xiàn)的概率 86 87 ''' 88 def backword(self, O): 89 T = len(O) 90 beta = np.zeros((T, self.N), np.float) #暫存計算的概率 91 92 #初始化 93 for i in range(self.N): 94 beta[T-1, i] = 1 #從后向前 95 #迭代計算 96 for t in range(T-2, -1, -1): 97 for i in range(self.N): 98 beta[t,i] = np.array([[A[j,i] * B[j,O[t+1]] * beta[t+1,j]] for \ 99 j in range(self.N)]).sum() 100 101 prob = np.array([self.pi[j] * self.B[i,O[1]] * beta[1,j] for j in range(self.N)]).sum() 102 103 return prob 104 105 106 107 if __name__ == 'main': 108 109 print('python my HMM') 110 111 #HMM模型的參數(shù) 112 A = [[0.8125,0.1875],[0.2,0.8]] 113 B = [[0.875,0.125], [0.25,0.75]] #每一行的和是 1 114 pi = [0.5,0.5] 115 hmm = HMM(A,B,pi) #構(gòu)建HMM 116 117 print(hmm) 118 119 print('python my HMM') 120 121 #HMM模型的參數(shù) 122 A = np.mat([[0.8125,0.1875],[0.2,0.8]]) 123 B = np.mat([[0.875,0.125], [0.25,0.75]]) #每一行的和是 1 124 pi = [0.5,0.5] 125 O = [[1,0,0,1,1,0,0,0,0], 126 [1,1,0,1,0,0,1,1,0], 127 [0,0,1,1,0,0,1,1,1]] 128 129 hmm = HMM(A,B,pi) #構(gòu)建HMM 130 131 #計算前向概率,產(chǎn)生特定觀測序列O的概率 132 prob = hmm.forward(O[0]) 133 print('前向算法產(chǎn)生 O 序列的概率是: ' + str(prob)) 134 135 #后向算法計算觀測序列的概率 136 prob = hmm.backword(O[0]) 137 print('后向算法概率是: ' + str(prob)) 138 #計算隱含概率,維特比算法 139 path, prob2 = hmm.viterbi(O[0]) 140 print('產(chǎn)生 O 序列最大概率路徑是: ' + str(path)) 141 print('概率是: ' + str(prob2)) 142 143 hmm.printHmm()?
轉(zhuǎn)載于:https://www.cnblogs.com/robin2ML/p/7340033.html
總結(jié)
- 上一篇: 自己定义九宫格手势解锁
- 下一篇: 【VBA】查看窗口当前状态