2014年5月15日 星期四

[ Java 代碼範本 ] mmseg4j : 碼上會! mmseg4j 中文斷詞java 實作

來源自 這裡 
Preface: 
照著這篇文章的步驟,你可以使用 mmseg4j 將一串正體(繁體)中文的字串依照詞彙切開,以方便進行中文文字探勘 (Text Mining) 等計算詞頻的工作。mmseg4j 是採用 蔡志浩先生 在2000 年發表的一個中文分詞演算法 ─ MMSeg,它使用兩套演算法與四個模糊解析規則,據稱能達到98.41% 中文斷詞準確率 (理論請參考MMSeg官網)。這樣的準確率已經近似於大陸中科院的 ICTCLAS,973計畫專家組評測第一名的98.5%,此外mmseg4j在斷詞速度表現良好,高達1900kb/s (Simple版本). 

此外可喜可賀的是,mmseg4j詞庫採用utf-8編碼 (不像ICTCLAS使用GB) 而且可以自訂,因此只要替換詞庫就可以用來將優美的正體中文進行斷詞,以下來稍微介紹一下詞庫。mmseg4j 預設使用sogou 詞庫 (去除無意義詞),並合併 rmmseg (Ruby中文斷詞套件) 的詞庫,共14多萬詞。詞庫放在jar裡面,若使用WinRAR等軟體,將下載解開的mmseg4j裡面的mmseg4j-all-X.X.X-with-dic.jar 再解開,裡面的data 資料夾就是詞庫檔預設的位置: 
* chars.dic:單一字和對應的頻率,提供complex模式使用。
* units.dic:單位詞,如:分、秒、年。主要是在數位後面的單位資訊切分好,不與words.dic中的詞有混淆。
* words.dic:核心的詞庫檔,一行一詞,不需要其它任何資料,採utf-8編碼。

若要自訂辭典,檔案名必需是 “words” 為首碼和“.dic”為副檔名,例如 wordsXXX.dic。然後我們可以把這個些自訂的詞庫集中在某個資料夾,並在程式中設定讀取這些詞庫檔 (稍後會示範),也可以把這樣的純文字文件用WinRAR壓縮回mmseg4j-all-X.X.X-with-dic.jar 的data 資料夾中。官網(簡體)下載mmseg4j:mmseg4j 

下載mmseg4j 正體(繁體)中文詞庫: 
以下詞庫是筆者透過程式工具將原本的詞庫轉為正體字,以方便台港使用者研究學習: 
units.dicwords.dic 正體版
mmseg4j-all-1.8.2-with-dic.jar 正體版,我把辭典包在這裡面,所以不介意也可以直接用這個jar (之後 demo 的程式也是使用這個jar)

來吧!我們來斷詞 : 
我們要 import 這些東西,如下: 
  1. import java.io.IOException;  
  2. import java.io.Reader;  
  3. import java.io.StringReader;  
  4.   
  5. import com.chenlb.mmseg4j.ComplexSeg;  
  6. import com.chenlb.mmseg4j.Dictionary;  
  7. import com.chenlb.mmseg4j.MMSeg;  
  8. import com.chenlb.mmseg4j.Seg;  
  9. import com.chenlb.mmseg4j.Word;  
值得注意的是 import com.chenlb.mmseg4j.ComplexSeg 代表使用 Complex 版本的斷詞 (包含四個模糊規則);若要使用簡單版本,請換成 import com.chenlb.mmseg4j.SimpleSeg;。接下來,我們在class裡面宣告一個字典型態的變數 dic (儲存詞庫),並建立建構子與設定一些程式資訊,如下: 
  1. protected Dictionary dic;  
  2.       
  3. public SegChinese() {  
  4.     System.setProperty("mmseg.dic.path""./src/SegChinese/data");  //這裡可以指定自訂詞庫  
  5.     dic = Dictionary.getInstance();  
  6. }  
  7.   
  8. protected Seg getSeg() {  
  9.     return new ComplexSeg(dic);  
  10. }  
Seg 方法可以指定要使用的分詞器,在這邊使用 Complex (複雜版的),並將字典及放入分詞器中。這裡一定要提一下,自訂的字典可以藉由 System.setProperty("mmseg.dic.path", "路徑"); 來指定,其中路徑若是相對路徑的話,是相對於專案資料夾的目錄,在上面的例子中,我故意將字典資料夾放在專案資料夾中的 data/mmseg_dic 路徑下,我們可以在其中放入多個字典檔,就可以使用多個字典. 再來我們要建構程式的斷詞核心部分,如下: 
  1. public String segWords(String txt, String wordSpilt) throws IOException {  
  2.     Reader input = new StringReader(txt);  
  3.     StringBuilder sb = new StringBuilder();  
  4.     Seg seg = getSeg();  
  5.     MMSeg mmSeg = new MMSeg(input, seg);  
  6.     Word word = null;  
  7.     boolean first = true;  
  8.     while((word=mmSeg.next())!=null) {  
  9.         if(!first) {  
  10.             sb.append(wordSpilt);  
  11.         }  
  12.         String w = word.getString();  
  13.         sb.append(w);  
  14.         first = false;        
  15.     }  
  16.     return sb.toString();  
  17. }  
這裡我們傳入一個字串與一個希望用來作為分隔的符號,接著使用MMSeg進行分詞,每個詞可以用.next()取得,最後把它變為字串回傳。main 方法以測試程式執行,如下: 
  1. public static void main(String args[]) throws Exception  
  2. {  
  3.     SegChinese seg = new SegChinese();  
  4.     String txt = "這行文字是要被中文斷詞處理的文章,可以從執行結果看斷詞是否成功 莊圓大師";  
  5.     System.out.println(seg.segWords(txt, " | "));  
  6. }  
Supplement: 
CKIP 中文斷詞系統

2 則留言:

  1. 您好,我想請問有可以讀檔後斷詞的程式碼嗎?謝謝您~~

    回覆刪除
    回覆
    1. 可以具體描述你的需求如:
      1. 讀進檔案
      2. 對檔案每一行進行斷詞並寫進輸出檔案
      3. ...

      另外這需要支援命令列使用?

      刪除

[Git 常見問題] error: The following untracked working tree files would be overwritten by merge

  Source From  Here 方案1: // x -----删除忽略文件已经对 git 来说不识别的文件 // d -----删除未被添加到 git 的路径中的文件 // f -----强制运行 #   git clean -d -fx 方案2: 今天在服务器上  gi...