Viterbi-Algorithm(維特比)算法


CSDN博客:皮乾東 
知乎:Htrying 
微博:Htring的微博 
微信公眾號:自然語言處理愛好者(ID:NLP_lover) 
文章來自:《數學之美》
Viterbi-Algorithm算法
維特比算法是一個特殊但應用最廣的動態規划算法。利用動態規划,可以解決任何一個圖中的最短路徑問題。而維特比算法是針對一個特殊的圖-籬笆網了(Lattice)的有向圖最短路徑問題而提出來的。它之所以重要,是因為凡是使用隱馬爾科夫模型描述的問題都可以用它解碼,包括當前的數字通信、語音識別、機器翻譯、拼音轉漢字、分詞等。
背景
假定用戶(盲打時)輸入的拼音時y1,y2,...,yNy1,y2,...,yN,對應的漢字是x1,x2,...,xNx1,x2,...,xN(雖然真正的輸入法產品都是以詞作為輸入單位的,為了便於說明問題及簡單起見,以字為單位來解釋維特比算法),那么根據當前介紹的工具:
x1,x2,...,xN=ArgMaxx∈XP(x1,x2,...,xN|y1,y2,...,yN)=ArgMaxx∈X∏Ni=1P(yi|xi)P(xi|xi−1)x1,x2,...,xN=ArgMaxx∈X⁡P(x1,x2,...,xN|y1,y2,...,yN)=ArgMaxx∈X⁡∏i=1NP(yi|xi)P(xi|xi−1) (1)
輸入的可見序列為y1,y2,...,yNy1,y2,...,yN,而產生他們的隱含序列是x1,x2,...,xNx1,x2,...,xN。可以用下圖描述這樣一個過程: 
這是一個相對簡單的隱馬爾科夫鏈,沒用狀態跳躍,也沒有自環。P(xi|xi−1)P(xi|xi−1)是狀態之間的轉移概率,P(yi|xi)P(yi|xi)是每個狀態的產生概率。現在,這個馬爾科夫鏈的每個狀態的輸出是固定,但是每個狀態的值可以變化。比如輸出讀音”zhong”的字可以是”中”、”種“等多個字。我們不妨抽象一點,用符號xijxij表示狀態xixi的第jj個可能的值。如果把每個狀態按照不同的值展開,就得到下面這個籬笆網絡(Lattice):
 
在上圖中,每個狀態有3個或4個值,當然時間中它們可以有任意個值。
那么從第一個狀態到最后一個狀態的任何一條路徑(Path)都可能產生我們觀察到的輸出序列Y。當然這些路徑的可能性不一樣,而我們要做的就是找到最可能的這條路徑,並不是很難。但麻煩的是這樣的路徑組合數非常多,會讓序列狀態數的增長呈指數式增長。漢語中每個無聲調的拼音對應13個左右的國標漢字,假定句子長為10個字,那么這個組合數為1310∼5×10141310∼5×1014這個計算量就相當的大了。因此,需要一個最好能和狀態數目成正比的算法,而這個算法在1967年首次提出,即維特比算法。
主要內容
維特比算法基礎
1.如果概率最大的路徑P(或者說是最短路徑)經過某個點,比如下圖中的x22x22,那么這條路徑上從起始點S到x22x22的這一段路徑Q,一定是S到x22x22之間的最短路徑。否則,用S到x22x22的最短路徑R代替Q,便構成了一條比P更短的路徑,這就和之前的假設矛盾了。
2.從S到E路徑必定經過第i時刻的某個狀態,假定第i時刻有k個狀態,那么如果記錄了從S到i個狀態的所有k個節點(所有時刻的所有狀態)的最短路徑,最終的最短路徑必經過其中的一條。這樣,在任何時刻,只要考慮非常有限條候選路徑即可。
3.結合以上兩點,假定當我們從狀態i進入到i+1時,從S到i上各個節點的最短路徑已經找到,並且記錄到這些節點上,那么在計算出從起點S到第i+1狀態的某個結點的最短路徑時,只要考慮從S到前一個狀態i所有的k個節點的最短路徑,以及從這k個節點到xi+1,jxi+1,j的距離即可。 
維特比算法
1.從點S觸發,對於第一個狀態x1x1的各個節點,不妨假定有n1n1個,計算出S到它們的距離d(S,x1i)d(S,x1i),這里的x1ix1i表示的是狀態1的節點,因為只有一步,所以這些都是S到它們各自的最短路徑。
2.(算法的關鍵)對於第二個狀態x2x2的所有節點,要計算S到它們的最短距離,我們知道,對於特定的節點x2ix2i,可以經過狀態1的n1n1中的任何一個節點x1ix1i,當然,對應的路徑長度就是d(S,x2i)=d(S,x1j)+d(x1j,x2i)d(S,x2i)=d(S,x1j)+d(x1j,x2i)。由於j有n1n1種可能性,我們要一一計算,然后找出最小值。即
d(S,x2i)=minI=1,n1d(S,x1j)+d(x1j,x2i)d(S,x2i)=minI=1,n1d(S,x1j)+d(x1j,x2i)
這樣對於第二個狀態的每個節點,需要進行n1n1次乘法計算。假定這個狀態有n2n2個節點,把S這些節點的距離都計算一遍,就有O(n1⋅n2)O(n1⋅n2)次計算。
接下來,類似地按照上述方法從第二個狀態走到第三個狀態,一直走到最好一個狀態,就得到了整個網格從頭到尾的最短路徑。每一步計算的復雜度都和相鄰兩個狀態SiSi和Si+1Si+1各自的節點數目ni,ni+1ni,ni+1的乘積成正比,即O(ni⋅ni+1)O(ni⋅ni+1)。如果假定這個在這個隱含馬爾可夫鏈中節點最多的狀態有D個節點,也就是說整個網格的寬度為D,那么任何一步的復雜度不超過O(D2)O(D2),由於網格長度是N,所以整個維特比算法的復雜度是O(N⋅D2)O(N⋅D2).
回到最初的問題中,計算量基本上是13×13×10=1690≈10313×13×10=1690≈103,這樣就降低了很大的計算量。
總的來說,無論在語音識別、輸入法打字中,輸入都是按照流(Stream)的方式進行的,只要處理每個狀態的時間比講話,或者打字速度,那么無論輸入有多長,解碼過程永遠就是實時的。 
--------------------- 
作者:AIAS編程有道 
來源:CSDN 
原文:https://blog.csdn.net/meiqi0538/article/details/80960128 
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!


免責聲明!

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



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