隱型馬爾科夫模型(HMM)向前算法實例講解(暴力求解+代碼實現)---盒子模型


先來解釋一下HMM的向前算法:

  前向后向算法是前向算法和后向算法的統稱,這兩個算法都可以用來求HMM觀測序列的概率。我們先來看看前向算法是如何求解這個問題的。

  前向算法本質上屬於動態規划的算法,也就是我們要通過找到局部狀態遞推的公式,這樣一步步的從子問題的最優解拓展到整個問題的最優解。在這里我們認為隨機過程中各個狀態St的概率分布,只與它的前一個狀態St-1有關,同時任何時刻的觀察狀態只僅僅依賴於當前時刻的隱藏狀態。

  在t時刻我們定義觀察狀態的概率為:

                αt(i)=P(o1,o2,...ot,it=qi|λ)

  從下圖可以看出,我們可以基於時刻t時各個隱藏狀態的前向概率,再乘以對應的狀態轉移概率,即αt(j)aji就是在時刻t觀測到o1,o2,...ot,即時刻t隱藏狀態qj,qj總和再乘以該時刻的發射概率得到時刻t+1隱藏狀態qi的概率。

 

 下面總結下前向算法。

    輸入:HMM模型λ=(A,B,Π)λ=(A,B,Π),觀測序列O=(o1,o2,...oT)

    輸出:觀測序列概率P(O|λ)

    1) 計算時刻1的各個隱藏狀態前向概率:

      α1(i)=πibi(o1),i=1,2,...N

    2) 遞推時刻2,3,...T時刻的前向概率:

      

    3) 計算最終結果:

      

    從遞推公式可以看出,我們的算法時間復雜度是O(TN2),比暴力解法的時間復雜度O(TNT)少了幾個數量級。

實例說明:

3個盒子,每個盒子都有紅、白兩種球,具體情況如下:

    盒子          1   2  3

    紅球數      5  4   7

    黑球數      5  6   3

   按照下面的方法從盒子里抽球,開始的時候,從第一個盒子抽球的概率是0.2,從第二個盒子抽球的概率是0.4,從第三個盒子抽球的概率是0.4。以這個概率抽一次球后,將球放回。然后從當前盒子轉移到下一個盒子進行抽球。規則是:如果當前抽球的盒子是第一個盒子,則以0.5的概率仍然留在第一個盒子繼續抽球,以0.2的概率去第二個盒子抽球,以0.3的概率去第三個盒子抽球。如果當前抽球的盒子是第二個盒子,則以0.5的概率仍然留在第二個盒子繼續抽球,以0.3的概率去第一個盒子抽球,以0.2的概率去第三個盒子抽球。如果當前抽球的盒子是第三個盒子,則以0.5的概率仍然留在第三個盒子繼續抽球,以0.2的概率去第一個盒子抽球,以0.3的概率去第二個盒子抽球。如此下去,直到重復三次,得到一個球的顏色的觀測序列:

                  O={}
  注意在這個過程中,觀察者只能看到球的顏色序列,卻不能看到球是從哪個盒子里取出的。
如下圖:
根據HMM的定義,我們可以得到觀察集合:
            V={紅、白} M=2
隱藏的狀態是:
        Q={盒子1、盒子2、盒子3} N=3
而觀察序列和狀態序列的長度為3.
 
對應的矩陣表示為:
初始狀態序列:
        ∏={0.2.0.4.0.4}T
狀態轉移矩陣:
          |0.5  0.2  0.3|
      A=  |0.3  0.5  0.2|
          |0.2  0.3  0.5|
觀察狀態矩陣:
          |0.5  0.5|
      B=  |0.4  0.6|
          |0.7  0.3|
1、暴力求解:
   ①紅色球
      隱藏狀態是盒子1:α1(1)=π1b1(o1)=0.2×0.5=0.1
      隱藏狀態是盒子2:α1(2)=π2b2(o1)=0.4×0.4=0.16
      隱藏狀態是盒子3:α1(3)=π3b3(o1)=0.4×0.7=0.28
  ②第一次紅色球前提下第二次白色球
         隱藏狀態是盒子1:α2(1)=[0.10.5+0.160.3+0.280.2]×0.5=0.077
      隱藏狀態是盒子2:α2(2)=[0.10.2+0.160.5+0.280.3]×0.6=0.1104
      隱藏狀態是盒子3:α2(3)=[0.10.3+0.160.2+0.280.5]×0.3=0.0606
  ③第一次紅色球、第二次白色球且第三次紅色球
      隱藏狀態是盒子1:α3(1)=[0.0770.5+0.11040.3+0.06060.2]×0.5=0.04187
        隱藏狀態是盒子2:α3(2)=[0.0770.2+0.11040.5+0.06060.3]×0.4=0.03551
      隱藏狀態是盒子3:α3(3)=[0.0770.3+0.11040.2+0.06060.5]×0.7=0.05284
最終我們求出觀測序列:O={}的概率為:
      P=0.04187+0.03551+0.05284=0.13022
 
1、python代碼實現:
# -*- coding: UTF-8 -*-
import numpy as np def Forward(trainsition_probability,emission_probability,pi,obs_seq): """ :param trainsition_probability:trainsition_probability是狀態轉移矩陣 :param emission_probability: emission_probability是發射矩陣 :param pi: pi是初始狀態概率 :param obs_seq: obs_seq是觀察狀態序列 :return: 返回結果 """ trainsition_probability = np.array(trainsition_probability) emission_probability = np.array(emission_probability) pi = np.array(pi) Row = np.array(trainsition_probability).shape[0] F = np.zeros((Row,Col))                      #最后要返回的就是F,就是我們公式中的alpha
    F[:,0] = pi * np.transpose(emission_probability[:,obs_seq[0]])  #這是初始化求第一列,就是初始的概率*各自的發射概率
    for t in range(1,len(obs_seq)):              #這里相當於填矩陣的元素值
        for n in range(Row):                     #n是代表隱藏狀態的
            F[n,t] = np.dot(F[:,t-1],trainsition_probability[:,n])*emission_probability[n,obs_seq[t]]   #對應於公式,前面是對應相乘
    return F if __name__ == '__main__': trainsition_probability = [[0.5,0.2,0.3],[0.3,0.5,0.2],[0.2,0.3,0.5]] emission_probability = [[0.5,0.5],[0.4,0.6],[0.7,0.3]] pi = [0.2,0.4,0.4] #然后下面先得到前向算法,在A,B,pi參數已知的前提下,求出特定觀察序列的概率是多少?
    obs_seq = [0,1,0] Row = np.array(trainsition_probability).shape[0] Col = len(obs_seq) F = Forward(trainsition_probability,emission_probability,pi,obs_seq) print F

對應結果:

[[ 0.1     0.077      0.04187 ]
[ 0.16    0.1104    0.035512]
[ 0.28    0.0606    0.052836]]

 
 
      
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM