文|一魚數據
上節課,我們學習了自然語言處理課程(一):自然語言處理在網文改編市場的應用,了解了相關的基礎理論。接下來,我們將要了解一些具體的、可操作的技術方法。
作為小說愛好者的你,是否有設想過通過一些計算機工具對小說做一些有趣的事情呢?閱讀本文,你可以了解到如何運用現在最流行、最容易運用的jieba分詞包,統計一個段落的詞頻,然后來通過詞頻推斷小說的關鍵情節、核心人物。
作為文本分析和情感分析最基礎的工作就是對文本進行分詞,后期的文本挖掘、情感分析、規律探尋等工作很大程度上取決於分詞的精確度。在當代的中文自然語言分析領域,Jieba分詞包因為它的簡易性和高效性被廣大工作者廣泛的運用。
值得一提的是,小編在網上做了調查,想對Jieba分詞包的作者SunJunyi做一個簡單的介紹,但無奈信息太少,也源於他本人很低調,沒有過多的信息,有興趣的朋友可以在鏈接https://github.com/fxsjy?tab=repositories通過郵件聯系到他本人(小編沒有嘗試過)。
本篇文章會在Jieba分詞包的運用原理以及實際運用進行介紹,並會分享我們在文本分析用到的實例。
原理介紹
在介紹Jieba分詞原理之前,我們先用最直接的思維角度來設想如果我們自己進行分詞,我們會如何去分詞。
舉個簡單的例子,我們有一句話是“我現在去公司開會“,人類最直觀的想法就是從左向右掃描此句,然后分詞成“我/現在/去/公司/開會”。但作為計算機機器,當人工智能還停留在我們的幻想時,我們能做的、可能就是給計算機一本詞典,讓它根據詞典來分詞。這樣的方法可以應用於大部分句子,但當遇到一詞多義、或者有雙重理解詞語組合的情況時,分析就變得不那么容易了。
例如‘松江大學城書店‘,正確的分詞方法應該是’松江/大學城/書店‘,但由於詞典里或許沒有大學城這個詞語的緣故,計算機會把詞分成’松江/大學/城/書店’,這樣的分詞就是錯誤的。Jieba分詞包針對這一類的問題,運用有效的統計模型與中文語言的特性相結合,將分詞的效果提升了很多檔次。
Jieba分詞包的高效首先離不開對語料庫的精心選擇。在作者SunJunyi通過大量的訓練之后,在名為dict.txt的文件里錄入了兩萬多條詞作為參考,進行最基本的布局。但是大家可以設想,假設我們是什么都不知道、只能通過查找這個字典來進行詞語歸類的機器人,我們每一次分句都要基本上閱讀上萬條詞語 ,我們的眼睛和大腦都會受不了。雖然計算機比人的效率高了數個數量級,但每一次進行如此大量的查找也會非常的耗時。
Jieba分詞包在這里運用到了數據結構里的trie(前綴樹或字典樹)對詞語進行高效的分類,便於查找。

如上圖所示,這就是最簡單的trie的原理在分詞上的運用:我們有Johnny、Joe、Jane和Jack四個名字,假設我們要讓計算機查找名字Jack是否存在,普通的方法來說,計算機可能會掃描所有的字符串,非常耗時低效,但trie的從上至下搜索、每一次只判定一個字母、如果某個特定的節點(node)的下一個節點(child node)不再符合搜索要求,那么搜索就會停止,這樣效率就會大大的提高。
此外,trie也結合了計算機領域另一個知識,名為有向無環圖(DAG),trie與有向無環圖的結合很高效的解決了第一段所提到的雙重理解詞語組合的問題。舉個例子:

通過設定,計算機自動識別出了兩種分詞方法,分別為’有/意見/分歧/’ 和 ‘有意/見/分歧’,這就是trie和DAG的最基本應用。
那么如何從這兩個切分組合中篩選出一個更優的呢?這里就要用到一點點統計學的知識,既然一個句子有多個分詞方式,那么我們就應該選擇使得這個句子出現概率最大的切分組合。學過概率論與數理統計的同學可以很容易得把這個思想同極大似然估計(Maximum Likelihood Estimation)聯系起來。
在制定了切分方案的評價准則后, jieba分詞包運用了動態規划來找出詞頻最大切分組合。動態規划涉及到很多內容,我們就不做詳細的介紹,但它在這里起到的效果很通俗易懂。舉個例子:假設一個句子K,它可以被計算機隨機分為a,b,c三種分詞形式,那么計算機就通過大量的運算,在標准正確的情況下取概率最大的一種分詞形式。在這里,動態規划法對分詞分好之后每個詞語出現的頻率進行了統計(頻率=次數/總數),得到最大的概率切分組合從而完成分詞。
可能還有的同學會問,那么如果有沒有錄入字典的詞該怎么辦呢?這里Jieba分詞包用到了HMM模型和經典的維特比(Viterbi)算法,將未登錄的詞語分為開始、中間、結束和單獨成詞四種分類來自動分詞。總的來說,Jieba分詞包在擁有HMM模型和維特比算法以后,即使詞典一個詞都沒有也能夠進行大致的分詞,只是准確率會有所降低。
實際運用
Jieba 分詞細分為了三種,分為精確模式、全模式和搜索引擎模式(在實際運用會進行介紹),每一個模式都有着自己的特定用法,但大體差別不大,這里我們用Python為大家進行演示。

其中word1為全模式,word2為精確模式,word3為搜索引擎模式,在這個例子里面,全模式和搜索引擎模式是差不多的,都將所有的詞組展示了出來,但順序有所不同,精確模式只輸出了句子分詞最大可能性的一組。
這里需要注意的一點:所有的word1,word2,word3並不是一個字符串,而是一個迭代器(iterator),要通過print(‘ ‘.join(word1))的方式正常輸出中文字符,否則直接print只會出現對象的地址。如果嫌這個很麻煩,也可以直接使用lcut()或lcut_for_search()直接將分詞放進一個list,直接運用。

此外,我們還可以用load_userdict(file_name)添加自己想添加的字典,讓判斷變得更加的准確,示例如下:
當我們只用jieba的默認字典時,牛肉和餅干被默認為兩個詞語。然后我們在與程序文件相同目錄的地方創建一個文本文檔,將’牛肉餅干’輸入進去,作為一個詞組,得到的分詞就不一樣了。當然,我們也可以直接添加“牛肉餅干”這個詞。

除此之外,Jieba分詞包還支持一些其他的功能,我們在這里就不一一的介紹了,詳情可以參考jieba在github上面README.txt的詳細介紹。
實例分享
在進行了較為枯燥的介紹后,終於來到了好玩又令人激動地實例分享,我們這次對紅樓夢的幾個段落進行文本統計,所需要的工具包為jieba。
首先我們要做的是導出txt文件里紅樓夢的文本,分割為短句,並對每個短句進行一定的處理,保證文本的整潔和規律。具體步驟為:
1. 依換行符,句號,逗號等分隔符將全文分為短句。
2. 刪除每個短句前后的空格。
3. 剔除沒有任何文字和數字的短句。
然后我們就可以進行分詞了,這里的后半部分小編將字典進行了排序,不是本文的重點,重點是要知道怎么利用jieba進行分詞。這里小編把每一個短句切分為詞語,並把這個結果寫入一個字典里。如果字典已經有這個詞了,那么這個詞對應的頻數+1,如果沒有,那么就添加這一個詞,頻數設置為1。

最后就是將結果持久化存儲到本地了,這里就不做詳細的介紹了,有興趣的可以下去了解