基於隱馬爾科夫(HMM)模型的中文分詞實踐

一、中文分詞問題

中文分詞是自然語言處理中一個最基礎的問題,就是一段話怎麼切分。比如:

今天的天氣怎麼樣

可以按如下方式分詞

今天天氣怎麼樣

這樣一個任務交給機器自動切分,很容易想到基於詞典的匹配,但是匹配會面臨如下問題:

  1. 詞典需要人工不停錄入,否則沒法識別新詞。這也就是機器學習中一直強調的泛化能力;

  2. 不同場景下分詞方式不一樣,比如:

南京市長是個好同志

而下面這句話就不能把「市長」分到一起了:

南京市長江大橋

今天要介紹一種基於統計的分詞方式。首先我們轉換下思維,把分詞問題做個轉換:分詞問題就是對句子中的每個字打標註,標註要麼是一個詞的開始(B),要麼是一個詞的中間位置(M),要麼是一個詞的結束位置(E),還有單個字的詞,用S表示。比如下面的句子可以這樣標註:

我S想S去S烏B魯M木M齊E

思維的轉換很重要,下面對中文分詞進行形式化描述:

設觀察集合為mathbf O={o_1,o_2,...,o_l};狀態集合為mathbf S={s_1,s_2,...,s_k}

問題:已知輸入的觀察序列為:mathbf X=x_1x_2...x_n; x_i in {mathbf O}.

求對應的狀態序列:mathbf Y=y_1y_2...y_n; y_i in mathbf S

可以直接進行求解

P(Y|X)=frac {P(X|Y)P(Y)} {P(X)}

二、隱馬爾科夫假設

遍歷狀態Y的所有可能性,條件概率最大的則為對應的狀態序列。

由於P(X)都一樣,而我們只關心哪個最大,所以只需求$P(X|Y)P(Y)$即可。

下面需要引入馬爾科夫假設了:

假設1: 齊次馬爾科夫假設:狀態序列只和前一個狀態有關係,與其他狀態及觀察值無關,即:

P(y_i|x_1,y_1,x_2,y_2,...,x_{i-1},y_{i-1})=P(y_i|y_{i-1})

假設2: 觀察獨立性假設。即假設任意時刻的觀察值僅與當前的狀態值有關,即:

P(x_i|x_1,y_1,x_2,y_2,...,x_{i-1},y_{i_1},y_i)=P(x_i|y_i)

有了以上假設就容易計算$P(X|Y)P(Y)$了

displaystyle P(X|Y)P(Y)=pi(y_1)prod_2^n P(y_i|y_{i-1})P(x_i|y_i)

其中pi(y_1)表示第一個狀態為y_1的概率。一般我們會對上式取對數,因為取對數不會改變大小關係,但可以簡化計算:

displaystyle log{P(X|Y)P(Y)}=pi(y_1) + sum_2^n {log{P(y_i|y_{i-1})} + log{P(x_i|y_i)}}

這樣直接計算時間複雜度是:

n*|S|^n

這個指數級複雜度顯然太高了,所以有以下優化的演算法。

三、維特比(Viterbi)演算法

如上圖所示,每一列可以看做一簇地點,初始時你可以選擇從第一列的任意一個點出發,每個點會給不同的初始金幣值。然後沿著邊到最後一列任何一個定點上,每經過一條邊會獲取相應的金幣值,問最後能獲取的最大金幣值。

其實這個問題和剛才求條件概率最大值是同一個問題。可以採用動態規劃的方法來解決:

init_gold[i]就是第一列第i個頂點出發的初始值。設max_gold[i][j]表示到達第i列第j個頂點時能獲得的最大金幣值,gold[i][j][k]表示走第i列第j個定點到第i+1列第k個頂點的邊能獲得的金幣值。則有如下遞推公式:

max\_gold[i+1][j] = max(max\_gold[i][0]+gold[i][0][j], max\_gold[i][1]+gold[i][1][j],...,max_gold[i][n]+gold[i][n][j])

從上面的公式計算最大值,時間複雜度降為:

n*|S|^2

求得最大值後,反推即可知道每列走的是哪個頂點,也就是分詞中的標註序列。

四、分詞實踐

基本上搞明白上面的原理後動手實現就很容易了,需要說明有以下幾點:

  • 訓練集。 訓練數據可以從這裡獲取,關於這個數據集的介紹可以看這裡

  • 平滑處理。對於沒有在訓練集中出現的字,或者轉移概率為零的情況,可以給個無限小的數,比如-3.14e+100

我用python簡單實現了下,可以在github看到。

五、分詞效果的評測

模型訓練好了之後就需要對模型做評測了,那麼如何評測模型呢?

因為分詞方案並不是唯一的,每個人都會有自己的見解。所以有了gold方案,就是找一個測試集,然後給出相應的分詞方案作為標準答案。假設標準答案分出詞的個數是N,你的模型給出結果和標準答案相同的分詞個數是c,你的模型給出的其他單詞個數是e,也就是分錯的個數,那麼:

準確率(Precision):P=frac c {c+e}

召回率(Recall):R=frac c N

F1值:F=frac {2*P*R} {P+R}

以上值當然越大越好,但是準確率和召回率會有一定製約關係,要想兩者都大,是一件比較困難的事情。當然,還有個指標:

錯誤率:ER=frac e N

六、參考資料

  1. 李航,機器學習方法,第十一章,清華大學出版社
  2. 隱馬爾可夫模型及其應用(1)簡介&解碼問題 | bitJoy

  3. 編碼無悔 / Intent & Focused

推薦閱讀:

Learning Explanatory Rules from Noisy Data 閱讀筆記4
NNLM最新論文調研-1-《Character-Aware Neural Language Models》
tf.nn.nce_loss 來自一篇古老的文章
AI+互聯網金融--入職半年總結
【機器閱讀理解】Fast and Accurate Reading Comprehension by Combining Self-Attention and Convolution

TAG:機器學習 | 自然語言處理 |