2011年11月15日 星期二

mmseg4j 中文斷詞java 實作


照著這篇文章的步驟,你可以使用java 將一串正體(繁體)中文的字串依照詞彙切開,以方便進行中文文字探勘(Text Mining)等計算詞頻的工作。
image
▲mmseg4j中文斷詞結果,可以看到它把「處理」、「文章」等詞分割出來
首先呢,為了簡化開發,程式都在Eclipse 上開發,以下用簡單兩句話說明Eclipse 如何安裝:
  • Java網站,下載並安裝JRE (請選擇合適的作業系統)
  • Eclipse官網,下載Eclipse Classic 版本,將之解壓縮之後,執行資料夾中的Eclipse.exe ,就可以用它來寫Java 程式了
簡單介紹MMSeg 與mmseg4j
mmseg4j 是採用蔡志浩先生在2000 年發表的一個中文分詞演算法 ─ MMSeg,它使用兩套演算法與四個模糊解析規則,據稱能達到98.41% 中文斷詞準確率(理論請參考MMSeg官網)。這樣的準確率已經近似於大陸中科院的ICTCLAS,973計畫專家組評測第一名的98.5%,此外mmseg4j在斷詞速度表現良好,高達1900kb/s(Simple版本),根據5樓網友實測表示比庖丁(Paoding)還快。
此外可喜可賀的是,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 (請選擇最新的zip檔案,名稱會如「mmseg4j-1.8.3.zip」)
下載mmseg4j 正體(繁體)中文詞庫 以下詞庫是筆者透過程式工具將原本的詞庫轉為正體字,以方便台港使用者研究學習,歡迎下載分享,但請註明來源:)
來吧!我們來斷詞 當然不免俗的啟動Eclipse之後,我們必須先建立一個專案。檔案 > 新增 > Java專案
image
▲名稱取作SegChinese
image
▲下一步到Java 設定的地方,選擇新增外部JAR,然後瀏覽到剛剛下載來的mmseg4j-all-X.X.X-with-dic.jar,新增後按下完成。接著展開左邊專案目錄,在src上按右鍵,選擇新增類別,取個類別名稱,在這裡我還是取為「SegChinese」。
55行java 程式「碼上會」
我們要import這些東西,如下:
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;

import com.chenlb.mmseg4j.ComplexSeg;
import com.chenlb.mmseg4j.Dictionary;
import com.chenlb.mmseg4j.MMSeg;
import com.chenlb.mmseg4j.Seg;
import com.chenlb.mmseg4j.Word;


值得注意的是import com.chenlb.mmseg4j.ComplexSeg代表使用Complex 版本的斷詞(包含四個模糊規則);若要使用簡單版本,請換成import com.chenlb.mmseg4j.SimpleSeg;。


接下來,我們在class裡面宣告一個字典型態的變數dic(儲存詞庫),並建立建構子與設定一些程式資訊,如下:
protected Dictionary dic;
 
public SegChinese() {
 System.setProperty("mmseg.dic.path", "./src/SegChinese/data"); //這裡可以指定自訂詞庫
 dic = Dictionary.getInstance();
}

protected Seg getSeg() {
 return new ComplexSeg(dic);
}


Seg方法可以指定要使用的分詞器,在這邊使用Complex(複雜版的),並將字典及放入分詞器中。這裡一定要提一下,自訂的字典可以藉由System.setProperty("mmseg.dic.path", "路徑"); 來指定,其中路徑若是相對路徑的話,是相對於專案資料夾的目錄,在上面的例子中,我故意將字典資料夾放在專案資料夾中的src/SegChinese裡的data資料夾中,我們可以在data資料夾中放入多個字典檔,就可以使用多個字典。


再來我們要建構程式的斷詞核心部分,如下:
public String segWords(String txt, String wordSpilt) throws IOException {
 Reader input = new StringReader(txt);
 StringBuilder sb = new StringBuilder();
 Seg seg = getSeg();
 MMSeg mmSeg = new MMSeg(input, seg);
 Word word = null;
 boolean first = true;
 while((word=mmSeg.next())!=null) {
  if(!first) {
   sb.append(wordSpilt);
  }
  String w = word.getString();
  sb.append(w);
  first = false;  
 }
 return sb.toString();
}


這裡我們傳入一個字串與一個希望用來作為分隔的符號,接著使用MMSeg進行分詞,每個詞可以用.next()取得,最後把它變為字串回傳。


最後我們建立一個run 方法,用來傳入測試段詞的文字。以及main 方法以測試程式執行,如下:
protected void run(String[] args) throws IOException {
 String txt = "這行文字是要被中文斷詞處理的文章,可以從執行結果看斷詞是否成功 莊圓大師";
 
 if(args.length > 0) {
  txt = args[0];
 }
 
 System.out.println(segWords(txt, " | "));
}

public static void main(String[] args) throws IOException {  
 new SegChinese().run(args);
}


在run中我傳入直線(|)作為分隔符號,以上短短55行就完成了中文斷詞,輸出結果頁首所示。我把這份java 檔附在文末,也歡迎下載測試。


附件下載:SegChinese.java


結語在這裡我要感謝前輩Deduce的提點,讓我能花相對少的摸索找到這套工具。當然這只是一篇讓讀者很快了解如何使用mmseg4j的小品文,所以只精簡的介紹了最基本以及常用的功能。我在java/text mining上的確是晚輩,所以若有撰寫不當也請各界多多包含與指教。

1 則留言: