模型 HMM=(A, B, \pi)
初始化三個引數:隱狀態初始狀態概率向量\pi,狀態轉移概率矩陣A,隱狀態生成觀測狀態概率矩陣B,
實作三個方法:
1、2. 計算給定觀測狀態序列向量的概率(前向和后向兩種計算方法),
3. 給定觀測狀態序列,求出與該序列最匹配的隱狀態序列及其概率(Viterbi演算法),
程式如下:
# -*- coding: utf-8 -*- # @Author : ZhaoKe # @Time : 2022-09-18 14:43 from typing import List import numpy as np class HMM(): def __init__(self): # 對應三個隱狀態初始化概率矩陣 self.init_prob = np.array([0.4, 0.3, 0.3]) # 隱狀態會生成觀測狀態的概率矩陣 self.gene_prob = np.array([ [0.8, 0.2], [0.6, 0.4], [0.3, 0.7] ]) # 狀態轉移概率矩陣 self.tran_prob = np.array([ [0.4, 0.5, 0.1], [0.3, 0.4, 0.3], [0.1, 0.5, 0.4] ]) # 求解生成特定的序列的概率 # 例如,輸入[0, 1, 0] def forward_prob_generate(self, series: List): # 行數等于隱狀態個數,列數等于序列長度 # print(len(self.init_prob), len(series)) res = np.zeros((len(self.init_prob), len(series))) res[:, 0] = np.multiply(self.init_prob, self.gene_prob[:, series[0]]) for i in range(1, len(series)): res[:, i] = np.multiply(np.matmul(res[:, i-1], self.tran_prob), self.gene_prob[:, series[i]]) print(res) # 后向生成特定序列的概率 def backward_prob_generate(self, series: List): res = np.zeros((len(self.init_prob), len(series))) n = len(series) res[:, n-1] = 1 for i in range(n-2, -1, -1): res[:, i] = np.matmul(self.tran_prob, np.multiply(self.gene_prob[:, series[i+1]], res[:, i+1])) print(res) print(np.sum(self.init_prob * self.gene_prob[:, 1] * res[:, 0])) # 維特比演算法求解特定觀測序列的最優隱狀態向量及其概率 def viterbi(self, series: List): # 動態規劃 dp = np.zeros((3, 4)) dp[:, 0] = 1 dp[:, 1] = self.init_prob * self.gene_prob[:, series[0]] per = list(map(int, np.zeros(len(series)+1))) per[1] = np.argmax(dp[:, 1]) # print(dp) # print(per) for i in range(2, len(series)+1): for j in range(0, 3): tmp = dp[:, i-1] * self.tran_prob[:, j] dp[j, i] = np.max(tmp) * self.gene_prob[j][series[i-1]] print(dp[:, i]) per[i] = np.argmax(dp[:, i]) print("動態規劃矩陣:\n", dp) print("最優路徑:", per) print("概率計算:", dp[per[-1], 3]) if __name__ == '__main__': hmm = HMM() # hmm.forward_prob_generate([0, 1, 0]) # hmm.backward_prob_generate([1, 0, 1]) # hmm.viterbi([0,0,0]) # hmm.viterbi([0,0,1]) # hmm.viterbi([0,1,0]) # hmm.viterbi([0,1,1]) hmm.viterbi([1,0,0]) # hmm.viterbi([1,0,1]) # hmm.viterbi([1,1,0]) # hmm.viterbi([1,1,1])
和例題對照,結果正確
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/509040.html
標籤:其他
上一篇:NLP語言學基礎
