1. 程式人生 > 實用技巧 >詞性標註維特比演算法介紹

詞性標註維特比演算法介紹

對求解詞性標註過程中使用的維特比演算法進行介紹。

籬笆網路(Lattice)的最短路徑問題

已知下圖的籬笆網路,每個節點間的數字表示相鄰節點間的距離,求從A走到E的最短路徑是那一條。

graph LR A[A]--6-->B1[B1] A[A]--7-->B2[B2] A[A]--5-->B3[B3] B1--5-->C1[C1] B1--6-->C2[C2] B1--9-->C3[C3] B2--4-->C1[C1] B2--3-->C2[C2] B2--7-->C3[C3] B3--4-->C1[C1] B3--6-->C2[C2] B3--6-->C3[C3] C1--7-->D1[D1] C1--8-->D2[D2] C1--3-->D3[D3] C2--5-->D1[D1] C2--4-->D2[D2] C2--3-->D3[D3] C3--5-->D1[D1] C3--7-->D2[D2] C3--6-->D3[D3] D1--4-->E D2--8-->E D3--5-->E

針對上述籬笆網路(Lattic),如何求出A到E的最短路徑?

一般情況下,我們可以通過窮舉法,一條一條路徑進行計算,然後通過比較獲取最短的路徑,基於上述的圖我們知道需要 \(4*3*3*3\)次計算,其中4為每一條路徑的計算次數,也就是從A到E需要計算4次加法獲取路徑距離,3個3是B、C、D三層每層是3個節點,每次每層取一個節點組成一條路徑。這種方法適合於很少層數以及每層很少節點的籬笆網路,若是一個籬笆網路有12層,每層13個節點,使用窮舉法則需要\(12*13^{13}\)次計算,這麼大的計算量即是是超級計算機也需要很久才能計算出來。

那麼針對上述籬笆網路的計算是否有很好的計算方式呢?我們採用動態規劃的思想將問題進行拆分看。思路分析如下:

  1. 第一步,我們反向思考此問題,如果我想要從A到E節點,則必須經過D[D1、D2、D3]層的節點,那麼要是我知道從A到D層每個節點的最短路徑,再加上D層各節點到E節點的距離,則可以計算出從A到E的最短路徑;
  2. 確定了從D到E的最短路徑後,我們則面臨新的問題,就是從A到D的最短路徑的計算問題,撇開最後一個E節點不考慮,將D認為是最後一層的節點,考慮D1的最短路徑,此時是不是將該問題同樣定位到我們第一步的問題,類似的採用此方法計算即可;
  3. 依次類推,求C層節點的最短路徑;而後求B層最短路徑,到了B層我們知道已經是最後一步的計算了,因為從A到B我們已經知道了距離,直接計算即可;
  4. 基於上述步驟,我們反向即可計算最短路徑問題了。

我們基於上述的步驟,我們在每一層M都僅需要考慮這樣一個問題:

為了到下一層的某個確定的點Nj,我們需要從當前層哪一個Mi出發?

一旦確定了從哪一個Mi出發,其他的節點則不在後續計算的考慮範圍內了。就比如我們找到了到C1需要從B3走,那就不考慮其他到C1的路徑了,這樣就大大減少了需要計算的路徑總數。

經過上述分析,我們從新考慮其計算複雜度。我們上述計算過程知道,每一步計算的複雜度都和相鄰兩個狀態的節點數目有關,比如C層有3個節點(狀態),B層有3個節點,從B層到C層計算最短路徑需要3*3次,也就是各個狀態節點數的乘積,如果整個籬笆網路的某個狀態的最大節點數為N,則每一步計算的最大複雜度為N*N次,總共有多少層則需要在乘以層數得到最終的計算複雜度。

維特比(vertibe)演算法

基於上述籬笆網路的說明,給出維特比演算法:

  • 從點S出發,對於第一個狀態 \(x_1\)的各個節點,不妨假設有\(n_1\)個,計算出S到它們的距離\(d(S,x_{1i})\),其中\(x_{1i}\)代表任意狀態1的節點。因為只有一步,所以這些距離都是S到它們各自的最短距離;
  • 對於第二個狀態 \(x_2\)的各個節點,要計算S到它們的最短路徑。我們知道,對於特定的節點\(x_{2i}\),從S到它的路徑可以經過狀態1的\(n_1\)中任何一個節點\(x_{1i}\),當然,對應的路徑長度就是\(d(S,x_{2i})=d(S,x_{1j})+d(x_{1j}, x_{2i})\),由於\(j\)\(n_1\)中可能性,我們要一一計算,然後找到最小值,即是\(d(S,x_{2i})=min_{j=1,n_1}d(S,x_{1j})+d(x_{1j}, x_{2i})\)。這樣對於第二個狀態的每個節點,需要\(n_1\)次乘法計算,假定這個狀態有\(n_2\)個節點,把從S到這些節點的距離都計算一遍,就有\(O(n_1*n_2)\)次計算。
  • 接下來,類似的按照上述方法從第二個狀態走到第三個狀態,一直走到最後一個狀態,記得到了整個網路從頭到尾的最短路徑。每一步計算的複雜度都和兩個狀態 \(s_i\)\(s_{i+1}\)各自的節點數目\(n_1\)\(n_2\)的乘積成正比,即\(O(n_1*n_2)\)。如果假設在這個隱含馬爾科夫鏈中節點最多的狀態有D個節點,也就是說整個籬笆網路的寬度為D,那麼任何一步的複雜度不超過\(O(D^2)\),由於網路長度為N,所以整個維特比演算法的複雜度為\(O(N*D^2)\)

上述即是對維特比演算法的相關介紹,文章參考了吳軍博士的《數學之美》維特比演算法介紹章節,及小白給小白詳解維特比演算法(一)