狀態 \(N\)個html
狀態序列 \(S = s_1,s_2,...\)python
觀測序列 \(O=O_1,O_2,...\)算法
\(\lambda(A,B,\pi)\)學習
觀測序列生成過程spa
給定觀測序列 \(O=O_1O_2...O_T\),模型 \(\lambda (A,B,\pi)\),計算 \(P(O|\lambda)\),即計算觀測序列的機率.net
給定觀測序列 \(O=O_1O_2...O_T\),模型 \(\lambda (A,B,\pi)\),找到對應的狀態序列 \(S\)code
給定觀測序列 \(O=O_1O_2...O_T\),找到模型參數 \(\lambda (A,B,\pi)\),以最大化 \(P(O|\lambda)\),htm
給定模型 \(\lambda\) 和觀測序列 \(O\),如何計算\(P(O| \lambda)\)?blog
暴力枚舉每個可能的狀態序列 \(S\)jsx
對每個給定的狀態序列
一個狀態序列的產生機率
聯合機率
考慮全部的狀態序列
\(O\) 可能由任意一個狀態獲得,因此須要將每一個狀態的可能性相加。
這樣作什麼問題?時間複雜度高達 \(O(2TN^T)\)。每一個序列須要計算 \(2T\) 次,一共 \(N^T\) 個序列。
在時刻 \(t\),狀態爲 \(i\) 時,前面的時刻觀測到 \(O_1,O_2, ..., O_t\) 的機率,記爲 \(\alpha _i(t)\) :
當 \(t=1\) 時,輸出爲 \(O_1\),假設有三個狀態,\(O_1\) 多是任意一個狀態發出,即
當 \(t=2\) 時,輸出爲 \(O_1O_2\) ,\(O_2\) 可能由任一個狀態發出,同時產生 \(O_2\) 對應的狀態能夠由 \(t=1\) 時刻任意一個狀態轉移獲得。假設 \(O_2\) 由狀態 1
發出,以下圖
同理可得 \(\alpha_2(2),\alpha_3(2)\)
因此
因此前向算法過程以下:
step1:初始化 \(\alpha_i(1)= \pi_i*b_i(O_1)\)
step2:計算 \(\alpha_i(t) = (\sum^{N}_{j=1} \alpha_j(t-1)a_{ji})b_i(O_{t})\)
step3:\(P(O|\lambda) = \sum^N_{i=1}\alpha_i(T)\)
相比暴力法,時間複雜度下降了嗎?
當前時刻有 \(N\) 個狀態,每一個狀態可能由前一時刻 \(N\) 個狀態中的任意一個轉移獲得,因此單個時刻的時間複雜度爲 \(O(N^2)\),總時間複雜度爲 \(O(TN^2)\)
代碼實現
例子:
假設從三個 袋子 {1,2,3}
中 取出 4 個球 O={red,white,red,white}
,模型參數\(\lambda = (A,B,\pi)\) 以下,計算序列O
出現的機率
#狀態 1 2 3 A = [[0.5,0.2,0.3], [0.3,0.5,0.2], [0.2,0.3,0.5]] pi = [0.2,0.4,0.4] # red white B = [[0.5,0.5], [0.4,0.6], [0.7,0.3]]
step1:初始化 \(\alpha_i(1)= \pi_i*b_i(O_1)\)
step2:計算 \(\alpha_i(t) = (\sum^{N}_{j=1} \alpha_j(t-1)a_{ji})b_i(O_{t})\)
step3:\(P(O|\lambda) = \sum^N_{i=1}\alpha_i( T)\)
#前向算法 def hmm_forward(A,B,pi,O): T = len(O) N = len(A[0]) #step1 初始化 alpha = [[0]*T for _ in range(N)] for i in range(N): alpha[i][0] = pi[i]*B[i][O[0]] #step2 計算alpha(t) for t in range(1,T): for i in range(N): temp = 0 for j in range(N): temp += alpha[j][t-1]*A[j][i] alpha[i][t] = temp*B[i][O[t]] #step3 proba = 0 for i in range(N): proba += alpha[i][-1] return proba,alpha 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]] pi = [0.2,0.4,0.4] O = [0,1,0,1] hmm_forward(A,B,pi,O) #結果爲 0.06009
結果
在時刻 \(t\),狀態爲 \(i\) 時,觀測到 \(O_{t+1},O_{t+2}, ..., O_T\) 的機率,記爲 \(\beta _i(t)\) :
當 \(t=T\) 時,因爲 \(T\) 時刻以後爲空,沒有觀測,因此 \(\beta_i(t)=1\)
當 \(t = T-1\) 時,觀測 \(O_T\) ,\(O_T\) 可能由任意一個狀態產生
當 \(t=1\) 時,觀測爲 \(O_{2},O_{3}, ..., O_T\)
因此
後向算法過程以下:
step1:初始化 \(\beta_i(T)=1\)
step2:計算 \(\beta_i(t) = \sum^N_{j=1}a_{ij}b_j(O_{t+1})\beta_j(t+1)\)
step3:\(P(O|\lambda) = \sum^N_{i=1}\pi_ib_i(O_1)\beta_i(1)\)
代碼實現
仍是上面的例子
#後向算法 def hmm_backward(A,B,pi,O): T = len(O) N = len(A[0]) #step1 初始化 beta = [[0]*T for _ in range(N)] for i in range(N): beta[i][-1] = 1 #step2 計算beta(t) for t in reversed(range(T-1)): for i in range(N): for j in range(N): beta[i][t] += A[i][j]*B[j][O[t+1]]*beta[j][t+1] #step3 proba = 0 for i in range(N): proba += pi[i]*B[i][O[0]]*beta[i][0] return proba,beta 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]] pi = [0.2,0.4,0.4] O = [0,1,0,1] hmm_backward(A,B,pi,O) #結果爲 0.06009
結果
回顧前向、後向變量:
即在給定的狀態序列中,\(t\) 時刻狀態爲 \(i\) 的機率。
使用先後向算法能夠計算隱狀態,記 \(\gamma_i(t) = P(s_t=i|O,\lambda)\) 表示時刻 \(t\) 位於隱狀態 \(i\) 的機率
references:
[1] https://www.cs.sjsu.edu/~stamp/RUA/HMM.pdf
[2]http://www.javashuo.com/article/p-tsuweuhp-g.html
[3] http://www.javashuo.com/article/p-wmvxlnjq-cn.html
[4] https://blog.csdn.net/xueyingxue001/article/details/52396494