如何用Python提取中文關鍵詞?

本文一步步爲你演示,如何用Python從中文文本中提取關鍵詞。若是你須要對長文「觀其大略」,不妨嘗試一下。python

2017-12-07-20-38-22-7-426487.png

需求

好友最近對天然語言處理感興趣,由於他打算利用自動化方法從長文本里提取關鍵詞,來肯定主題。git

他向我詢問方法,我推薦他閱讀個人那篇《如何用Python從海量文本提取主題?》。github

看過以後,他表示頗有收穫,可是應用場景和他本身的需求有些區別web

如何用Python從海量文本提取主題?》一文面對的是大量的文檔,利用主題發現功能對文章聚類。而他不須要處理不少的文檔,也沒有聚類的需求,可是須要處理的每篇文檔都很長,但願經過自動化方法從長文提取關鍵詞,以觀其大略。算法

我忽然發現,以前竟然忘了寫文,介紹單一文本關鍵詞的提取方法。微信

雖然這個功能實現起來並不複雜,可是其中也有些坑,須要避免踩進去的。編輯器

經過本文,我一步步爲你演示如何用Python實現中文關鍵詞提取這一功能。工具

環境

Python

第一步是安裝Python運行環境。咱們使用集成環境Anaconda。post

請到這個網址 下載最新版的Anaconda。下拉頁面,找到下載位置。根據你目前使用的系統,網站會自動推薦給你適合的版本下載。我使用的是macOS,下載文件格式爲pkg。學習

2017-12-03-22-19-31-2-856072.png

下載頁面區左側是Python 3.6版,右側是2.7版。請選擇2.7版本。

雙擊下載後的pkg文件,根據中文提示一步步安裝便可。

2017-12-03-22-19-31-2-856170.jpeg

樣例

我專門爲你準備了一個github項目,存放本文的配套源代碼和數據。請從這個地址下載壓縮包文件,而後解壓。

解壓後的目錄名稱爲demo-keyword-extraction-master,樣例目錄包含如下內容:

2017-12-7_21-24-56_snapshots-01.jpg

除了README.md這個github項目默認說明文件外,目錄下還有兩個文件,分別是數據文件sample.txt和程序源代碼文件demo-extract-keyword.ipynb。

結巴分詞

咱們使用的關鍵詞提取工具爲結巴分詞

以前在《如何用Python作中文分詞?》一文中,咱們曾經使用過該工具爲中文語句作分詞。此次咱們使用的,是它的另外一項功能,即關鍵詞提取。

請進入終端,使用cd命令進入解壓後的文件夾demo-keyword-extraction-master,輸入如下命令:

pip install jieba
複製代碼

好了,軟件包工具也已經準備就緒。下面咱們執行

jupyter notebook
複製代碼

進入到Jupyter筆記本環境。

image.png

到這裏,環境已經準備好了,咱們下面來介紹本文使用的中文文本數據。

數據

一開始,我還曾爲尋找現成的中文文本發愁。

網上能夠找到的中文文本浩如煙海。

可是拿來作演示,是否會有版權問題,我就不肯定了。萬一把哪位你們之做拿來作了分析,人家可能就要過問一句「這電子版你是從哪裏搞到的啊?」

萬一再所以提出訴訟,我可沒法招架。

後來發現,我這簡直就是自尋煩惱——找別人的文本幹什麼?用我本身的不就行了?

這一年多以來,我寫的文章已有90多篇,總字數已經超過了27萬。

image.png

我特地從中找了一篇非技術性的,以免提取出的關鍵詞全都是Python命令。

我選取的,是去年的那篇《網約車司機二三事》。

image.png

這篇文章,講的都是些比較有趣的小故事。

我從網頁上摘取文字,存儲到sample.txt中。

注意,這裏是很容易踩坑的地方。在夏天的一次工做坊教學中,好幾位同窗由於從網上摘取中文文本出現問題,卡住很長時間。

