文字挖掘的分詞原理

劉建平Pinard發表於2017-04-07

    在做文字挖掘的時候,首先要做的預處理就是分詞。英文單詞天然有空格隔開容易按照空格分詞,但是也有時候需要把多個單詞做為一個分詞,比如一些名詞如“New York”,需要做為一個詞看待。而中文由於沒有空格,分詞就是一個需要專門去解決的問題了。無論是英文還是中文,分詞的原理都是類似的,本文就對文字挖掘時的分詞原理做一個總結。

1. 分詞的基本原理

    現代分詞都是基於統計的分詞,而統計的樣本內容來自於一些標準的語料庫。假如有一個句子:“小明來到荔灣區”,我們期望語料庫統計後分詞的結果是:"小明/來到/荔灣/區",而不是“小明/來到/荔/灣區”。那麼如何做到這一點呢?

    從統計的角度,我們期望"小明/來到/荔灣/區"這個分詞後句子出現的概率要比“小明/來到/荔/灣區”大。如果用數學的語言來說說,如果有一個句子$S$,它有m種分詞選項如下:$$A_{11}A_{12}...A_{1n_1}$$$$A_{21}A_{22}...A_{2n_2}$$$$......  ......$$$$A_{m1}A_{m2}...A_{mn_m}$$

    其中下標$n_i$代表第$i$種分詞的詞個數。如果我們從中選擇了最優的第$r$種分詞方法,那麼這種分詞方法對應的統計分佈概率應該最大,即:$$r = \underbrace{arg\;max}_iP(A_{i1},A_{i2},...,A_{in_i}) $$

    但是我們的概率分佈$P(A_{i1},A_{i2},...,A_{in_i})$並不好求出來,因為它涉及到$n_i$個分詞的聯合分佈。在NLP中,為了簡化計算,我們通常使用馬爾科夫假設,即每一個分詞出現的概率僅僅和前一個分詞有關,即:$$P(A_{ij}|A_{i1},A_{i2},...,A_{i(j-1)}) = P(A_{ij}|A_{i(j-1)})$$

    在前面我們講MCMC取樣時,也用到了相同的假設來簡化模型複雜度。使用了馬爾科夫假設,則我們的聯合分佈就好求了,即:$$P(A_{i1},A_{i2},...,A_{in_i}) = P(A_{i1})P(A_{i2}|A_{i1})P(A_{i3}|A_{i2})...P(A_{in_i}|A_{i(n_i-1)})$$

    而通過我們的標準語料庫,我們可以近似的計算出所有的分詞之間的二元條件概率,比如任意兩個詞$w_1,w_2$,它們的條件概率分佈可以近似的表示為:$$P(w_2|w_1) = \frac{P(w_1,w_2)}{P(w_1)} \approx \frac{freq(w_1,w_2)}{freq(w_1)}$$$$P(w_1|w_2) = \frac{P(w_2,w_1)}{P(w_2)} \approx \frac{freq(w_1,w_2)}{freq(w_2)}$$

    其中$freq(w_1,w_2)$表示$w_1,w_2$在語料庫中相鄰一起出現的次數,而其中$freq(w_1),freq(w_2)$分別表示$w_1,w_2$在語料庫中出現的統計次數。

    利用語料庫建立的統計概率,對於一個新的句子,我們就可以通過計算各種分詞方法對應的聯合分佈概率,找到最大概率對應的分詞方法,即為最優分詞。

2. N元模型

    當然,你會說,只依賴於前一個詞太武斷了,我們能不能依賴於前兩個詞呢?即:$$P(A_{i1},A_{i2},...,A_{in_i}) = P(A_{i1})P(A_{i2}|A_{i1})P(A_{i3}|A_{i1},A_{i2})...P(A_{in_i}|A_{i(n_i-2)},A_{i(n_i-1)})$$

    這樣也是可以的,只不過這樣聯合分佈的計算量就大大增加了。我們一般稱只依賴於前一個詞的模型為二元模型(Bi-Gram model),而依賴於前兩個詞的模型為三元模型。以此類推,我們可以建立四元模型,五元模型,...一直到通用的$N$元模型。越往後,概率分佈的計算複雜度越高。當然演算法的原理是類似的。

    在實際應用中,$N$一般都較小,一般都小於4,主要原因是N元模型概率分佈的空間複雜度為$O(|V|^N)$,其中$|V|$為語料庫大小,而$N$為模型的元數,當$N$增大時,複雜度呈指數級的增長。

    $N$元模型的分詞方法雖然很好,但是要在實際中應用也有很多問題,首先,某些生僻詞,或者相鄰分詞聯合分佈在語料庫中沒有,概率為0。這種情況我們一般會使用拉普拉斯平滑,即給它一個較小的概率值,這個方法在樸素貝葉斯演算法原理小結也有講到。第二個問題是如果句子長,分詞有很多情況,計算量也非常大,這時我們可以用下一節維特比演算法來優化演算法時間複雜度。

