筆記轉載於GitHub項目:https://github.com/NLP-LOVE/Introduction-NLP
9. 信息抽取
信息抽取是一個寬泛的概念,指的是從非結構化文本中提取結構化信息的一類技術。這類技術依然分爲基於規則的正則匹配、有監督學習和無監督學習等各種實現方法。我們將使用一些簡單實用的無監督學習方法。由於不需要標註語料庫,所以可以利用海量的非結構化文本。
本章按照顆粒度從小到大的順序,介紹抽取新詞、關鍵詞、關鍵短語和關鍵句的無監督學習方法。
9.1 新詞提取
-
概述
新詞是一個相對的概念,每個人的標準都不一樣,所以我們這裏定義: 詞典之外的詞語(OOV)稱作新詞。
新詞的提取對中文分詞而言具有重要的意義,因爲語料庫的標註成本很高。那麼如何修訂領域詞典呢,此時,無監督的新詞提取算法就體現了現實意義。
-
基本原理
- 提取出大量文本(生語料)中的詞語,無論新舊。
- 用詞典過濾掉已有的詞語,於是得到新詞。
步驟 2 很容易,關鍵是步驟 1,如何無監督的提取出文本中的單詞。給定一段文本,隨機取一個片段,如果這個片段左右的搭配很豐富,並且片段內部成分搭配很固定,則可以認爲這是一個詞。將這樣的片段篩選出來,按照頻次由高到低排序,排在前面的有很高概率是詞。
如果文本足夠大,再用通用的詞典過濾掉“舊詞”,就可以得到“新詞”。
片段外部左右搭配的豐富程度,可以用信息熵來衡量,而片段內部搭配的固定程度可以用子序列的互信息來衡量。
-
信息熵
在信息論中,信息熵( entropy )指的是某條消息所含的信息量。它反映的是聽說某個消息之後,關於該事件的不確定性的減少量。比如拋硬幣之前,我們不知道“硬幣正反”這個事件的結果。但是一旦有人告訴我們“硬幣是正面”這條消息,我們對該次拋硬幣事件的不確定性立即降爲零,這種不確定性的減小量就是信息熵。公式如下:
給定字符串 S 作爲詞語備選,X 定義爲該字符串左邊可能出現的字符(左鄰字),則稱 H(X) 爲 S 的左信息熵,類似的,定義右信息熵 H(Y),例如下列句子:兩隻蝴蝶飛啊飛
這些蝴蝶飛走了
那麼對於字符串蝴蝶,它的左信息熵爲1,而右信息熵爲0。因爲生語料庫中蝴蝶的右鄰字一定是飛。假如我們再收集一些句子,比如“蝴蝶效應”“蝴蝶蛻變”之類,就會觀察到右信息熵會增大不少。
左右信息熵越大,說明字符串可能的搭配就越豐富,該字符串就是一個詞的可能性就越大。
光考慮左右信息熵是不夠的,比如“吃了一頓”“看了一遍”“睡了一晚”“去了一趟”中的了一的左右搭配也很豐富。爲了更好的效果,我們還必須考慮詞語內部片段的凝聚程度,這種凝聚程度由互信息衡量。
-
互信息
互信息指的是兩個離散型隨機變量 X 與 Y 相關程度的度量,定義如下:
互信息的定義可以用韋恩圖直觀表達:其中,左圓圈表示H(X),右圓圈表示H(Y)。它們的並集是聯合分佈的信息熵H(X,Y),差集有多件嫡,交集就是互信息。可見互信息越大,兩個隨機變量的關聯就越密切,或者說同時發生的可能性越大。
片段可能有多種組合方式,計算上可以選取所有組合方式中互信息最小的那一種爲代表。有了左右信息熵和互信息之後,將兩個指標低於一定閾值的片段過濾掉,剩下的片段按頻次降序排序,截取最高頻次的 N 個片段即完成了詞語提取流程。
-
實現
我們用四大名著來提起100個高頻詞。
代碼請見(語料庫自動下載): extract_word.py
https://github.com/NLP-LOVE/Introduction-NLP/tree/master/code/ch09/extract_word.py
運行結果如下:
雖然我們沒有在古典文學語料庫上進行訓練,但新詞識別模塊成功的識別出了麝月、高太尉等生僻詞語,該模塊也適用於微博等社交媒體的不規範文本。
9.2 關鍵詞提取
詞語顆粒度的信息抽取還存在另一個需求,即提取文章中重要的單詞,稱爲關鍵詞提起。關鍵詞也是一個沒有定量的標準,無法統一語料庫,所以就可以利用無監督學習來完成。
分別介紹詞頻、TF-IDF和TextRank算法,單文檔提起可以用詞頻和TextRank,多文檔可以使用TF-IDF來提取關鍵詞。
-
詞頻統計
關鍵詞通常在文章中反覆出現,爲了解釋關鍵詞,作者通常會反覆提及它們。通過統計文章中每種詞語的詞頻並排序,可以初步獲取部分關鍵詞。
不過文章中反覆出現的詞語卻不一定是關鍵詞,例如“的”。所以在統計詞頻之前需要去掉停用詞。
詞頻統計的流程一般是分詞、停用詞過濾、按詞頻取前 n 個。其中,求 m 個元素中前 n (n<=m) 大元素的問題通常通過最大堆解決,複雜度爲 O(mlogn)。HanLP代碼如下:
from pyhanlp import * TermFrequency = JClass('com.hankcs.hanlp.corpus.occurrence.TermFrequency') TermFrequencyCounter = JClass('com.hankcs.hanlp.mining.word.TermFrequencyCounter') if __name__ == '__main__': counter = TermFrequencyCounter() counter.add("加油加油中國隊!") # 第一個文檔 counter.add("中國觀衆高呼加油中國") # 第二個文檔 for termFrequency in counter: # 遍歷每個詞與詞頻 print("%s=%d" % (termFrequency.getTerm(), termFrequency.getFrequency())) print(counter.top(2)) # 取 top N # 根據詞頻提取關鍵詞 print('') print(TermFrequencyCounter.getKeywordList("女排奪冠,觀衆歡呼女排女排女排!", 3))
運行結果如下:
中國=2 中國隊=1 加油=3 觀衆=1 高呼=1 [加油=3, 中國=2] [女排, 觀衆, 歡呼]
用詞頻來提取關鍵詞有一個缺陷,那就是高頻詞並不等價於關鍵詞。比如在一個體育網站中,所有文章都是奧運會報道,導致“奧運會”詞頻最高,用戶希望通過關鍵詞看到每篇文章的特色。此時,TF-IDF 就派上用場了。
-
TF-IDF
TF-IDF (Term Frequency-lnverse Document Frequency,詞頻-倒排文檔頻次)是信息檢索中衡量一個詞語重要程度的統計指標,被廣泛用於Lucene、Solr、Elasticsearch 等搜索引擎。
相較於詞頻,TF-IDF 還綜合考慮詞語的稀有程度。在TF-IDF計算方法中,一個詞語的重要程度不光正比於它在文檔中的頻次,還反比於有多少文檔包含它。包含該詞語的文檔趣多,就說明它越寬泛, 越不能體現文檔的特色。 正是因爲需要考慮整個語料庫或文檔集合,所以TF-IDF在關鍵詞提取時屬於多文檔方法。
計算公式如下:
其中,t 代表單詞,d 代表文檔,TF(t,d) 代表 t 在 d 中出現頻次,DF(t) 代表有多少篇文檔包含 t。DF 的導數稱爲IDF,這也是 TF-IDF 得名的由來。當然,實際應用時做一些擴展,比如加一平滑、IDF取對數以防止浮點數下溢出。HanLP的示例如下:
from pyhanlp import * TfIdfCounter = JClass('com.hankcs.hanlp.mining.word.TfIdfCounter') if __name__ == '__main__': counter = TfIdfCounter() counter.add("《女排奪冠》", "女排北京奧運會奪冠") # 輸入多篇文檔 counter.add("《羽毛球男單》", "北京奧運會的羽毛球男單決賽") counter.add("《女排》", "中國隊女排奪北京奧運會金牌重返巔峯,觀衆歡呼女排女排女排!") counter.compute() # 輸入完畢 for id in counter.documents(): print(id + " : " + counter.getKeywordsOf(id, 3).toString()) # 根據每篇文檔的TF-IDF提取關鍵詞 # 根據語料庫已有的IDF信息爲語料庫之外的新文檔提取關鍵詞 print('') print(counter.getKeywords("奧運會反興奮劑", 2))
運行後如下:
《女排》 : [女排=5.150728289807123, 重返=1.6931471805599454, 巔峯=1.6931471805599454] 《女排奪冠》 : [奪冠=1.6931471805599454, 女排=1.2876820724517808, 奧運會=1.0] 《羽毛球男單》 : [決賽=1.6931471805599454, 羽毛球=1.6931471805599454, 男單=1.6931471805599454] [反, 興奮劑]
觀察輸出結果,可以看出 TF-IDF 有效的避免了給予“奧運會”這個寬泛的詞語過高的權重。
TF-IDF在大型語料庫上的統計類似於一種學習過程,假如我們沒有這麼大型的語料庫或者存儲IDF的內存,同時又想改善詞頻統計的效果該怎麼辦呢?此時可以使用TextRank算法。
-
TextRank
TextRank 是 PageRank 在文本中的應用,PageRank是一種用於排序網頁的隨機算法,它的工作原理是將互聯網看作有向圖,互聯網上的網頁視作節點,節點 Vi 到節點 Vj 的超鏈接視作有向邊,初始化時每個節點的權重 S(Vi) 都是1,以迭代的方式更新每個節點的權重。每次迭代權重的更新表達式如下:
其中 d 是一個介於 (0,1) 之間的常數因子,在PagRank中模擬用戶點擊鏈接從而跳出當前網站的概率,In(Vi) 表示鏈接到 Vi 的節點集合,Out(Vj) 表示從 Vj 出發鏈接到的節點集合。可見,開不是外鏈越多,網站的PageRank就越高。網站給別的網站做外鏈越多,每條外鏈的權重就越低。如果一個網站的外鏈都是這種權重很低的外鏈,那麼PageRank也會下降,造成不良反應。正所謂物以類聚,垃圾網站推薦的鏈接往往也是垃圾網站。因此PageRank能夠比較公正的反映網站的排名。將 PageRank 應用到關鍵詞提取,無非是將單詞視作節點而已,另外,每個單詞的外鏈來自自身前後固定大小的窗口內的所有單詞。
HanLP實現的代碼如下:
from pyhanlp import * """ 關鍵詞提取""" content = ( "程序員(英文Programmer)是從事程序開發、維護的專業人員。" "一般將程序員分爲程序設計人員和程序編碼人員," "但兩者的界限並不非常清楚,特別是在中國。" "軟件從業人員分爲初級程序員、高級程序員、系統" "分析員和項目經理四大類。") TextRankKeyword = JClass("com.hankcs.hanlp.summary.TextRankKeyword") keyword_list = HanLP.extractKeyword(content, 5) print(keyword_list)
運行結果如下:
[程序員, 程序, 分爲, 人員, 軟件]
9.3 短語提取
在信息抽取領域,另一項重要的任務就是提取中文短語,也即固定多字詞表達串的識別。短語提取經常用於搜索引擎的自動推薦,文檔的簡介生成等。
利用互信息和左右信息熵,我們可以輕鬆地將新詞提取算法拓展到短語提取。只需將新詞提取時的字符替換爲單詞, 字符串替換爲單詞列表即可。爲了得到單詞,我們依然需要進行中文分詞。 大多數時候, 停用詞對短語含義表達幫助不大,所以通常在分詞後過濾掉。
代碼如下:
from pyhanlp import *
""" 短語提取"""
text = '''
算法工程師
算法(Algorithm)是一系列解決問題的清晰指令,也就是說,能夠對一定規範的輸入,在有限時間內獲得所要求的輸出。
如果一個算法有缺陷,或不適合於某個問題,執行這個算法將不會解決這個問題。不同的算法可能用不同的時間、
空間或效率來完成同樣的任務。一個算法的優劣可以用空間複雜度與時間複雜度來衡量。算法工程師就是利用算法處理事物的人。
1職位簡介
算法工程師是一個非常高端的職位;
專業要求:計算機、電子、通信、數學等相關專業;
學歷要求:本科及其以上的學歷,大多數是碩士學歷及其以上;
語言要求:英語要求是熟練,基本上能閱讀國外專業書刊;
必須掌握計算機相關知識,熟練使用仿真工具MATLAB等,必須會一門編程語言。
2研究方向
視頻算法工程師、圖像處理算法工程師、音頻算法工程師 通信基帶算法工程師
3目前國內外狀況
目前國內從事算法研究的工程師不少,但是高級算法工程師卻很少,是一個非常緊缺的專業工程師。
算法工程師根據研究領域來分主要有音頻/視頻算法處理、圖像技術方面的二維信息算法處理和通信物理層、
雷達信號處理、生物醫學信號處理等領域的一維信息算法處理。
在計算機音視頻和圖形圖像技術等二維信息算法處理方面目前比較先進的視頻處理算法:機器視覺成爲此類算法研究的核心;
另外還有2D轉3D算法(2D-to-3D conversion),去隔行算法(de-interlacing),運動估計運動補償算法
(Motion estimation/Motion Compensation),去噪算法(Noise Reduction),縮放算法(scaling),
銳化處理算法(Sharpness),超分辨率算法(Super Resolution) 手勢識別(gesture recognition) 人臉識別(face recognition)。
在通信物理層等一維信息領域目前常用的算法:無線領域的RRM、RTT,傳送領域的調製解調、信道均衡、信號檢測、網絡優化、信號分解等。
另外數據挖掘、互聯網搜索算法也成爲當今的熱門方向。
算法工程師逐漸往人工智能方向發展。'''
phrase_list = HanLP.extractPhrase(text, 5)
print(phrase_list)
運行結果如下:
[算法工程師, 算法處理, 一維信息, 算法研究, 信號處理]
目前該模塊只支持提取二元語法短語。在另一些場合,關鍵詞或關鍵短語依然顯得碎片化,不足以表達完整的主題。這時通常提取中心句子作爲文章的簡短摘要,而關鍵句的提取依然是基於 PageRank 的拓展。
9.4 關鍵句提取
由於一篇文章中幾乎不可能出現相同的兩個句子,所以樸素的 PageRank 在句子顆粒度上行不通。爲了將 PageRank 利用到句子顆粒度上去,我們引人 BM25 算法衡量句子的相似度,改進鏈接的權重計算。這樣窗口的中心句與相鄰的句子間的鏈接變得有強有弱,相似的句子將得到更高的投票。而文章的中心句往往與其他解釋說明的句子存在較高的相似性,這恰好爲算法提供了落腳點。本節將先介紹BM25算法,後介紹TextRank在關鍵句提取中的應用。
-
BM25
在信息檢索領域中,BM25 是TF-IDF的一種改進變種。TF-IDF衡量的是單個詞語在文檔中的重要程度,而在搜索引擎中,查詢串(query)往往是由多個詞語構成的。如何衡量多個詞語與文檔的關聯程度,就是BM25所解決的問題。
形式化的定義 Q 爲查詢語句,由關鍵字 q1 到 qn 組成,D 爲一個被檢索的文檔,BM25度量如下:
-
TextRank
有了BM25算法之後,將一個句子視作查詢語句,相鄰的句子視作待查詢的文檔,就能得到它們之間的相似度。以此相似度作爲 PageRank 中的鏈接的權重,於是得到一種改進算法,稱爲TextRank。它的形式化計算方法如下:
其中,WS(Vi) 就是文檔中第 i 個句子的得分,重複迭代該表達式若干次之後得到最終的分值,排序後輸出前 N 個即得到關鍵句。代碼如下:from pyhanlp import * """自動摘要""" document = '''水利部水資源司司長陳明忠9月29日在國務院新聞辦舉行的新聞發佈會上透露, 根據剛剛完成了水資源管理制度的考覈,有部分省接近了紅線的指標, 有部分省超過紅線的指標。對一些超過紅線的地方,陳明忠表示,對一些取用水項目進行區域的限批, 嚴格地進行水資源論證和取水許可的批准。''' TextRankSentence = JClass("com.hankcs.hanlp.summary.TextRankSentence") sentence_list = HanLP.extractSummary(document, 3) print(sentence_list)
結果如下:
[嚴格地進行水資源論證和取水許可的批准, 水利部水資源司司長陳明忠9月29日在國務院新聞辦舉行的新聞發佈會上透露, 有部分省超過紅線的指標]
9.5 總結
我們看到,新詞提取與短語提取,關鍵詞與關鍵句的提取,在原理上都是同一種算法在不同文本顆粒度上的應用。值得一提的是, 這些算法都不需要標註語料的參與,滿足了人們“不勞而獲”的慾望。然而必須指出的是,這些算法的效果非常有限。對於同一個任務,監督學習方法的效果通常遠遠領先於無監督學習方法。
9.6 GitHub
HanLP何晗–《自然語言處理入門》筆記:
https://github.com/NLP-LOVE/Introduction-NLP
項目持續更新中…
目錄
章節 |
---|
第 1 章:新手上路 |
第 2 章:詞典分詞 |
第 3 章:二元語法與中文分詞 |
第 4 章:隱馬爾可夫模型與序列標註 |
第 5 章:感知機分類與序列標註 |
第 6 章:條件隨機場與序列標註 |
第 7 章:詞性標註 |
第 8 章:命名實體識別 |
第 9 章:信息抽取 |
第 10 章:文本聚類 |
第 11 章:文本分類 |
第 12 章:依存句法分析 |
第 13 章:深度學習與自然語言處理 |