這是由於不一樣於英語,漢字有編碼問題。不一樣系統都有不一樣的默認編碼,不一樣版本的Python接受的編碼也不一樣。你從網上下載的文本文件,也可能與你係統的編碼不統一。

image.png

不論如何,這些因素都有可能致使你打開後的文本里,處處都是看不懂的亂碼。

於是,正確的使用中文文本數據方式,是你在Jupyter Notebook裏面,新建一個文本文件。

image.png

而後,會出現如下的空白文件。

image.png

把你從別處下載的文本,用任意一種能正常顯示的編輯器打開,而後拷貝所有內容,粘貼到這個空白文本文件中,就能避免編碼錯亂。

避開了這個坑,能夠爲你節省不少沒必要要的煩惱嘗試。

好了,知道了這個竅門,下面你就能愉快地進行關鍵詞提取了。

執行

回到Jupyter Notebook的主界面,點擊demo-extract-keyword.ipynb,你就能看到源碼了。

image.png

對,你沒看錯。只須要這短短的4個語句,就能完成兩種不一樣方式(TF-idf與TextRank)的關鍵詞提取。

本部分咱們先講解執行步驟。不一樣關鍵詞提取方法的原理,咱們放在後面介紹。

首先咱們從結巴分詞的分析工具箱裏導入全部的關鍵詞提取功能。

from jieba.analyse import *
複製代碼

在對應的語句上,按下Shift+Enter組合按鍵,就能夠執行語句,獲取結果了。

而後,讓Python打開咱們的樣例文本文件,而且讀入其中的所有內容到data變量。

with open('sample.txt') as f:
    data = f.read()
複製代碼

使用TF-idf方式提取關鍵詞和權重,而且依次顯示出來。若是你不作特殊指定的話,默認顯示數量爲20個關鍵詞。

for keyword, weight in extract_tags(data, withWeight=True):
    print('%s %s' % (keyword, weight))
複製代碼

顯示內容以前,會有一些提示,不要管它。

Building prefix dict from the default dictionary ...
Loading model from cache /var/folders/8s/k8yr4zy52q1dh107gjx280mw0000gn/T/jieba.cache
Loading model cost 0.547 seconds.
Prefix dict has been built succesfully.
複製代碼

而後列表就出來了:

優步 0.280875594782
司機 0.119951947597
乘客 0.105486129485
師傅 0.0958888107815
張師傅 0.0838162334963
目的地 0.0753618512886
網約車 0.0702188986954
姐姐 0.0683412127766
本身 0.0672533110661
上車 0.0623276916308
活兒 0.0600134354214
天津 0.0569158056792
10 0.0526641740216
開優步 0.0526641740216
事兒 0.048554456767
李師傅 0.0485035501943
天津人 0.0482653686026
繞路 0.0478244723097
出租車 0.0448480260748
時候 0.0440840298591
複製代碼

我看了一下,以爲關鍵詞提取仍是比較靠譜的。固然,其中也混入了個數字10,好在無傷大雅。

若是你須要修改關鍵詞數量,就須要指定topK參數。例如你要輸出10個關鍵詞,能夠這樣執行:

for keyword, weight in extract_tags(data, topK=10, withWeight=True):
    print('%s %s' % (keyword, weight))
複製代碼

下面咱們嘗試另外一種關鍵詞提取方式——TextRank。

for keyword, weight in textrank(data, withWeight=True):
    print('%s %s' % (keyword, weight))
複製代碼

關鍵詞提取結果以下:

優步 1.0
司機 0.749405996648
乘客 0.594284506457
姐姐 0.485458741991
天津 0.451113490366
目的地 0.429410027466
時候 0.418083863303
做者 0.416903838153
沒有 0.357764515052
活兒 0.291371566494
上車 0.277010013884
繞路 0.274608592084
轉載 0.271932903186
出來 0.242580745393
出租 0.238639889991
事兒 0.228700322713
單數 0.213450680366
出租車 0.212049665481
拉門 0.205816713637
跟着 0.20513470986
複製代碼

