1. 程式人生 > >【自然語言處理】詳說中文自動分詞

【自然語言處理】詳說中文自動分詞

文章目錄

詳說中文自動分詞

前言

       中文分詞技術屬於自然語言處理技術範疇,中文分詞是其他中文資訊處理的基礎,比如搜尋引擎只是中文分詞的一個應用。


一、 what is 中文分詞

       中文分詞指的是將一個漢字序列切分成一個個單獨的詞。分詞就是將------>連續的字序列------>按照一定的規範------>重新組合成詞序列------>的過程。
       大家都知道,對於英文而言,單詞之間是有固定的空格作為自然分界符的,中文只能是以句段通過明顯分分界符來簡單劃界,而詞沒有一個形式上的分界符。

二、中文分詞的用途

       機器翻譯,語音合成,自動分類,自動摘要,自動校對,搜尋引擎這些都要用到中文分詞。

三、中文分詞的特點和難點

       中文分詞就是讓計算機在詞與詞之間加上邊界標記。當前研究所面臨的問題和困難主要體現在三個方面:分詞的規範、歧義詞的切分和未登入詞識別。

(1) 分詞的規範。
       中文因其自身語言特性的侷限,字(詞)的界限往往很模糊,關於字(詞)的抽象定義和詞邊界的劃定尚沒有一個公認的、權威的標準。曾經有專家對母語是漢語者進行了調查,結果顯示,對漢語文字中“詞”的認同率僅有 70% 左右。正是由於這種不同的主觀分詞差異,給漢語分詞造成了極大的困難。儘管在 1992 年國家頒佈了《資訊處理用現代詞漢語分詞規範》,但是這種規範很容易受主觀因素影響,在處理現實問題時也不免相形見絀。

(2) 歧義詞切分。
中文中的歧義詞是很普遍的,歧義詞即同一個詞有多種切分方式,該如何處理這種問題呢?普遍認為中文歧義詞有三種類型。
       ⊚ 交集型切分歧義,漢語詞如AJB 型別,滿足AJ 和JB 分別成詞。如“大學生”一種切分方式“大學/生”,另一種切分方式“大/學生”。你很難去判定哪種切分正確,即使是人工切分也只能依據上下文,類似的有“結合成”“美國會”等。
       ⊚ 組合型切分歧義,漢語詞如AB,滿足A、B、AB 分別成詞。如“郭靖有武功高超的才能”中的“才能”,一種切分為“郭靖/有/武功/高超/的/才能”,另一種切分“中國/什麼/時候/才/能/達到/發達/國家/水平”顯示是不同的切分方式。
       ⊚ 混合型切分歧義,漢語詞包含如上兩種共存情況。如“郭靖說這把劍太重了”,其中“太重了”是交集型欄位,“太重”是組合型欄位。

(3) 未登入詞(新詞)識別。
       未登入詞又稱新詞。這類詞通常指兩個方面,一是詞庫中沒有收錄的詞,二是訓練語料沒有出現過的詞。未登入詞主要體現在以下幾種。
       ⊚ 新出現的網路用詞。如“藍芽”“藍瘦香菇”“房姐”“奧特”“累覺不愛”等。
       ⊚ 研究領域名稱:特定領域和新出現領域的專有名詞。如“蘇丹紅”“禽流感”“埃博拉”“三聚氰胺”等。
       ⊚ 其他專有名詞:諸如城市名、公司企業、職稱名、電影、書籍、專業術語、縮寫詞等。如“成都”“阿里巴巴”“三少爺的劍”“NLP”“川大”等。

四、常見的中文分詞方法

(1) 基於字串匹配的分詞方法。
       基本思想是基於詞典匹配,將待分詞的中文文字根據一定規則進行切分和調整,然後跟詞典中的詞語進行匹配,匹配成功則按照詞典的詞分詞,匹配失敗則通過調整或者重新選擇,如此反覆迴圈即可。代表方法有基於正向最大匹配和基於逆向最大匹配及雙向匹配法。

(2) 基於理解的分詞方法。
       基本思想是通過專家系統或者機器學習神經網路方法模擬人的理解能力前者是通過專家對分詞規則的邏輯推理並總結形成特徵規則,不斷迭代完善規則,其受到資源消耗大和演算法複雜度高的制約。後者通過機器模擬人類理解的方式,雖然可以取得不錯的效果,但是依舊受訓練時間長和過擬合等因素困擾。

(3) 基於統計的分詞方法。
       關於統計的中文分詞方法的基本思想如下所示:
       ⊚ 基於隱馬爾可夫模型的中文分詞方法。基本思想是通過文字作為觀測序列去確定隱藏序列的過程。該方法採用Viterbi 演算法對新詞識別,效果不錯,但具有生成式模型的缺點,需要計算聯合概率,因此隨著文字增大,存在計算量大的問題。
       ⊚ 基於最大熵模型的中文分詞方法。基本思想是學習概率模型時,在可能的概率分佈模型中,認為熵最大的進行切分。該方法可以避免生成模型的不足,但是存在偏移量的問題。
       ⊚ 基於條件隨機場模型的中文分詞方法。基本思想主要來源於最大熵馬爾可夫模型,主要關注的字跟上下文標記位置有關,進而通過解碼找到詞邊界。因此需要大量訓練語料,而訓練和解碼又非常耗時。

       總的來說,基於詞典和統計的方法分詞速度比較快,但是在不同領域取得的效果差異很大,還存在構造費時費力、演算法複雜度高、移植性差等缺點。
       基於統計的中文分詞,雖然其相較於規則的方法取得了不錯的效果,但也存在模型訓練時間長、分詞速度慢等問題。



五、中文分詞工具

1、HanLP 中文分詞

       HanLP 是由一系列模型與演算法組成的Java 工具包,目標是普及自然語言處理在生產環境中的應用。HanLP 具備功能完善、效能高效、架構清晰、語料時新、可自定義等特點。在提供豐富功能的同時,HanLP 內部模組堅持低耦合、模型堅持惰性載入、服務堅持靜態提供、詞典堅持明文釋出,使用起來非常方便,同時自帶一些語料處理工具,幫助使用者訓練自己的語料

A、 python呼叫hanlp進行中文分詞

程式碼所示:

 """
 author:jjk
 datetime:2018/11/5
 coding:utf-8
 project name:Pycharm_workstation
 Program function: python呼叫HanLP分詞(中文)

"""
import jpype
from jpype import *

# 呼叫HanLP的java包,如下路徑下載並解壓c盤即可:
# 啟動JVM,Linux需替換分號;為冒號:
startJVM(getDefaultJVMPath(),
         "-Djava.class.path=F:/Pycharm/Pycharm_workstation/NLP and actual combat/chapter eight\hanlp-1.6.8.jar;"
         "F:/Pycharm/Pycharm_workstation/NLP and actual combat/chapter eight", "-Xms1g", "-Xmx1g")

# 預設分詞
print("=" * 30 + "HanLP分詞" + "=" * 30)

paraStr1 = '中國科學院計算技術研究所的宗成慶教授正在教授自然語言處理課程'
HanLP = JClass('com.hankcs.hanlp.HanLP')
print(HanLP.segment(paraStr1))

# 標準分詞
print("=" * 30 + "標準分詞" + "=" * 30)
StandardTokenizer = JClass('com.hankcs.hanlp.tokenizer.StandardTokenizer')
print(StandardTokenizer.segment(paraStr1))

# NLP分詞NLPTokenizer會執行全部命名實體識別和詞性標註
print("=" * 30 + "NLP分詞" + "=" * 30)
NLPTokenizer = JClass('com.hankcs.hanlp.tokenizer.NLPTokenizer')
print(NLPTokenizer.segment(paraStr1))

# 索引分詞
print("=" * 30 + "索引分詞" + "=" * 30)
IndexTokenizer = JClass('com.hankcs.hanlp.tokenizer.IndexTokenizer')
termList = IndexTokenizer.segment(paraStr1)  # 獲取分詞內容
for term in termList:
    print(str(term) + " [" + str(term.offset) + ":" + str(term.offset + len(term.word)) + "]")

