當前位置: 首頁>>算法&結構>>正文


維特比算法(Viterbi Algorithm)

本分摘錄翻譯自wikipedia Viterbi algorithm
維特比算法(Viterbi algorithm)是一種動態規劃算法,它用於尋找最可能產生觀測到的事件的序列,這個序列是隱含狀態序列,也叫維特比路徑(Viterbi path)。最典型的應用場景是馬爾科夫信息源上下文和隱馬爾科夫模型(HMM)。
該算法廣泛應用於通信技術中的解卷積碼,例如:CDMA、GSM數字蜂窩網、撥號調製解調器、衛星、深空通信以及802.11無線網。當前,該算法也經常用於語音識別、語音合成、說話人分割(diarization, 姑且這麽翻譯,它的意思是將同一段語音中不同人的話語歸為一類)[1] 、關鍵詞識別、計算語言學、生物信息學中。例如,在語音轉文本中(語音識別),聲音信號作為觀察到的事件序列,而文本序列作為聲音信號的隱含原因。對於給定的聲音信號,維特比算法找出最可能的文本序列。

曆史(History)

維特比算法是以Andrew Viterbi 的名字來命名的,他在1967年提出了這個算法,作為含噪聲的數字通信鏈路中卷積碼的解碼方法。[2] 不過,該算法具有multiple invention的曆史——至少有7個獨立的發明者,包括:Viterbi, Needleman and Wunsch, and Wagner and Fischer.[3] “維特比(路徑,算法)”已經成為使用動態規劃解決概率最大化問題的標準術語。[3] 例如,在statistical parsing中,對於一個單詞序列,動態規劃算法能找到最可能上下文無關的語法分析結果,通常稱之為“維特比分析”。[4][5][6]

算法(Algorithm)

假設在一個隱馬爾科模型(HMM)中,狀態空間為S, 狀態i的初始概率為πi, 狀態i到j的轉移概率為ai,j。觀察到的值為y1, y2, …, yT 。產生觀察值的最可能狀態序列是x1, x2, …, xT通過下麵的迭代關係給出:[7] gif.latex其中Pt,k是以k為最終狀態的前t個觀察值對應的最可能的狀態序列的概率, P(yt|k)是在隱含狀態k對應觀察值yt生成概率。維特比路徑可以通過保存等式(2)中用到的x的反向指針得到。
根據公式(2),維特比算法計算中需要考察每個狀態的|S|個值和前一狀態的|S|個值從而計算當前最佳,即每個狀態需要O(|S|2)次計算,總共的狀態數量為T,所以總的時間複雜度為: O(T × |S|2)。

實例(Example)

以鄉村中原始的小診所為例。村民隻有兩種簡單的屬性:健康或者發燒。他們隻能通過診所的醫生知道自己是否發燒。聰明的醫生通過詢問病人感覺如何來診斷是否發燒;村民的回答是:正常、頭暈、寒冷三者之一。
假設某病人每天都來診所告訴醫生她感覺如何。醫生認為病人的健康狀況是一個離散的馬爾科夫鏈(Markov chain)。有兩種狀態“Healthy”和”Fever”,但是醫生沒法直接觀察到,也就是說這兩個狀態對醫生來說是隱藏(hidden)的。每天,病人會基於自身健康狀況,以某個幾率告訴醫生他的感覺:可能是”normal”、”cold”或”dizzy”三者之一,這些事觀察值。這裏的整個係統可以看做是隱馬爾科夫模型(HMM)。
醫生了解村民通常的健康狀況,以及是否有發熱情況下的症狀。也就是說,HMM的參數是已知的。這可以表示為下麵的Python變成語言:

//初始狀態
states = ('Healthy', 'Fever')

//觀察值
observations = ('normal', 'cold', 'dizzy')
 
//初始概率
start_probability = {'Healthy': 0.6, 'Fever': 0.4}
 
//轉移概率
transition_probability = {
   'Healthy' : {'Healthy': 0.7, 'Fever': 0.3},
   'Fever' : {'Healthy': 0.4, 'Fever': 0.6}
   }

//生成概率
emission_probability = {
   'Healthy' : {'normal': 0.5, 'cold': 0.4, 'dizzy': 0.1},
   'Fever' : {'normal': 0.1, 'cold': 0.3, 'dizzy': 0.6}
   }

這段代碼中,start_probability表示病人第一次去診所時醫生認為他屬於HMM某個狀態的經驗知識(醫生所知道的隻有病人更傾向於健康,0.6的概率為Healthy, 0.4的概率為Fever)。transition_probability表示馬爾科夫鏈中的健康情況轉變。在上述例子中,如果病人今天是Healthy那麽明天有30%的幾率是Fever. emission_probability表示的是在不同的健康狀況下不同感覺的可能性,這個可以稱為生成概率,也可以叫做狀態發射概率。比如:如果他是Healthy的,那麽感覺是normal的概率是50%;如果是Fever, 感覺dizzy的概率是60%。

400px-An_example_of_HMM

某病人連續三天就診,醫生了解到第一天她感覺是normal, 第二天是cold, 第三天是dizzy。醫生的疑問是:最能解釋對病人的這些觀察值的健康狀態序列是什麽?這個問題可以通過維特比算法來回答。

def viterbi(obs, states, start_p, trans_p, emit_p):
    V = [{}]
    path = {}
 
    # Initialize base cases (t == 0)
    for y in states:
        V[0][y] = start_p[y] * emit_p[y][obs[0]]
        path[y] = [y]
 
    # Run Viterbi for t > 0
    for t in range(1, len(obs)):
        V.append({})
        newpath = {}
 
        for y in states:
            (prob, state) = max((V[t-1][y0] * trans_p[y0][y] * emit_p[y][obs[t]], y0) for y0 in states)
            V[t][y] = prob
            newpath[y] = path[state] + [y]
 
        # Don't need to remember the old paths
        path = newpath
    n = 0           # if only one element is observed max is sought in the initialization values
    if len(obs) != 1:
        n = t
    print_dptable(V)
    (prob, state) = max((V[n][y], y) for y in states)
    return (prob, path[state])
 
