NLP(一):jieba分词
本文主要講統計分詞。
中文預處理的一個重要的環節就是對語料進行分詞,將一句話或者一個段落拆分成許多獨立個體的詞,然后方便向量化,接著進行TF-IDF的特征處理。
在英語中,單詞本身就是“詞”,而在漢語中,“詞”以“字”為基本單位,文章的語義表達仍然以“詞”來劃分,所以在處理中文文本時,需要進行分詞處理,將句子轉換為“詞”的表示,這個切分詞語的過程就是中文分詞。
現在已有的分詞算法大體可以分為:
規則分詞:通過維護一個足夠大的詞典,這個詞典中存儲了很多的詞條,然后計算機會與這些已經存在的詞條進行匹配,匹配到一個就完成一個分詞。主要有正向最大匹配法(MM),逆向最大匹配法(RMM),雙向最大匹配法(BMM)
基于理解的分詞方法:其做法就是讓計算機盡可能模擬人類對于句子的理解,在分詞的時候讓計算機做到句法分析,語義分析,但是因為漢語言的龐雜以及多變性,這種分詞方法并沒有那么成熟。
統計分詞:主要思想是把每個詞看作是由詞的最小單位的各個字組成的,如果相連的兩個字在不同的文本中出現的次數越多,就表示這兩個字很有可能構成一個詞,因此就利用字與字相鄰出現的頻率來反應成詞的可靠性。這種做法是給出大量的已分好詞的文本,然后利用機器學習此文本的分詞方式和方法,訓練相應的分詞模型,從而達到對未知文本的分詞,這里就用到了統計學習算法,比如隱馬爾可夫HMM,條件隨機場CRF。
一、jieba引入
jieba分詞是分詞的一種工具,鏡像下載方法如下:
打開anaconda prompt,輸入pip,再輸入pip install jieba -i https://pypi.douban.com/simple/即可安裝成功。
接下來先看jieba分詞的三種分詞模式:精確模式,全模式,搜索引擎模式:
全模式和搜索引擎模式會把分詞的所有可能都打印出來,一般情況使用精確模式就可以了,在某些模糊匹配場景中,使用全模式和搜索引擎模式,代碼如下:
import jieba
sent="中文分詞是文本處理不可缺少的一步!"
seg_list=jieba.cut(sent,cut_all=True)
print('全模式:','/'.join(seg_list))
import jieba
sent="中文分詞是文本處理不可缺少的一步!"
seg_list=jieba.cut(sent,cut_all=False)
print('精確模式:','/'.join(seg_list))
import jieba
sent="中文分詞是文本處理不可缺少的一步!"
seg_list=jieba.cut(sent)
print('默認精確模式:','/'.join(seg_list))
import jieba
sent="中文分詞是文本處理不可缺少的一步!"
seg_list=jieba.cut_for_search(sent)
print('搜索引擎模式:','/'.join(seg_list))
初學到這里的時候我在想,既然jieba分詞這么好,那好像沒有去研究它的必要了,只要會調庫,就算是會分詞了?這個問題留在這、
在運行代碼的時候發現,代碼的名字不能命名為“jieba”,否則就會出現“AttributeError: module 'jieba' has no attribute 'cut'”的報錯。o(╯□╰)o
jieba.cut : 方法接受三個輸入參數: 需要分詞的字符串;cut_all 參數用來控制是否采用全模式;HMM 參數用來控制是否使用 HMM 模型
jieba.cut_for_search : 方法接受兩個參數:需要分詞的字符串;是否使用 HMM 模型。該方法適合用于搜索引擎構建倒排索引的分詞,粒度比較細
jieba.cut 以及 jieba.cut_for_search :返回的結構都是一個可迭代的 generator,可以使用 for 循環來獲得分詞后得到的每一個詞語(unicode),或者用jieba.lcut 以及jieba.lcut_for_search 直接返回 list
二、添加新詞/加載自定義詞典
當我們在進行分詞的時候可能會有一些新的詞語,而這些詞語分詞器沒有進行對應的訓練,那么就可能導致分詞有誤。
例如:
import jieba
sent="我不是藥神很好看"
seg_list=jieba.cut(sent,cut_all=False)
print('精確模式:','/'.join(seg_list))
輸出結果為:
“我不是藥神”應該是一個詞,那我們添加它,在網上搜索的時候找到兩種添加方法,還未查明兩種方法的區別,但是這兩種方法適合詞較少,可以手動添加的情況,比如對于醫學大類的主題文本就不適合這樣一行一行的添加:
jieba.add_word("我是詞")
jieba.suggest_freq("我是詞",True)
import jieba
sent="我不是藥神很好看"
jieba.add_word("我不是藥神")
seg_list=jieba.cut(sent,cut_all=False)
print('精確模式:','/'.join(seg_list))
import jieba
sent="我不是藥神很好看"
jieba.suggest_freq("我不是藥神", True)
seg_list=jieba.cut(sent,cut_all=False)
print('精確模式:','/'.join(seg_list))
這兩種方式得到的輸出結果都為:
如果是某一專業領域的文本,可在網上尋找用戶自定義詞典,代碼如下:
# 加載用戶自定義字典
jieba.load_userdict('./source/user_dict.utf8')
三、停用詞
有時候我們需要對新聞進行高頻詞提取,將其作為熱詞,發現輿論的焦點。高頻詞指的是文檔中出現頻率高且非無用的詞語,在一定程度上代表了文章的焦點。但是諸如“的”,“了”也是文章中經常出現的詞,它們對我們提取高頻詞產生了干擾且無用,無意義,稱為停用詞。
有時候并不出于做高頻詞提取的目的,而我們分詞后的下一步常常要做的就是向量化,進行文本分析的時候不需要這些停用詞,要想辦法去除。
所以出于上述兩種停用詞的使用目的,下述代碼也有兩種方式:
①對于TF-IDF,我們只需要告訴組件停用詞庫,它將自己載入詞庫并使用它,具體代碼為:
import jieba.analyse
jieba.analyse.set_stop_words("C:/Users/Administrator/Desktop/stop_words/stop_words.txt")
這里要注意,對于txt文件是用‘utf-8’來解碼的,所以還要注意下載的停用詞表的存儲方式,即:
這里編碼方式需要選擇UTF-8,否則會出現如下報錯:
②除了上一種涉及到tfidf的載入停用詞表的方式,還有如下方式,主要是將停用詞表輸入到代碼中為一個列表;然后對分詞結果進行篩選,如果分詞不在停用詞表中且不是換行符,就將詞和一個空格輸出:
import jieba
import jieba.analyse
stpwrd_dic = open("C:/Users/Administrator/Desktop/stop_words/stop_words.txt", encoding='UTF-8')
stpwrd_content = stpwrd_dic.read()
stpwrdlst = stpwrd_content.splitlines()
content="沙瑞金贊嘆易學習的胸懷了,是金山的百姓有福,可是這件事對李達康的觸動很大。易學習又回憶起他們三人分開的前一晚,大家一起喝酒話別,易學習被降職到道口縣當縣長,王大路下海經商,李達康連連賠禮道歉,覺得對不起大家,他最對不起的是王大路,就和易學習一起給王大路湊了5萬塊錢,王大路自己東挪西撮了5萬塊,開始下海經商。沒想到后來王大路竟然做得風生水起。沙瑞金覺得他們三人,在困難時期還能以沫相助,很不容易。"
tent=jieba.cut(content,cut_all=False)
stp=' '
for words in tent:
if words not in stpwrdlst:
if words!=' ':
stp+=words
stp+=' '
print(stp)
使用停用詞表后的代碼結果為:
可以看到,一些標點符號和停用詞被去除了,這里還是要注意一下編碼的問題,即open時需要encoding='UTF-8',否則會報錯。
四、原理淺析
jieba分詞結合了基于規則和基于統計兩類方法:
首先,基于前綴詞典進行詞圖掃描,生成句子中漢字所有可能成詞情況所構成的有向無環圖(DAG),前綴詞典就是詞典中的詞是按照前綴包含的順序排列。
比如這句話‘天使蘭超溫柔’
jieba 在其源碼中有一個 dict.txt 文件,基于這個文件生成一個 trie 樹,將需要進行分詞的句子生成有向無環圖 (DAG),通俗來說就是將需要分詞的句子對照已有的 trie 樹生成幾種可能的區分。像上圖,就是一個DAG,它的劃分結果是‘天 使 蘭 超 溫 柔’,jieba基于前綴詞典可以快速構建包含全部可能分詞結果的有向無環圖,上圖分詞結果只是其中的一條分詞路徑,‘有向’是指全部的路徑都起始于第一個字,止于最后一個字,無環是指節點之間不構成閉環。
然后,采用動態規劃查找最大概率路徑,找出基于詞頻的最大切分組合,并將其作為最終的分詞結果:
最后,基于未登錄詞,使用基于漢字成詞的hmm模型,采用維特比算法進行推導:
未登陸詞指的是在dict.txt里面沒有被記錄的詞,值得注意的是當我們把dict.txt中的詞語全部刪除,jieba依然能夠進行分詞,但是分出來的詞大部分長度都為2,其實這個時候使用的就是HMM來進行分詞了。
我們可以將中文的詞匯按照B(begin–開始的位置)E(end–結束的位置)M(middle–中間的位置)S(singgle–單獨成詞的位置,沒有前也沒有后)排列成一個序列,jieba中就是以這種形式來標記中文的詞語,舉個例子:“深圳”這個詞語可以被標記為BE,也就是深/B圳/E,其意義是深是開始的位置,圳是結束的位置,復雜一些的詞語“值得關注”會被標記為BMME,也就是開始,中間,中間,結束。
在jieba中對語料進行了訓練從而得到了三個概率表,通過訓練得到了概率表再加上viterbi算法就可以得到一個概率最大的BEMS序列, 按照B打頭, E結尾的方式, 對待分詞的句子重新組合, 就得到了分詞結果。
例如我們有一個待分詞的句子“全世界都在學中國話”,這句話可以得到一個BEMS序列 [S,B,E,S,S,S,B,E,S](注意這個序列是一個假設,不一定正確),接下來我們將序列中的BE放在一起得到一個詞,單獨的S獨立出來,那么我們就可以得到這樣的一個分詞結果“全/S 世界/BE 都/S 在/S 學/S 中國/BE 話/S”這樣我們就得到了一個較為準確的分詞結果。
總結
以上是生活随笔為你收集整理的NLP(一):jieba分词的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 趣文:如果编程语言是车
- 下一篇: 写给年轻程序员的一封信