# 極速索引分詞
print("=" * 30 + " 極速詞典分詞" + "=" * 30)
SpeedTokenizer = JClass('com.hankcs.hanlp.tokenizer.SpeedTokenizer')
print(NLPTokenizer.segment(paraStr1))

# 自定義分詞
paraStr2 = '攻城獅逆襲單身狗,迎娶白富美,走上人生巔峰'
print("=" * 30 + " 自定義分詞" + "=" * 30)
CustomDictionary = JClass('com.hankcs.hanlp.dictionary.CustomDictionary')
CustomDictionary.add('攻城獅')
CustomDictionary.add('單身狗')
HanLP = JClass('com.hankcs.hanlp.HanLP')
print(HanLP.segment(paraStr2))

# 命名實體標識和詞性標註
print("=" * 20 + "命名實體識別與詞性標註" + "=" * 30)
NLPTokenizer = JClass('com.hankcs.hanlp.tokenizer.NLPTokenizer')
print(NLPTokenizer.segment(paraStr1))

# 關鍵字提取
f = open("paraStr3.txt", "rb")  # 讀取文字  
string = f.read().decode("utf-8")

# paraStr3="水利部水資源司司長陳明忠9月29日在國務院新聞辦舉行的新聞釋出會上透露,根據剛剛完成了水資源管理制度的考核,有部分省接近了紅線的指標,有部分省超過紅線的指標。對一些超過紅線的地方,陳明忠表示,對一些取用水專案進行區域的限批,嚴格地進行水資源論證和取水許可的批准。"
print("=" * 30 + "關鍵詞提取" + "=" * 30)
print(HanLP.extractKeyword(string, 8))

# 獲取文字---自動生成摘要
ff = open("paraStr0.txt", "rb")  # 讀取文字
string2 = ff.read().decode("utf-8")
print("=" * 30 + "自動摘要" + "=" * 30)
print(HanLP.extractSummary(string2, 5))

# 地方名識別
paraStr4 = ["武勝縣新學鄉政府大樓門前鑼鼓喧天", "藍翔給寧夏固原市彭陽縣紅河鎮黑牛溝村捐贈了挖掘機"]
print("=" * 30 + "地名識別" + "=" * 30)
HanLP = JClass('com.hankcs.hanlp.HanLP')
segment = HanLP.newSegment().enablePlaceRecognize(True)
for sentence in paraStr4:
    print(HanLP.segment(sentence))

# 依存句法分析
paraStr5 = "徐先生還具體幫助他確定了把畫雄鷹、松鼠和麻雀作為主攻目標。"
print("=" * 30 + "依存句法分析" + "=" * 30)
print(HanLP.parseDependency(paraStr5))

jpype.shutdownJVM()

結果如下所示(部分截圖):
在這裡插入圖片描述


2、 BosonNLP

       玻森實驗室開發的一款分詞工具。

3、 語言云:

       以哈工大社會計算與資訊檢索研究中心研發的“語言技術平臺(LTP)”為基礎,為使用者提供高效精準的中文自然語言處理雲服務。

4、 NLPIR

       中科院分詞系統。

5、 新浪雲

6、 搜狗分詞

7、 結巴分詞

8、 SCWS

       簡易中文分詞系統縮寫。SCWS 由hightman 開發,並以BSD 許可協議開源發
布,原始碼託管在GitHub。

9、 騰訊文智

10、盤古分詞

11、IKAnalyzer

       一個開源的、基於Java 語言開發的輕量級的中文分詞工具包。

六、結巴中文分詞

1、結巴中文分詞的特點

(1) 支援三種分詞模式。

⊚ 精確模式,試圖將句子最精確地切開,適合文字分析;
⊚ 全模式,把句子中所有的可以成詞的詞語都掃描出來,速度非常快,但是不能解決歧義;
⊚ 搜尋引擎模式,在精確模式的基礎上,對長詞再次切分,提高召回率,適合用於搜尋引擎分詞。

(2) 支援繁體分詞
(3) 支援自定義詞典

