現實生活中有這樣一類隨機現象,在已知如今狀況的條件下,將來時刻的狀況只與如今有關,而與遙遠的過去並沒有直接關係。算法
好比天氣預測,若是咱們知道「晴天,多雲,雨天」之間的轉換機率,那麼若是今天是晴天,咱們就能夠推斷出明天是各類天氣的機率,接着後天的天氣能夠由明天的進行計算。這類問題能夠用 Markov 模型來描述。數組
進一步,若是咱們並不知道今天的天氣屬於什麼情況,咱們只知道今明後三天的水藻的乾燥溼潤狀態,由於水藻的狀態和天氣有關,咱們想要經過水藻來推測這三天的真正的天氣會是什麼,這個時候就用 Hidden Markov 模型來描述。學習
HMM 模型的本質是從觀察的參數中獲取隱含的參數信息,而且先後之間的特徵會存在部分的依賴影響。spa
根據可觀察狀態的序列找到一個最可能的隱藏狀態序列翻譯
中文分詞,就是給一個漢語句子做爲輸入,以「BEMS」組成的序列串做爲輸出,而後再進行切詞,進而獲得輸入句子的劃分。其中,B表明該字是詞語中的起始字,M表明是詞語中的中間字,E表明是詞語中的結束字,S則表明是單字成詞。code
例如:給個句子orm
小明碩士畢業於中國科學院計算所
獲得BEMS組成的序列爲遞歸
BEBEBMEBEBMEBES
由於句尾只多是E或者S,因此獲得切詞方式爲it
BE/BE/BME/BE/BME/BE/S
進而獲得中文句子的切詞方式爲io
小明/碩士/畢業於/中國/科學院/計算/所
這是個HMM問題,由於你想要獲得的是每一個字的位置,可是看到的只是這些漢字,須要經過漢字來推出每一個字在詞語中的位置,而且每一個字屬於什麼狀態還和它以前的字有關。
此時,咱們須要根據可觀察狀態的序列找到一個最可能的隱藏狀態序列。
五元組
經過上面的例子,咱們能夠知道 HMM 有如下5個要素。
觀測序列-O:小明碩士畢業於中國科學院計算所
狀態序列-S:BEBEBMEBEBMEBES
初始狀態機率向量-π:句子的第一個字屬於{B,E,M,S}這四種狀態的機率
狀態轉移機率矩陣-A:若是前一個字位置是B,那麼後一個字位置爲BEMS的機率各是多少
觀測機率矩陣-B:在狀態B的條件下,觀察值爲耀的機率,取對數後是-10.460
備註:示例數值是對機率值取對數以後的結果,爲了將機率相乘的計算變成對數相加,其中-3.14e+100做爲負無窮,也就是對應的機率值是0
三類問題
當經過五元組中某些已知條件來求未知時,就獲得HMM的三類問題:
中文分詞這個例子屬於第二個問題,即解碼問題。
咱們但願找到 s_1,s_2,s_3,... 使 P (s_1,s_2,s_3,...|o_1,o_2,o_3....) 達到最大。
意思是,當咱們觀測到語音信號 o_1,o_2,o_3,... 時,咱們要根據這組信號推測出發送的句子 s_1,s_2,s_3,....,顯然,咱們應該在全部可能的句子中找最有可能性的一個。
兩個假設
利用貝葉斯公式獲得:
這裏須要用到兩個假設來進一步簡化上述公式
有限歷史性假設: si 只由 si-1 決定
獨立輸出假設:第 i 時刻的接收信號 oi 只由發送信號 si 決定
有了上面的假設,就能夠利用算法 Viterbi 找出目標機率的最大值。
根據動態規劃原理,最優路徑具備這樣的特性:若是最優路徑從結點 i_{t}^* 到終點 i_{T}^,那麼這兩點之間的全部可能的部分路徑必須是最優的。
依據這一原理,咱們只需從時刻 t=1 開始,遞推地計算在時刻 t 狀態爲 i 的各條部分路徑的最大機率,直至獲得時刻 t=T 狀態爲 i 的各條路徑的最大機率 P^,最優路徑的終結點 i_{T}^* 也同時獲得。以後,爲了找出最優路徑的各個結點,從終結點 i_{T}^* 開始,由後向前逐步求得結點 i_{T-1}*...,i_{1},進而獲得最優路徑 I^=i_{1}*...,i_{T}*,這就是維特比算法.
舉個栗子:
觀測序列 O=(紅,白,紅),想要求狀態序列S。
須要定義兩個變量:
1.初始化
t=1 時的紅,分別是在狀態 1,2,3 的條件下觀察得來的機率計算以下:
此時 path 的第一列全是 0.
2.遞歸
t=2 時的白,若是此時是在 1 的條件下觀察得來的話,先計算此時狀態最多是由前一時刻的哪一個狀態轉換而來的,取這個最大值,再乘以 1 條件下觀測到 白 的機率,同時記錄 path矩陣:以下圖 weight[0][1]=0.028,此值來源於前一時刻狀態是3,因此,
3.終止
在 t=3 時的最大機率 P^=0.0147,相應的最優路徑的終點是 i_3^=3.
4.回溯
由最優路徑的終點 3 開始,向前找到以前時刻的最優勢:
在 t=2 時,因 i_3^=3,狀態 3 的最大機率 P=0.0147,來源於狀態 3,因此 i_2^=3.
在 t=1 時,因 i_2^=3,狀態 3 的最大機率 P=0.042,來源於狀態 3,因此 i_1^=3.
最後獲得最優路徑爲 I*=(i_{1},i_{2}^,i_{3}^*)=(3,3,3)
根據上面講的 HMM 和 Viterbi,接下來對中文分詞這個問題,構造五元組並用算法進行求解。
通過這個算法後,會獲得兩個矩陣 weight 和 path:
二維數組 weight[4][15],4是狀態數(0:B,1:E,2:M,3:S),15是輸入句子的字數。好比 weight[0][2] 表明 狀態B的條件下,出現'碩'這個字的可能性。
二維數組 path[4][15],4是狀態數(0:B,1:E,2:M,3:S),15是輸入句子的字數。好比 path[0][2] 表明 weight[0][2]取到最大時,前一個字的狀態,好比 path[0][2] = 1, 則表明 weight[0][2]取到最大時,前一個字(也就是明)的狀態是E。記錄前一個字的狀態是爲了使用viterbi算法計算完整個 weight[4][15] 以後,能對輸入句子從右向左地回溯回來,找出對應的狀態序列。
使用 InitStatus 和 EmitProbMatrix 對 weight 二維數組進行初始化。
由 EmitProbMatrix 能夠得出
因此能夠初始化 weight[i][0] 的值以下:
注意上式計算的時候是相加而不是相乘,由於以前取過對數的緣由。
//遍歷句子,下標i從1開始是由於剛纔初始化的時候已經對0初始化結束了 for(size_t i = 1; i < 15; i++) { // 遍歷可能的狀態 for(size_t j = 0; j < 4; j++) { weight[j][i] = MIN_DOUBLE; path[j][i] = -1; //遍歷前一個字可能的狀態 for(size_t k = 0; k < 4; k++) { double tmp = weight[k][i-1] + _transProb[k][j] + _emitProb[j][sentence[i]]; if(tmp > weight[j][i]) // 找出最大的weight[j][i]值 { weight[j][i] = tmp; path[j][i] = k; } } } }
如此遍歷下來,weight[4][15]
和 path[4][15]
就都計算完畢。
邊界條件以下:
對於每一個句子,最後一個字的狀態只多是 E 或者 S,不多是 M 或者 B。
因此在本文的例子中咱們只須要比較 weight[1(E)][14]
和 weight[3(S)][14]
的大小便可。
在本例中:
weight[1][14] = -102.492;
weight[3][14] = -101.632;
因此 S > E,也就是對於路徑回溯的起點是 path[3][14]
。
進行回溯,獲得序列
SEBEMBEBEMBEBEB。
再進行倒序,獲得
BEBEBMEBEBMEBES
接着進行切詞獲得
BE/BE/BME/BE/BME/BE/S
最終就找到了分詞的方式
小明/碩士/畢業於/中國/科學院/計算/所
HMM不僅用於中文分詞,若是把 S 換成句子,O 換成語音信號,就變成了語音識別問題,若是把 S 換成中文,O 換成英文,就變成了翻譯問題,若是把 S 換成文字,O 換成圖像,就變成了文字識別問題,此外還有詞性標註等等問題。
對於上述每種問題,只要知道了五元組中的三個參數矩陣,就能夠應用 Viterbi 算法獲得結果。
原文:https://www.jianshu.com/p/f140c3a44ab6