開源自然語言處理工具包hanlp中CRF分詞實現詳解

adnb34g發表於2019-02-27

 

CRF 簡介

CRF 是序列標註場景中常用的模型,比 HMM 能利用更多的特徵,比 MEMM 更能抵抗標記偏置的問題。

[gerative-discriminative.png] 

CRF 訓練

這類耗時的任務,還是交給了用 C++ 實現的 CRF++ 。關於 CRF++ 輸出的 CRF 模型,請參考《 CRF++ 模型格式說明》。  

CRF 解碼

解碼採用維特比演算法實現。並且稍有改進,用中文偽碼與白話描述如下:

首先任何字的標籤不僅取決於它自己的引數,還取決於前一個字的標籤。但是第一個字前面並沒有字,何來標籤?所以第一個字的處理稍有不同,假設第 個字的標籤為 X ,遍歷 X 計算第一個字的標籤,取分數最大的那一個。

如何計算一個字的某個標籤的分數呢?某個字根據 CRF 模型提供的模板生成了一系列特徵函式,這些函式的輸出值乘以該函式的權值最後求和得出了一個分數。該分數只是“點函式”的得分,還需加上“邊函式”的得分。邊函式在本分詞模型中簡化為 f(s ,s) ,其中 s ’為前一個字的標籤, s 為當前字的標籤。於是該邊函式就可以用一個 4*4 的矩陣描述,相當於 HMM 中的轉移機率。

實現了評分函式後,從第二字開始即可運用維特比後向解碼,為所有字打上 BEMS 標籤。  

例項

還是取經典的 “商品和服務”為例,首先 HanLP CRFSegment 分詞器將其拆分為一張表:

 

null 表示分詞器還沒有對該字標註。

程式碼

上面說了這麼多,其實我的實現非常簡練:


 

 

 


標註結果

標註後將 table列印出來:

 

最終處理

 

BEMS 該合併的合併,得到:

[ 商品 /null, /null, 服務 /null]

然後將詞語送到詞典中查詢一下,沒查到的暫時當作 nx ,並記下位置(因為這是個新詞,為了表示它的特殊性,最後詞性設為 null ),再次使用維特比標註詞性:

[ 商品 /n, /cc, 服務 /vn]

新詞識別

 

CRF 對新詞有很好的識別能力,比如:

CRFSegment segment = new CRFSegment();

segment.enablePartOfSpeechTagging(true);

System.out.println(segment.seg(" 你看過穆赫蘭道嗎 "));

輸出

 

CRF 標註結果

  S   

  S   

  S   

  B   

  M   

  M   

  E   

  S   

[ /rr, /v, /uguo, 穆赫蘭道 /null, /y]

 

null 表示新詞。




來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31524777/viewspace-2637046/,如需轉載,請註明出處,否則將追究法律責任。

相關文章