3. 維特比演算法與分詞

    為了簡化原理描述,我們本節的討論都是以二元模型為基礎。

    對於一個有很多分詞可能的長句子,我們當然可以用暴力方法去計算出所有的分詞可能的概率,再找出最優分詞方法。但是用維特比演算法可以大大簡化求出最優分詞的時間。

    大家一般知道維特比演算法是用於隱式馬爾科夫模型HMM解碼演算法的,但是它是一個通用的求序列最短路徑的方法,不光可以用於HMM,也可以用於其他的序列最短路徑演算法,比如最優分詞。

    維特比演算法採用的是動態規劃來解決這個最優分詞問題的,動態規劃要求區域性路徑也是最優路徑的一部分,很顯然我們的問題是成立的。首先我們看一個簡單的分詞例子:"人生如夢境"。它的可能分詞可以用下面的概率圖表示:

    圖中的箭頭為通過統計語料庫而得到的對應的各分詞位置BEMS(開始位置,結束位置,中間位置,單詞)的條件概率。比如P(生|人)=0.17。有了這個圖,維特比演算法需要找到從Start到End之間的一條最短路徑。對於在End之前的任意一個當前區域性節點,我們需要得到到達該節點的最大概率$\delta$,和記錄到達當前節點滿足最大概率的前一節點位置$\Psi$。

    我們先用這個例子來觀察維特比演算法的過程。首先我們初始化有:$$\delta(人) = 0.26\;\;\Psi(人)=Start\;\;\delta(人生) = 0.44\;\;\Psi(人生)=Start$$

    對於節點"生",它只有一個前向節點,因此有:$$\delta(生) = \delta(人)P(生|人) = 0.0442 \;\; \Psi(生)=人 $$

     對於節點"如",就稍微複雜一點了,因為它有多個前向節點,我們要計算出到“如”概率最大的路徑:$$\delta(如) = max\{\delta(生)P(如|生),\delta(人生)P(如|人生)\} = max\{0.01680, 0.3168\} = 0.3168 \;\; \Psi(如) = 人生 $$

    類似的方法可以用於其他節點如下:$$\delta(如夢) = \delta(人生)P(如夢|人生) = 0.242 \;\; \Psi(如夢)=人生 $$$$\delta(夢) = \delta(如)P(夢|如) = 0.1996 \;\; \Psi(夢)=如 $$$$\delta(境) = max\{\delta(夢)P(境|夢) ,\delta(如夢)P(境|如夢)\}= max\{0.0359, 0.0315\} = 0.0359 \;\; \Psi(境)=夢 $$$$\delta(夢境) = \delta(如)P(夢境|如) = 0.1585 \;\; \Psi(夢境)=如 $$

    最後我們看看最終節點End:$$\delta(End) = max\{\delta(夢境)P(End|夢境), \delta(境)P(End|境)\} = max\{0.0396, 0.0047\} = 0.0396\;\;\Psi(End)=夢境$$

    由於最後的最優解為“夢境”,現在我們開始用$\Psi$反推:$$\Psi(End)=夢境 \to \Psi(夢境)=如 \to \Psi(如)=人生 \to \Psi(人生)=start $$

    從而最終的分詞結果為"人生/如/夢境"。是不是很簡單呢。

    由於維特比演算法我會在後面講隱式馬爾科夫模型HMM解碼演算法時詳細解釋,這裡就不歸納了。

4. 常用分詞工具

    對於文字挖掘中需要的分詞功能,一般我們會用現有的工具。簡單的英文分詞不需要任何工具,通過空格和標點符號就可以分詞了,而進一步的英文分詞推薦使用nltk。對於中文分詞,則推薦用結巴分詞(jieba)。這些工具使用都很簡單。你的分詞沒有特別的需求直接使用這些分詞工具就可以了。

5. 結語

    分詞是文字挖掘的預處理的重要的一步,分詞完成後,我們可以繼續做一些其他的特徵工程,比如向量化(vectorize),TF-IDF以及Hash trick,這些我們後面再講。

 

(歡迎轉載,轉載請註明出處。歡迎溝通交流: liujianping-ok@163.com) 

相關文章