# Don't study this, it just prints a table of the steps.
def print_dptable(V):
    s = "    " + " ".join(("%7d" % i) for i in range(len(V))) + "\n"
    for y in V[0]:
        s += "%.5s: " % y
        s += " ".join("%.7s" % ("%f" % v[y]) for v in V)
        s += "\n"
    print(s)

viterbi函數有如下參數: obs 是觀察值序列,例如[‘normal’, ‘cold’, ‘dizzy’]; states是隱含的狀態;start_p是初始概率;trans_p是轉移概率;emit_p是發射概率(生成概率)。為了代碼的簡介性,我們假設obs是非空的並且trans_p[i][j]和emit_p[i][j]對所有的狀態i,j都有值。
運行上述函數的代碼如下:


def example(): 
       return viterbi(observations, states, start_probability, transition_probability, emission_probability) 
print(example()) 

 

程序顯示最可能產生觀察值[‘normal’, ‘cold’, dizzy’]的狀態是[‘Healthy’, ‘Healthy’, ‘Fever’].也就是說,給定觀察到的活動,病人最可能在第一天和第二天都是Healthy的,她第一天感覺正常第二天感覺冷,第三天的時候就確定開始發熱了。
維特比算法的操作可以通過籬笆網絡圖 trellis diagram來可視化。維特比路徑本質上就是通過籬笆網絡的最短路徑。診所的例子對應的籬笆網絡如下;對應的維特比路徑被加粗顯示。(注,Day3第一幀右下角的概率應該是P(‘dizzy’|newstat))

Animation of the trellis diagram for the Viterbi algorithm. After Day 3, the most likely path is ['Healthy', 'Healthy', 'Fever']

當實現維特比算法的時候,需要注意的是很多語言使用浮點運算,由於p很小,這會導致運算結果的溢出(underflow)。避免這個問題的常用技術是使用概率的對數運算(logarithm of the probabilities )。一旦算法運行完畢,可以通過合適的指數運算來取得概率的準確值。

擴展(Extensions)

有一種維特比算法的泛化算法稱為max-sum algorithm(也叫max-product algorithm), 在大量圖模型(例如貝葉斯網絡(Bayesian networks), 馬爾科夫隨機場(Markov random fields) 和 條件隨機場( conditional random fields )). )中,該算法可用於尋找全部或者部分隱含變量( latent variables )的值。
使用迭代維特比解碼(iterative Viterbi decoding)算法,對於給定的HMM我們可以找到觀察值子序列的最佳匹配。
另外一種算法是最近提出的Lazy Viterbi algorithm,該算法在實踐中比原來的維特比算法有更好的性能,因為該算隻在實際需要的時候才進行節點擴展。

偽代碼(Pseudocode)

給定觀察值空間O = {o1, o2, …, oN};狀態空間S = {s1, s2, …, sK}, 觀察值序列Y={y1, y2, …, yT};轉移矩陣A(K×K), 其中Aij存儲狀態si到狀態sj的轉移概率;生成矩陣B(K×N), 其中Bij存儲從狀態si生成觀察值oj的概率;大小為K的初始概率數組π, 其中πi存儲x1 = Si的概率。設X = {x1, x2, …, xT}是生成觀察值Y={y1, y2, …, yT}的狀態序列。
在這個動態規劃問題中,我們構造兩個二維表T1, T2(大小均為K×T)。T1 的元存概率,T2的元素存路徑。基於上述定義的偽代碼如下:3

參閱(See also)

Notes

  1. Xavier Anguera et Al, “Speaker Diarization: A Review of Recent Research”, retrieved 19. August 2010, IEEE TASLP
  2. 29 Apr 2005, G. David Forney Jr: The Viterbi Algorithm: A Personal History
  3. Daniel Jurafsky; James H. Martin. Speech and Language Processing. Pearson Education International. p. 246.
  4. Schmid, Helmut (2004). Efficient parsing of highly ambiguous context-free grammars with bit vectors (PDF). Proc. 20th Int’l Conf. on Computational Linguistics (COLING). doi:10.3115/1220355.1220379. edit
  5. Klein, Dan; Manning, Christopher D. (2003). A* parsing: fast exact Viterbi parse selection (PDF). Proc. 2003 Conf. of the North American Chapter of the Association for Computational Linguistics on Human Language Technology (NAACL). pp. 40–47. doi:10.3115/1073445.1073461. edit
  6. Stanke, M.; Keller, O.; Gunduz, I.; Hayes, A.; Waack, S.; Morgenstern, B. (2006). “AUGUSTUS: Ab initio prediction of alternative transcripts”. Nucleic Acids Research 34: W435. doi:10.1093/nar/gkl200. edit
  7. Xing E, slide 11
  8. Qi Wang; Lei Wei; Rodney A. Kennedy (2002). “Iterative Viterbi Decoding, Trellis Shaping,and Multilevel Structure for High-Rate Parity-Concatenated TCM”. IEEE Transactions on Communications 50: 48–55. doi:10.1109/26.975743.
  1. A fast maximum-likelihood decoder for convolutional codes (PDF). Vehicular Technology Conference. December 2002. pp. 371–375. doi:10.1109/VETECF.2002.1040367.

References

實現(Implementations)

外部鏈接(External links)

本文由《純淨天空》出品。文章地址: https://vimsky.com/zh-tw/article/863.html,未經允許,請勿轉載。