Python實現隱馬爾可夫模型的前向后向算法的示例代碼
本篇文章對隱馬爾可夫模型的前向和后向算法進行了Python實現,并且每種算法都給出了循環(huán)和遞歸兩種方式的實現。
前向算法Python實現
循環(huán)方式
import numpy as np def hmm_forward(Q, V, A, B, pi, T, O, p): """ :param Q: 狀態(tài)集合 :param V: 觀測集合 :param A: 狀態(tài)轉移概率矩陣 :param B: 觀測概率矩陣 :param pi: 初始概率分布 :param T: 觀測序列和狀態(tài)序列的長度 :param O: 觀測序列 :param p: 存儲各個狀態(tài)的前向概率的列表,初始為空 """ for t in range(T): # 計算初值 if t == 0: for i in range(len(Q)): p.append(pi[i] * B[i, V[O[0]]]) # 初值計算完畢后,進行下一時刻的遞推運算 else: alpha_t_ = 0 alpha_t_t = [] for i in range(len(Q)): for j in range(len(Q)): alpha_t_ += p[j] * A[j, i] alpha_t_t.append(alpha_t_ * B[i, V[O[t]]]) alpha_t_ = 0 p = alpha_t_t return sum(p) # 《統計學習方法》書上例10.2 Q = [1, 2, 3] V = {'紅':0, '白':1} A = np.array([[0.5, 0.2, 0.3], [0.3, 0.5, 0.2], [0.2, 0.3, 0.5]]) B = np.array([[0.5, 0.5], [0.4, 0.6], [0.7, 0.3]]) pi = [0.2, 0.4, 0.4] T = 3 O = ['紅', '白', '紅'] p = [] print(hmm_forward(Q, V, A, B, pi, T, O, p)) # 0.130218
遞歸方式
import numpy as np def hmm_forward_(Q, V, A, B, pi, T, O, p, T_final): """ :param T_final:遞歸的終止條件 """ if T == 0: for i in range(len(Q)): p.append(pi[i] * B[i, V[O[0]]]) else: alpha_t_ = 0 alpha_t_t = [] for i in range(len(Q)): for j in range(len(Q)): alpha_t_ += p[j] * A[j, i] alpha_t_t.append(alpha_t_ * B[i, V[O[T]]]) alpha_t_ = 0 p = alpha_t_t if T >= T_final: return sum(p) return hmm_forward_(Q, V, A, B, pi, T+1, O, p, T_final) Q = [1, 2, 3] V = {'紅':0, '白':1} A = np.array([[0.5, 0.2, 0.3], [0.3, 0.5, 0.2], [0.2, 0.3, 0.5]]) B = np.array([[0.5, 0.5], [0.4, 0.6], [0.7, 0.3]]) pi = [0.2, 0.4, 0.4] T = 0 O = ['紅', '白', '紅'] p = [] T_final = 2 # T的長度是3,T的取值是(0時刻, 1時刻, 2時刻) print(hmm_forward_(Q, V, A, B, pi, T, O, p, T_final))
后向算法Python實現
循環(huán)方式
import numpy as np def hmm_backward(Q, V, A, B, pi, T, O, beta_t, T_final): for t in range(T, -1, -1): if t == T_final: beta_t = beta_t else: beta_t_ = 0 beta_t_t = [] for i in range(len(Q)): for j in range(len(Q)): beta_t_ += A[i, j] * B[j, V[O[t + 1]]] * beta_t[j] beta_t_t.append(beta_t_) beta_t_ = 0 beta_t = beta_t_t if t == 0: p=[] for i in range(len(Q)): p.append(pi[i] * B[i, V[O[0]]] * beta_t[i]) beta_t = p return sum(beta_t) # 《統計學習方法》課后題10.1 Q = [1, 2, 3] V = {'紅':0, '白':1} A = np.array([[0.5, 0.2, 0.3], [0.3, 0.5, 0.2], [0.2, 0.3, 0.5]]) B = np.array([[0.5, 0.5], [0.4, 0.6], [0.7, 0.3]]) pi = [0.2, 0.4, 0.4] T = 3 O = ['紅', '白', '紅', '白'] beta_t = [1, 1, 1] T_final = 3 print(hmm_backward_(Q, V, A, B, pi, T, O, beta_t, T_final)) # 0.06009
遞歸方式
import numpy as np def hmm_backward(Q, V, A, B, pi, T, O, beta_t, T_final): if T == T_final: beta_t = beta_t else: beta_t_ = 0 beta_t_t = [] for i in range(len(Q)): for j in range(len(Q)): beta_t_ += A[i, j] * B[j, V[O[T+1]]] * beta_t[j] beta_t_t.append(beta_t_) beta_t_ = 0 beta_t = beta_t_t if T == 0: p=[] for i in range(len(Q)): p.append(pi[i] * B[i, V[O[0]]] * beta_t[i]) beta_t = p return sum(beta_t) return hmm_backward(Q, V, A, B, pi, T-1, O, beta_t, T_final) jpgQ = [1, 2, 3] V = {'紅':0, '白':1} A = np.array([[0.5, 0.2, 0.3], [0.3, 0.5, 0.2], [0.2, 0.3, 0.5]]) B = np.array([[0.5, 0.5], [0.4, 0.6], [0.7, 0.3]]) pi = [0.2, 0.4, 0.4] T = 3 O = ['紅', '白', '紅', '白'] beta_t = [1, 1, 1] T_final = 3 print(hmm_backward_(Q, V, A, B, pi, T, O, beta_t, T_final)) # 0.06009
這里我有個問題不理解,這道題的正確答案應該是0.061328,我計算出的答案和實際有一點偏差,我跟蹤了代碼的計算過程,發(fā)現在第一次循環(huán)完成后,計算結果是正確的,第二次循環(huán)后的結果就出現了偏差,我懷疑是小數部分的精度造成,希望有人能給出一個更好的解答,如果是代碼的問題也歡迎指正。
以上所述是小編給大家介紹的Python實現隱馬爾可夫模型的前向后向算法,希望對大家有所幫助!
相關文章
解決python中os.listdir()函數讀取文件夾下文件的亂序和排序問題
今天小編就為大家分享一篇解決python中os.listdir()函數讀取文件夾下文件的亂序和排序問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-10-10conda查看、創(chuàng)建、刪除、激活與退出環(huán)境命令詳解
在不同的項目中經常需要conda來配置環(huán)境,這樣能夠實現不同版本的python和庫的隨意切換,并且減少了很多不必要的麻煩,下面這篇文章主要給大家介紹了關于conda查看、創(chuàng)建、刪除、激活與退出環(huán)境命令的相關資料,需要的朋友可以參考下2023-05-05解決PyCharm不在run輸出運行結果而不是再Console里輸出的問題
這篇文章主要介紹了解決PyCharm不在run輸出運行結果而不是再Console里輸出的問題,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-09-09Python中l(wèi)ogging日志記錄到文件及自動分割的操作代碼
這篇文章主要介紹了Python中l(wèi)ogging日志記錄到文件及自動分割,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-08-08