2、安裝,獲取結巴分詞工具

       安裝:命令視窗下:
在這裡插入圖片描述
       獲取分詞工具
       連結:https://pan.baidu.com/s/117i8BG_pslFpXFEgfJNCfw
       提取碼:9jzf

3、主要分詞功能

       ⊚ jieba.cut 方法接受三個輸入引數:需要分詞的字串;cut_all 引數用來控制是否採用全模式;HMM 引數用來控制是否使用HMM 模型。
       ⊚ jieba.cut_for_search 方法接受兩個引數:需要分詞的字串;是否使用HMM 模型。該方法適合用於搜尋引擎構建倒排索引的分詞,粒度比較細。
       ⊚ 待分詞的字串可以是Unicode 或UTF-8 字串、GBK 字串。注意:不建議直接輸入GBK 字串,可能無法預料地錯誤解碼成UTF-8。
       ⊚ jieba.cut 和jieba.cut_for_search 返回的結構都是一個可迭代的generator,可以使用for迴圈來獲得分詞後得到的每一個詞語(Unicode)。
       ⊚ jieba.lcut 和jieba.lcut_for_search 直接返回list。
       ⊚ jieba.Tokenizer(dictionary=DEFAULT_DICT) 新建自定義分詞器,可用於同時使用不同詞典。jieba.dt 為預設分詞器,所有全域性分詞相關函式都是該分詞器的對映。

"""
 author:jjk
 datetime:2018/11/6
 coding:utf-8
 project name:Pycharm_workstation
 Program function: 結巴分詞
"""
import jieba
import time
start_time = time.time()

# 預設是精確模式
seg_list = jieba.cut("我是倒黴賈,我來自昆明理工大學",cut_all=True)
print("全模式:" + "/ ".join(seg_list)) # 全模式

seg_list = jieba.cut("我是倒黴賈,我來自昆明理工大學",cut_all=False)
print("精確模式:" + "/ ".join(seg_list)) # 精確模式

seg_list = jieba.cut_for_search("我是倒黴賈,我來自昆明理工大學")# 搜素引擎模式
print("搜尋引擎模式:",", ".join(seg_list))

stop_time = time.time()
time_sum = stop_time-start_time
print("一共耗時:",time_sum)

在這裡插入圖片描述

4、新增自定義詞典

       載入詞典

       ⊚ 開發者可以指定自己自定義的詞典,以便包含jieba 詞庫裡沒有的詞。雖然jieba 有新詞識別能力,但是自行新增新詞可以保證更高的正確率。
       ⊚ 用法:jieba.load_userdict(file_name) # file_name 為檔案類物件或自定義詞典的路徑。
       ⊚ 詞典格式和dict.txt 一樣,一個詞佔一行;每一行分詞語、詞頻(可省略)和詞性(可省略)三部分,用空格隔開,順序不可顛倒。file_name 若為路徑或二進位制方式開啟的檔案,則檔案必須為UTF-8 編碼。

七、結巴分詞工具說明

1、結巴分詞的演算法策略

(1) 基於字首詞典實現高效的詞圖掃描,生成句子中漢字所有可能成詞情況所構成的有向無環圖(DAG)。
(2) 採用了動態規劃查詢最大概率路徑,找出基於詞頻的最大切分組合。
(3) 對於未登入詞,採用基於漢字成詞能力的HMM 模型,使用Viterbi 演算法。

2、演算法實現分詞

       (1)基於字首詞典實現高效的詞圖掃描,生成句子中漢字所有可能成詞情況所構成的有向無環圖(DAG)。
       生成句子中漢字所有可能成詞情況所構成的有向無環圖。DAG 根據我們生成的字首字典來構造一個這樣的DAG,對一個sentence DAG 是以{key:list[i,j…], …} 的字典結構儲存,其中key 是詞在sentence 中的位置,list 存放的是在sentence 中以key 開始且詞sentence[key:i+1]在字首詞典中以key 開始i 結尾的詞的末位置i 的列表,即list 存放的是sentence 中以位置key 開始的可能詞語的結束位置,這樣通過查字典得到詞,以及開始位置+ 結束位置列表。

       例如:

句子“抗日戰爭”生成的DAG中{0:[0,1,3]} 這樣一個簡單的DAG, 就是表示0位置開始, 在0,1,3位置都是詞。就是說0-0,0-1,0-3 即“抗”,“抗日”,“抗日戰爭”這三個詞在dict.txt中是詞。

       (2)採用動態規劃查詢最大概率路徑,找出基於詞頻的最大切分組合。基於上面的DAG 利用動態規劃查詢最大概率路徑,理解DP 演算法(動態規劃演算法)很容易就能明白了。根據動態規劃查詢最大概率路徑的基本思路就是對句子從右往左反向計算最大概率。依次類推,最後得到最大概率路徑,得到最大概率的切分組合(這裡滿足最優子結構性質,可以利用反證法進行證明)。程式碼實現中有個小訣竅,即概率對數(可以讓概率相乘的計算變成對數相加,防止相乘造成下溢,因為在語料、詞庫中,每個詞的出現概率平均下來還是很小的浮點數)。

       (3)對於未登入詞,採用基於漢字成詞能力的HMM 模型,使用Viterbi 演算法;未登入詞其實就是詞典dict.txt 中沒有記錄的詞。這裡採用了HMM 模型,HMM 是一個簡單強大的模型HMM 在實際應用中主要用來解決3 類問題。

⊚ 評估問題(概率計算問題):即給定觀測序列O=O1,O2,O3…Ot 和模型引數λ=(A,B, π \pi ),怎樣有效計算這一觀測序列出現的概率(Forward-backward 演算法)。
⊚ 解碼問題(預測問題):即給定觀測序列O=O1,O2,O3…Ot 和模型引數λ=(A,B, π \pi ),怎樣尋找滿足這種觀察序列意義上最優的隱含狀態序列S (Viterbi 演算法, 近似演算法)。
⊚ 學習問題:即HMM 的模型引數λ=(A,B, π \pi ) 未知,如何求出這3 個引數以使觀測序列 O=O1,O2,O3…Ot 的概率儘可能大(即用極大似然估計的方法估計引數,Baum-Welch,EM 演算法)。
       模型的關鍵相應引數λ=(A,B, π \pi ),經過作者對大量語料的訓練,得到了finalseg 目錄下的三個檔案(初始化狀態概率( π \pi )即詞語以某種狀態開頭的概率,其實只有兩種,要麼是B,要麼是S。這個就是起始向量,就是HMM 系統的最初模型狀態,對應檔案prob _ start.py
       隱含狀態概率轉移矩A 即字的幾種位置狀態(用BEMS 四個狀態來標記,B 是開始begin 位置;E 是end,是結束位置;M 是middle,是中間位置;S 是single,單獨成詞的位置)的轉換概率,對應檔案prob _ trans.py
       觀測狀態發射概率矩陣B 即位置狀態到單字的發射概率,比如p(“狗”|M)表示一個詞的中間現“狗”這個字的概率,對應檔案prob_emit.py)。

九、結巴分詞基本用法

       至於結巴分詞的用法,博主就不在這裡一一詳述了,以下的參考連結已經很好的說明了它的用法!!!
1、https://blog.csdn.net/meiqi0538/article/details/80218870
2、https://blog.csdn.net/meiqi0538/article/details/80213431

結束語:
       對於中文分詞,是其他中文資訊處理的基礎,比如搜尋引擎只是中文分詞的一個應用。在內容中博主也闡述了何為中文分詞,中文分詞的用途,特點以及難點,中文分詞常用的方法以及中文分詞的工具。自然語言處理是一個交叉學科,真的是很難,學的東西很多,一個小小的分支就夠博主深入研究到畢業啦,,,能看到此處,都是好孩紙加油吧騷年!!!
       說到中文分詞的工具,你可能會想了解以下博文:
       https://blog.csdn.net/Jiajikang_jjk/article/details/83750758
       https://blog.csdn.net/Jiajikang_jjk/article/details/83756760
       https://blog.csdn.net/Jiajikang_jjk/article/details/83782825