注意此次提取的結果,與TF-idf的結果有區別。至少,那個很突兀的「10」不見了。

可是,這是否是意味着TextRank方法必定優於TF-idf呢?

這個問題,留做思考題,但願在你認真閱讀了後面的原理部分以後,可以獨立作出解答。

若是你只須要應用本方法解決實際問題,那麼請跳過原理部分,直接看討論吧。

原理

咱們簡要講解一下,前文出現的2種不一樣關鍵詞提取方式——TF-idf和TextRank的基本原理。

爲了避免讓你們感到枯燥,這裏我們就不使用數學公式了。後文我會給出相關的資料連接。若是你對細節感興趣,歡迎按圖索驥,查閱學習。

先說TF-idf。

它的全稱是 Term Frequency - inverse document frequency。中間有個連字符,左右兩側各是一部分,共同結合起來,決定某個詞的重要程度。

第一部分,就是詞頻(Term Frequency),即某個詞語出現的頻率。

咱們常說「重要的事說三遍」。

一樣的道理,某個詞語出現的次數多,也就說明這個詞語重要性可能會很高。

可是,這只是可能性,並不絕對。

例如現代漢語中的許多虛詞——「的,地,得」,古漢語中的許多句尾詞「之、乎、者、也、兮」,這些詞在文中可能出現許屢次,可是它們顯然不是關鍵詞。

這就是爲何咱們在判斷關鍵詞的時候,須要第二部分(idf)配合。

逆文檔頻率(inverse document frequency)首先計算某個詞在各文檔中出現的頻率。假設一共有10篇文檔,其中某個詞A在其中10篇文章中都出先過,另外一個詞B只在其中3篇文中出現。請問哪個詞更關鍵?

給你一分鐘思考一下,而後繼續讀。

公佈答案時間到。

答案是B更關鍵。

A可能就是虛詞,或者所有文檔共享的主題詞。而B只在3篇文檔中出現,所以頗有多是個關鍵詞。

逆文檔頻率就是把這種文檔頻率取倒數。這樣第一部分和第二部分都是越高越好。兩者都高,就頗有多是關鍵詞了。

TF-idf講完了,下面咱們說說TextRank。

相對於TF-idf,TextRank要顯得更加複雜一些。它不是簡單作加減乘除運算,而是基於圖的計算。

下圖是原始文獻中的示例圖。

image.png

TextRank首先會提取詞彙,造成節點;而後依據詞彙的關聯,創建連接。

依照鏈接節點的多少,給每一個節點賦予一個初始的權重數值。

而後就開始迭代。

根據某個詞所鏈接全部詞彙的權重,從新計算該詞彙的權重,而後把從新計算的權重傳遞下去。直到這種變化達到均衡態,權重數值再也不發生改變。這與Google的網頁排名算法PageRank,在思想上是一致的。

image.png

根據最後的權重值,取其中排列靠前的詞彙,做爲關鍵詞提取結果。

若是你對原始文獻感興趣,請參考如下連接:

討論

小結一下,本文探討了如何用Python對中文文本作關鍵詞提取。具體而言,咱們分別使用了TF-idf和TextRank方法,兩者提取關鍵詞的結果可能會有區別。

你作過中文關鍵詞提取嗎?使用的是什麼工具?它的效果如何?有沒有比本文更高效的方法?歡迎留言,把你的經驗和思考分享給你們,咱們一塊兒交流討論。

喜歡請點贊。還能夠微信關注和置頂個人公衆號「玉樹芝蘭」(nkwangshuyi)

若是你對數據科學感興趣,不妨閱讀個人系列教程索引貼《如何高效入門數據科學?》,裏面還有更多的有趣問題及解法。

相關文章
相關標籤/搜索