R語言︱文字挖掘之中文分詞包——Rwordseg包(原理、功能、詳解)

悟乙己發表於2016-04-04





筆者寄語:與前面的RsowballC分詞不同的地方在於這是一箇中文的分詞包,簡單易懂,分詞是一個非常重要的步驟,可以通過一些字典,進行特定分詞。大致分析步驟如下:


資料匯入——選擇分詞字典——分詞


但是下載步驟比較繁瑣,可參考之前的部落格: R語言·文字挖掘︱Rwordseg/rJava兩包的安裝(安到吐血)


——————————————————————————————————


Rwordseg與jiebaR分詞之間的區別


中文分詞比較有名的包非`Rwordseg`和`jieba`莫屬,他們採用的演算法大同小異,這裡不再贅述,我主要講一講他們的另外一個小的不同:

`Rwordseg`在分詞之前會去掉文字中所有的符號,這樣就會造成原本分開的句子前後相連,本來是分開的兩個字也許連在一起就是一個詞了,

`jieba`分詞包不會去掉任何符號,而且返回的結果裡面也會有符號。

所以在小文字準確性上可能`Rwordseg`就會有“可以忽視”的誤差,但是文字挖掘都是大規模的文字處理,由此造成的差異又能掀起多大的漣漪,與其分詞後要整理去除各種符號,倒不如提前把符號去掉了,所以我們才選擇了`Rwordseg`。


來看一下這篇論文一些中文分詞工具的效能比較《開源中文分詞器的比較研究_黃翼彪,2013》






8款中文分詞器的綜合效能排名:
Paoding(準確率、分詞速度、新詞識別等,最棒)
mmseg4j(切分速度、準確率較高)
IKAnalyzer
Imdict-chinese-analyzer
Ansj
盤古分詞
Httpcws
jieba

——————————————————————————————————

Rwordseg分詞原理以及功能詳情


Rwordseg 是一個R環境下的中文分詞工具,使用 rJava 呼叫 Java 分詞工具 Ansj。

Ansj 也是一個開源的 Java 中文分詞工具,基於中科院的 ictclas 中文分詞演算法, 採用隱馬爾科夫模型(Hidden Markov Model, HMM)。作者孫健重寫了一個Java版本, 並且全部開源,使得 Ansi 可用於人名識別、地名識別、組織機構名識別、多級詞性標註、 關鍵詞提取、指紋提取等領域,支援行業詞典、 使用者自定義詞典。


1、分詞原理

n-Gram+CRF+HMM的中文分詞的java實現.

分詞速度達到每秒鐘大約200萬字左右(mac air下測試),準確率能達到96%以上

目前實現了.中文分詞. 中文姓名識別 . 使用者自定義詞典,關鍵字提取,自動摘要,關鍵字標記等功能

可以應用到自然語言處理等方面,適用於對分詞效果要求高的各種專案.

