-
社群活躍。截止本文釋出前,Jieba在Github上已經有17,670的star數目。社群活躍度高,代表著該專案會持續更新,實際生產實踐中遇到的問題能夠在社群反饋並得到解決,適合長期使用。
-
功能豐富。Jieba其實並不是隻有分詞這一個功能,其是一個開源框架,提供了很多在分詞之上的演演算法,如關鍵詞提取、詞性標註等。
-
提供多種程式語言實現。Jieba官方提供了Python、C++、Go、R、iOS等多平臺多語言支援,不僅如此,還提供了很多熱門社群專案的擴充套件外掛,如ElasticSearch、solr、lucene等。在實際專案中,進行擴充套件十分容易。
-
使用簡單。Jieba的API總體來說並不多,且需要進行的配置並不複雜,方便上手。
作者:塗銘 劉祥 劉樹春
如需轉載請聯絡大資料(ID:hzdashuju)
Jieba分詞官網地址是:
https://github.com/fxsjy/jieba
可以採用如下方式進行安裝:
pip install jieba
Jieba分詞結合了基於規則和基於統計這兩類方法。
首先基於字首詞典進行詞圖掃描,字首詞典是指詞典中的詞按照字首包含的順序排列,例如詞典中出現了“上”,之後以“上”開頭的詞都會出現在這一部分,例如“上海”,進而會出現“上海市”,從而形成一種層級包含結構。
如果將詞看作節點,詞和詞之間的分詞符看作邊,那麼一種分詞方案則對應著從第一個字到最後一個字的一條分詞路徑。
因此,基於字首詞典可以快速構建包含全部可能分詞結果的有向無環圖,這個圖中包含多條分詞路徑,有向是指全部的路徑都始於第一個字、止於最後一個字,無環是指節點之間不構成閉環。
基於標註語料,使用動態規劃的方法可以找出最大機率路徑,並將其作為最終的分詞結果。對於未登入詞,Jieba使用了基於漢字成詞的HMM模型,採用了Viterbi演演算法進行推導。(進一步瞭解中文分詞演演算法,請點選:入門科普:一文看懂NLP和中文分詞演演算法(附程式碼舉例))
01 Jieba的三種分詞樣式
Jieba提供了三種分詞樣式:
-
精確樣式:試圖將句子最精確地切開,適合文字分析。
-
全樣式:把句子中所有可以成詞的詞語都掃描出來,速度非常快,但是不能解決歧義。
-
搜尋引擎樣式:在精確樣式的基礎上,對長詞再次切分,提高召回率,適合用於搜尋引擎分詞。
下麵是使用這三種樣式的對比。
import jieba
sent = '中文分詞是文字處理不可或缺的一步!'
seg_list = jieba.cut(sent, cut_all=True)
print('全樣式:', '/ '.join(seg_list))
seg_list = jieba.cut(sent, cut_all=False)
print('精確樣式:', '/ '.join(seg_list))
seg_list = jieba.cut(sent)
print('預設精確樣式:', '/ '.join(seg_list))
seg_list = jieba.cut_for_search(sent)
print('搜尋引擎樣式', '/ '.join(seg_list))
執行結果如下:
-
全樣式:
中文/分詞/是/文字/文字處理/本處/處理/不可/不可或缺/或缺/的/一步//
-
精確樣式:
中文/分詞/是/文字處理/不可或缺/的/一步/!
-
預設精確樣式:
中文/分詞/是/文字處理/不可或缺/的/一步/!
-
搜尋引擎樣式:
中文/分詞/是/文字/本處/處理/文字處理/不可/或缺/不可或缺/的/一步/!
可以看到,全樣式和搜尋引擎樣式下,Jieba將會把分詞的所有可能都打印出來。一般直接使用精確樣式即可,但是在某些模糊匹配場景下,使用全樣式或搜尋引擎樣式更適合。
接下來將結合具體案例,講解Jieba分詞的具體用法。
02 實戰之高頻詞提取
高頻詞一般是指檔案中出現頻率較高且非無用的詞語,其一定程度上代表了檔案的焦點所在。針對單篇檔案,可以作為一種關鍵詞來看。對於如新聞這樣的多篇檔案,可以將其作為熱詞,發現輿論焦點。
高頻詞提取其實就是自然語言處理中的TF(Term Frequency)策略。其主要有以下幹擾項:
-
標點符號:一般標點符號無任何價值,需要去除。
-
停用詞:諸如“的”“是”“了”等常用詞無任何意義,也需要剔除。
下麵採用Jieba分詞,針對搜狗實驗室的新聞資料,進行高頻詞的提取。
資料見:
https://github.com/nlpinaction/learning-nlp
chapter3/data/news下,包括9個目錄,目錄下均為txt檔案,分別代表不同領域的新聞。
該資料本質上是一個分類語料,這裡我們只挑選其中一個類別,統計該類的高頻詞。
首先,進行資料的讀取:
def get_content(path):
with open(path, 'r', encoding='gbk', errors='ignore') as f:
content = ''
for l in f:
l = l.strip()
content += l
return content
該函式用於載入指定路徑下的資料。
定義高頻詞統計的函式,其輸入是一個詞的陣列:
def get_TF(words, topK=10):
tf_dic = {}
for w in words:
tf_dic[w] = tf_dic.get(w, 0) + 1
return sorted(tf_dic.items(), key = lambda x: x[1], reverse=True)[:topK]
最後,主函式如下,這裡僅列舉了求出高頻詞的前10個:
def main():
import glob
import random
import jieba
files = glob.glob('./data/news/C000013/*.txt')
corpus = [get_content(x) for x in files]
sample_inx = random.randint(0, len(corpus))
split_words = list(jieba.cut(corpus[sample_inx]))
print('樣本之一:'+corpus[sample_inx])
print('樣本分詞效果:'+'/ '.join(split_words))
print('樣本的topK(10)詞:'+str(get_TF(split_words)))
執行主函式,結果如下:
-
樣本之一:
中國衛生部官員24日說,截至2005年底,中國各地報告的塵肺病病人累計已超過60萬例,職業病整體防治形勢嚴峻。衛生部副部長陳嘯宏在當日舉行的“國家職業衛生示範企業授牌暨企業職業衛生交流大會”上說,中國各類急性職業中毒事故每年發生200多起,上千人中毒,直接經濟損失達上百億元。職業病病人總量大、發病率較高、經濟損失大、影響惡劣。衛生部24日公佈,2005年衛生部共收到全國30個省、自治區、直轄市(不包括西藏、港、澳、臺)各類職業病報告12212例,其中塵肺病病例報告9173例,佔75.11%。陳嘯宏說,矽肺和煤工塵肺是中國最主要的塵肺病,且塵肺病發病工齡在縮短。去年報告的塵肺病病人中最短接塵時間不足三個月,平均發病年齡40.9歲,最小發病年齡20歲。陳嘯宏表示,政府部門執法不嚴、監督不力,企業生產水平不高、技術裝置落後等是職業衛生問題嚴重的原因。“但更重要的原因是有些企業法制觀念淡薄,社會責任嚴重缺位,缺乏維護職工健康的強烈的意識,職工的合法權益不能得到有效的保障。”他說。為提高企業對職業衛生工作的重視,衛生部、國家安全生產監督管理總局和中華全國總工會24日在京評選出56家國家級職業衛生工作示範企業,希望這些企業為社會推廣職業病防治經驗,促使其他企業作好職業衛生工作,保護勞動者健康。
-
樣本分詞效果:
中國衛生部/官員/24/日/說/,/截至/2005/年底/,/中國/各地/報告/的/塵肺病/病人/累計/已/超過/60/萬例/,/職業病/整體/防治/形勢嚴峻/。/衛生部/副/部長/陳嘯宏/在/當日/舉行/的/“/國家/職業/衛生/示範/企業/授牌/暨/企業/職業/衛生/交流/大會/”/上/說/,/中國/各類/急性/職業/中毒/事故/每年/發生/200/多起/,/上千人/中毒/,/直接/經濟損失/達上/百億元/。/職業病/病人/總量/大/、/發病率/較/高/、/經濟損失/大/、/影響/惡劣/。/衛生部/24/日/公佈/,/2005/年/衛生部/共/收到/全國/30/個省/、/自治區/、/直轄市/(/不/包括/西藏/、/港/、/澳/、/臺/)/各類/職業病/報告/12212/例/,/其中/塵肺病/病例/報告/9173/例/,/佔/75/./11/%/。/陳嘯宏/說/,/矽肺/和/煤工/塵肺/是/中國/最/主要/的/塵肺病/,/且/塵肺病/發病/工齡/在/縮短/。/去年/報告/的/塵肺病/病人/中/最/短/接塵/時間/不足/三個/月/,/平均/發病/年齡/40/./9/歲/,/最小/發病/年齡/20/歲/。/陳嘯宏/表示/,/政府部門/執法不嚴/、/監督/不力/,/企業/生產/水平/不高/、/技術裝置/落後/等/是/職業/衛生/問題/嚴重/的/原因/。/“/但/更/重要/的/原因/是/有些/企業/法制觀念/淡薄/,/社會/責任/嚴重/缺位/,/缺乏/維護/職工/健康/的/強烈/的/意識/,/職工/的/合法權益/不能/得到/有效/的/保障/。/”/他/說/。/為/提高/企業/對/職業/衛生/工作/的/重視/,/衛生部/、/國家/安全/生產/監督管理/總局/和/中華全國總工會/24/日/在/京/評選/出/56/家/國家級/職業/衛生/工作/示範/企業/,/希望/這些/企業/為/社會/推廣/職業病/防治/經驗/,/促使/其他/企業/作好/職業/衛生/工作/,/保護/勞動者/健康/。
-
樣本的topK(10)詞:
[(',',22),('、',11),('的',11),('。',10),('企業',8),('職業',7),('衛生',6),('塵肺病',5),('說',4),('報告',4)]
透過上面的結果,我們可以發現,諸如“的”“,”“。”“說”等詞佔據著很高的位置,而這類詞對把控文章焦點並無太大意義。我們需要的是類似“塵肺病”這種能夠簡要概括重點的詞彙。常用的辦法,是自定義一個停用詞典,當遇到這些詞時,過濾掉即可。
因此,我們可以自定義詞典,然後按照如下方式來進行最佳化。
首先,整理常用的停用詞(包括標點符號),按照每行一個寫入到一個檔案中(data目錄下的stop_words.utf8)。然後定義如下函式,用於過濾停用詞:
def stop_words(path):
with open(path) as f:
return [l.strip() for l in f]
接下來修改main函式中第11行分詞的部分,改為:
split_words = [x for x in jieba.cut(corpus[sample_inx]) if x not in stop_words('./data/stop_words.utf8')]
高頻詞前10位結果如下:
-
樣本的topK(10)詞:
[('企業', 8), ('職業', 7), ('衛生', 6), ('塵肺病', 5), ('衛生部', 4), ('報告', 4), ('職業病', 4), ('中國', 3), ('陳嘯宏', 3), ('工作', 3)]
對比之前的結果,會發現效果要想有所提升,必須去除了無用標點符號以及“的”等幹擾詞。註意,本節實戰中所用的停用詞典為筆者整理的通用詞典,一般實踐過程中,需要根據自己的任務,定期更新維護。
上面演示了透過Jieba按照常規切詞來提取高頻詞彙的過程。事實上,常用的中文分詞器在分詞效果上差距並不是特別大,但是在特定場景下常常表現的並不是那麼盡如人意。
通常這種情況下,我們需要定製自己的領域詞典,用以提升分詞的效果。Jieba分詞就提供了這樣的功能,使用者可以載入自定義詞典:
jieba.load_userdict('./data/user_dict.utf8')
Jieba要求的使用者詞典格式一般如下:
朝三暮四 3 i
大資料 5
湯姆 nz
公主墳
每一行為三個部分:詞語、詞頻(可省略)、詞性(可省略),用空格隔開,順序不可顛倒。該詞典檔案需為utf8編碼。
在提取高頻詞時,透過更合理的自定義詞典載入,能夠獲得更佳的效果。當然這裡僅僅演示了一篇檔案的高頻詞計算,多篇檔案的高頻詞提取也可按照該思路進行整體統計計算。
關於作者:塗銘,阿裡巴巴資料架構師,對大資料、自然語言處理、Python、Java相關技術有深入的研究,積累了豐富的實踐經驗。
劉祥,百煉智慧自然語言處理專家,主要研究知識圖譜、NLG等前沿技術,參與機器自動寫作產品的研發與設計。
劉樹春,七牛雲高階演演算法專家,七牛AI實驗室NLP&OCR;方向負責人,主要負責七牛NLP以及OCR相關專案的研究與落地。
本文摘編自《Python自然語言處理實戰:核心技術與演演算法》,經出版方授權釋出。
延伸閱讀《Python自然語言處理實戰》
點選上圖瞭解及購買
轉載請聯絡微信:togo-maruko
推薦語:阿裡巴巴、前明略資料和七牛雲的高階專家和科學家撰寫,零基礎掌握NLP的核心技術、方法論和經典演演算法。