昨晚我們又做了一次技術分享,繼續上次技術分享的話題“文字資料的處理”。上次,我們分享了文字處理的方方面面的知識點,比較巨集觀,這次我們就其中的一點“分詞”展開。
一、為什麼要分詞
“行文如流水”形容的是詩文、書法自然流暢不受拘束。這裡我們借用一下就是,中文句子詞彙之間如流水般無縫,不像英文那樣單詞之間用空格分開。比如:
中文:我在猿人學網站上學Python
英文:I learn Python on YuanRenXue.
在程式裡,從英文中得到一個一個單詞很簡單,用Python字串的split()函式就可以搞定。而對於中文做同樣的事情就比較難了,這時候我們就需要一個分詞程式專門搞這件事。
詞彙是語義表達的基本單位。詞語比單個字表達的意思更為精準。在搜尋引擎裡面,建立倒排索引的時候,需要對文字進行分割為一個個的語素,是分成一個一個的字好呢,還是分割成一個個詞好呢?我們來看看下面的例子。
首先,我們先簡單理解一下“倒排索引”這個概念。我們可以把它類比成一個Python的字典,key是索引的語素(字或詞),value是一個包含這個語素的文件ID的列表。下面我們對“我早上在海邊跑步”這句話進行分割、索引,假設這句話的文件ID是1。
按字分割:我/早/上/在/海/邊/跑/步
索引:
在這個索引裡面搜“上海”,先把查詢詞按照索引時同樣的方法分割為“上”和“海”兩個字,然後分別搜這兩個字,索引裡面都包含這兩個字,它們都對應這ID為1的文件,也就是搜尋到了文件ID為1的文件。但是,這句“我早上在海邊跑步”跟“上海”是沒什麼關心的。
也就是說,按字分割索引會讓搜尋引擎搜出很多不相關的結果出來。那麼,按詞索引呢?
按詞分割:我/早上/在/海邊/跑步
建立索引:
從這個索引裡面找“上海”就不能找到,從而不會返回不相關的結果。
二、分詞的原理
分詞是一個技術活也是一個累活兒。如果分詞是建立在新聞類的語料基礎上的,它對其它領域比如化工、醫學等等領域的文字的分詞效果往往不會好。這就需要我們對行業領域詞彙進行收集,加入到分詞詞典中,才能得到更好的效果,這個過程是比較累人的。
分詞的方法一般有以下幾種:
1、基於詞典的方法
這個方法樸素而快速,但不能很好的解決歧義和未收錄詞。歧義就是下面這種句子根據詞典可以有多種分割方法:
“結婚/的/和/尚未/結婚/的”
“結婚/的/和尚/未/結婚/的”
未收錄詞就是分詞詞典沒有包含的那些詞,這個問題可以通過不斷擴充套件詞典在某種程度上解決。
2、機器學習的方法
首先,要人工標註大批量的語料給機器學習演算法進行學習。標註的過程要耗費大量人力,標註的語料越多,機器學習的效果越好。機器學習的方法有HMM、CRF,以及近年流行的深度學習。它對歧義和未收錄詞的問題有較好的解決。但是,大量領域語料的缺失,也導致它不能很好的直接應用於其它專業領域。
三、jieba分詞工具
上次技術分享中,我們介紹了多款分詞工具。jieba作為一個純Python實現的工具,使用起來非常方便。它支援簡體和繁體分詞,也可以自定義詞典方便我們擴充套件領域詞。
結巴有三種分詞模式:
- 精確模式:適合文字分析。此法最常用
- 全模式,把句子中所有可能的詞都列出來。基本沒啥用
- 搜尋引擎模式:把長詞切分為短詞,讓搜尋引擎提高召回率。建立搜尋引擎的索引時用
安裝jieba很簡單:
pip install jieba
使用結巴進行分詞主要有兩個函式:
jieba.cut(text, cut_all=False, HMM=True)
jieba.cut_for_search(sentence, HMM=True)
其中,cut()函式最為常用。引數cut_all=True的話就開啟了全模式,這種模式幾乎不需要。預設的HMM=True會使用HMM模型嘗試檢測未登入詞。
寫個簡單的程式來測試一下幾種不同的分詞模式:
得到的結果如下:
精確模式:
猿人/ 學是/ 一個/ 學習/ Python/ 的/ 網站
全模式:
猿人/ 人學/ 是/ 一個/ 學習/ Python/ 的/ 網站
搜尋引擎模式:
猿人/ 學是/ 一個/ 學習/ Python/ 的/ 網站
精確模式下,會把“學是”當做一個詞分出來,這就是HMM計算的結果,當然對於這個例子,它計算錯了。
“猿人學”應該是一個詞,但它沒有分出來。這個時候我們就需要自定義詞典。
新增自定義的詞,有兩種方法:
(1)通過函式新增:
jieba.add_word(‘猿人學’, freq=5, tag=’n’)
可以多次呼叫這個函式,新增更多的詞。
(2)通過詞典檔案:
jieba.load_userdict(file_name)
file_name就是一個詞典檔案的路徑,它是一個文字檔案,每行一個詞,後面可以跟著它的頻率和詞性:
猿人學 8 n
js逆向 7
APP脫殼 n
非同步IO
詞性標註
jieba支援詞性標註,具體在它的子模組 jieba.posseg
import jieba.posseg as pseg
words = pseg.cut('我在猿人學學Python')
for word, flag in words:
print('{} {}'.format(word, flag))
我 r
在 p
猿人學 n
學 n
Python eng
詞性標註可以幫助我們更好的篩選文章主題詞(或者叫關鍵詞)。比如,介詞、數量詞不然名詞、動詞的意義更豐富,提取關鍵詞時可以對名詞等賦予更高的權重。
主題詞提取
jieba提供的主題詞提取的功能,具體在 jibba.analyse 子模組。它有兩種演算法的實現,分別是TF-IDF演算法和TextRank演算法。兩者的效果差不多,但後者計算量大很多,比較慢。所以,推薦使用前者。
TF-IDF演算法
jieba.analyse.extract_tags(
text,
topK=20,
withWeight=False,
allowPOS=())
text 為待提取的文字
topK 為返回幾個 TF/IDF 權重最大的關鍵詞,預設值為 20
withWeight 為是否一併返回關鍵詞權重值,預設值為 False
allowPOS 僅包括指定詞性的詞,預設值為空,即不篩選詞-權重
TextRank演算法
jieba.analyse.textrank(
text,
topK=20,
withWeight=False,
allowPOS=('ns', 'n', 'vn', 'v'))
直接使用,介面相同,注意預設過濾詞性。
四、詞雲圖:視覺化主題詞
前面我們通過jieba提取了文章的主題詞,可以使用“詞雲圖”這種方法把它視覺化的表現出來。
Python有個畫詞雲圖的第三方模組:wordcloud。用pip直接安裝:
pip install wordcloud
使用它主要有兩個類:
WordCloud([font_path, width, height, …])
畫詞雲圖的類
ImageColorGenerator(image[, default_color])
從一張彩色圖片中生成詞雲圖的顏色
使用WordCloud類進行詞雲圖繪製過程,需要注意的地方:
中文字型 : 必須指定中文字型,不然中文就畫不出來。
mask :以圖片物體形狀繪製詞雲圖。非物體形狀部分為白色,顏色值為#FFF 或 #FFFFFF
圖片顏色->字型顏色:使用ImageColorGenerator 從mamsk圖片提取顏色,把對應位置的字型顏色設定為同樣的顏色。
下面,我們以Python的logo作為詞雲圖形狀進行繪製。
文章內容是猿人學網站上的文章《大規模非同步新聞爬蟲的實現思路》,通過jieba提取主題詞,然後進行繪製。程式碼如下 :
執行這段程式碼後,生成了兩個詞雲圖,第一張是隨機生成的字型顏色:
第二張是根據Python logo 圖片中的顏色繪製字型顏色:
如果你選擇色彩更豐富的圖片,繪製出來的詞雲圖色彩也會更豐富。
這次技術分享,我們把jieba分詞的使用結合例項介紹給大家,最後使用wordcloud做了主題詞的視覺化呈現。
我的公眾號:猿人學 Python 上會分享更多心得體會,敬請關注。
***版權申明:若沒有特殊說明,文章皆是猿人學 yuanrenxue.com 原創,沒有猿人學授權,請勿以任何形式轉載。***