(官方說明文件來源:http://pan.baidu.com/s/1sj5Edjf)


該演算法實現分詞有以下幾個步驟:


1、 全切分,原子切分;

2、 N最短路徑的粗切分,根據隱馬爾科夫模型和viterbi演算法,達到最優路徑的規劃;

3、人名識別;

4、 系統詞典補充;
5、 使用者自定義詞典的補充;
6、 詞性標註(可選) 


2、Ansj分詞的準確率


這是我採用人民日報1998年1月語料庫的一個測試結果,首先要說明的是這份人工標註的語料庫本身就有錯誤。

  •     P(準確率):0.984887218571267
  •     R(召回率):0.9626488103178712
  •     F(綜合指標F值):0.9736410471396494 

3、歧義詞、未登入詞的表現

歧異方面的處理方式自我感覺還可以,基於“最佳實踐規則+統計”的方式,雖然還有一部分歧異無法識別,但是已經完全能滿足工程應用了。

至於未登入詞的識別,目前重點做了中文人名的識別,效果還算滿意,識別方式用的“字型+前後監督”的方式,也算是目前我所知道的效果最好的一種識別方式了。


4、演算法效率

在我的測試中,Ansj的效率已經遠超ictclas的其他開源實現版本。

核心詞典利用雙陣列規劃,每秒鐘能達到千萬級別的粗分。在我的MacBookAir上面,分詞速度大約在300w/字/秒,在酷睿i5+4G記憶體組裝機器上,更是達到了400w+/字/秒的速度。


參考文獻:

Rwordseg說明:http://jianl.org/cn/R/Rwordseg.html

ansj中文分詞github:https://github.com/NLPchina/ansj_seg

ansj中文分詞作者專訪:http://blog.csdn.net/blogdevteam/article/details/8148451


——————————————————————————————————


一、資料匯入、函式測試


本次使用程式碼與案例是基於北門吹風部落格而來。


#匯入rJava 和Rwordseg

library(rJava)
library(Rwordseg)

#測試rJava 和Rwordseg是否安裝好
teststring1 <- "我愛R語言,我愛文字挖掘"
segmentCN(teststring1)                  ##Rwordseg中的函式,中文分詞

#觀察分詞1000次花的時間
system.time(for(i in 1:1000) segmentCN(teststring1))
#segmentCN的詳細解釋
?segmentCN


二、分詞詞典的使用


筆者認為選擇分詞詞典對於後續的分析極為重要,詞典庫是之後分詞的匹配庫,這個詞庫越強大,分詞的效果就越好。網上大多使用的是搜狗分詞包。


1、從搜狗詞庫下載分詞詞典

##用搜狗詞庫的時候 一定要在官網上下載  ~.scel 檔案,
##搜狗下載官網:http://pinyin.sogou.com/dict/cate/index/101
#不能直接將 下載的 ~.txt改為~.scel
installDict("F:/R/文字挖掘分詞詞庫/自然語言處理及計算語言學相關術語.scel","computer",dicttype = "scel")

2、檢視詞典的函式

載入詞典函式為installDict,下面有一些簡單的介紹,其中的詞類名稱是自定義的,每個詞類名稱需要不一樣。


#檢視詞典
#installDict函式介紹
# installDict(dictpath, dictname,dicttype = c("text", "scel"), load = TRUE)
#installDict("工作目錄","詞類名稱",dicttype = c("text", "scel"), load = TRUE)
listDict()
#uninstallDict() 刪除安裝的詞典
uninstallDict()
#listDict() 檢視剩餘的詞典
listDict()

 deleteWords( )刪詞 

分別有檢視、安裝、刪除的函式。

3、自定義詞典


可以自己設定哪些關鍵詞需要額外注意區分開來,也可以刪除已經加入詞庫的一些關鍵詞,

對於一些專業領域,專業名詞較多的案例,很推薦。


#自定義詞典
#手動新增或刪除詞彙,僅僅只在記憶體中臨時新增,未記錄下來
segmentCN("畫角聲斷譙門")
insertWords("譙門")   #讓某片語放入記憶體
segmentCN("畫角聲斷譙門")

deleteWords(c("譙門","畫角"))   #刪除某片語
segmentCN("畫角聲斷譙門")

#使用save引數,把操作記錄下來,下回啟動能直接用
insertWords(c("譙門","畫角"),save=TRUE)
segmentCN("畫角聲斷譙門")


三、分詞

1、Rwordseg分詞包核心函式segmentCN


Rwordseg分詞包主要函式是segmentCN,這個函式是核心,筆者詳解一下這個函式,程式碼如下:


#segmentCN函式解釋
segmentCN(strwords,
          analyzer = get("Analyzer", envir = .RwordsegEnv),
          nature = FALSE, nosymbol = TRUE,
          returnType = c("vector", "tm"), isfast = FALSE,
          outfile = "", blocklines = 1000)

#strwords:中文句子
#analyzer:分析的java物件
#nature:是否識別片語的詞性(動詞、形容詞)
#nosymbol:是否保留句子符號
#returnType:預設是一個字串,也可以儲存成其他的樣式,比如tm格式,以供tm包分析
#isfast:“否”代表劃分成一個個字元,“是”代表保留句子,只是斷句
#outfile:如果輸入是一個檔案,檔案的路徑是啥
#blocklines:一行的最大讀入字元數


分詞時候的原則是,如果該詞是預設詞典裡面的,那麼優先分詞出來。那麼你insert以及詞典加入的詞語,都不會被分出來,而且按照預設詞典分。

如何有一個新詞,容易被拆開了分,那麼怎麼辦?

目前還沒有特別棒的方法,不過你在insert時候,可以把出現頻次提高,這樣好像可以提高優先順序。

至於Rwordseg預設詞典,在哪呢?


2、關於人名的分詞


#引數isNameRecognition  可用來人的名字識別,
getOption("isNameRecognition") #預設是不進行人名識別,輸出false
segmentCN("梅超風不是是桃花島島主")
segment.options(isNameRecognition = TRUE)
getOption("isNameRecognition")
segmentCN("梅超風是桃花島島主")





除了人名之外,rwordseg還有兩類識別:

2、數字識別(isNumRecognition ,預設為TRUE,預設識別數字);

3、量詞識別(isQuantifierRecognition,預設為TRUE,預設識別量詞)。


————————————————————


延伸一:python中的模組——pynlpir

import pynlpir
pynlpir.open()

s = '歡迎科研人員、技術工程師、企事業單位與個人參與NLPIR平臺的建設工作。'
pynlpir.segment(s)

[('歡迎', 'verb'), ('科研', 'noun'), ('人員', 'noun'), ('、', 'punctuation mark'), ('技術', 'noun'), ('工程師', 'noun'), ('、', 'punctuation mark'), ('企事業', 'noun'), ('單位', 'noun'), ('與', 'conjunction'), ('個人', 'noun'), ('參與', 'verb'), ('NLPIR', 'noun'), ('平臺', 'noun'), ('的', 'particle'), ('建設', 'verb'), ('工作', 'verb'), ('。', 'punctuation mark')]





相關文章