維特比算法Python實現


前言

維特比算法是隱馬爾科夫問題的一個基本問題算法。維特比算法解決的問題是已知觀察序列,求最可能的標注序列。

什么是維特比算法?

維特比算法盡管是基於嚴格的數學模型的算法,但是維特比算法畢竟是算法,因此可以感性地去理解。關於感性的認識,知乎上有維特比算法的感性認識講解,講的非常好,也非常仔細。在這里,我闡述一下自己的理解,如果有沒有講明白的地方,可以參考知乎上的講解。
比如說我們知道一個人有三個精神狀態,比如說正常、冷、頭暈。並且我們知道身體狀態轉換概率

狀態 健康 發燒
健康 0.7 0.3
發燒 0.4 0.6

以及精神狀態和身體狀態的概率分布

狀態 正常 頭暈
健康 0.5 0.4 0.1
發燒 0.1 0.3 0.6

我們已經知道一個人的精神狀態是正常、冷、頭暈。我們想要知道這個人三天的身體狀態。利用維特比算法就可以很好的預測。

看起來很神奇?

維特比算法完全基於普通的概率論知識,下面結合Python實現來闡述一下維特比算法究竟是什么。
首先可以將概率矩陣借助Numpy輸入程序

tran = np.array([[0.7, 0.3],
                 [0.4, 0.6]])
laun = np.array([[0.5, 0.4, 0.1],
                 [0.1, 0.3, 0.6]])
init = np.array([0.6,0.4 ])
look = np.array([0, 1,2])  # 觀測序列
kind = ['健康', '發燒']

上面的init矩陣是健康狀態的初始概率,0.6代表初始狀態有0.6的概率為健康,0.4代表初始狀態有0.4的概率為發燒。
我們已經知道第一天的精神狀態是正常,那么健康的概率就是P(正常|健康)*P(健康|初始狀態)。發燒的概率也是同理。
因此我們可以利用下面的代碼實現初始健康狀態的計算

dp = np.array([a * b for a, b in zip(init, laun[:, look[0]])])
print(max(dp))
print('第1次' + kind[np.where(dp==max(dp))[0][0]])

上面算出來的概率並不是代表初始狀態下健康的概率,初始狀態下健康的概率我們在問題初始時就已經知道,不需要計算。這里計算的是,在初始狀態下,究竟是健康更可能推出來正常,還是發燒更能推出來健康。從這個角度來思考問題,可以發現這樣也可以決定這個人的第一天的健康狀態究竟是什么。
后面的問題也是采用相同的辦法來處理,比如對於第二天來說,精神狀態是冷,也就是狀態1。這里我們可以計算概率為P(冷|健康)P(健康|上一天健康)P(上一天健康)
相應的python代碼如下:

for i in range(1,3):
    temp = np.copy(dp)
    for j in range(2):
        dp[j] = max([a * b for a, b in zip(temp, tran[:,j])])*laun[j,look[i]]
    print('第{}次'.format(i+1) + kind[np.where(dp==max(dp))[0][0]])

根據上述代碼,我們就可以計算出每天最有可能的健康狀態。

總結

維特比算法利用概率知識,通過已知的觀察序列情況,通過推算在某種標注序列的情況下發生觀察序列的概率,然后求出最有可能的標注序列情況,從而解決標注序列推測的問題。


免責聲明!

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



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