當我寫下這篇文章的時候,我的內心是激動的,這是因為,自從去年6月份寫了文章利用關系抽取構建知識圖譜的一次嘗試 后,我就一直在試圖尋找一種在開放領域能夠進行三元組抽取的辦法,也有很多讀者問過我這方面的問題,今天,筆者將給出答復,雖然不是正確答案(現在也沒有正確答案),但至少,我寫下了自己的答案。
離我想出這個抽取系統雖然才過去不久,但我的心情,已經由開始的激動狂喜,轉化為后來的平淡,直到現在的不滿。事實證明,開放領域的三元組抽取實在太難,以筆者個人的努力和智商,實在沒法給出完美的答案,所以,文章的題目是嘗試,僅僅作為嘗試,並不能解決好這個問題。但,我還是想寫些什么,希望能夠對筆者有一點點啟發,同時,也是對自己近半年的探尋做一個總結。
關於三元組抽取的基本介紹和常用辦法,筆者之前已經在不少文章中描述過,這里不再過多介紹,有興趣的讀者可以參考文章利用關系抽取構建知識圖譜的一次嘗試 和 NLP(二十六)限定領域的三元組抽取的一次嘗試 。本文將會介紹筆者在開放領域做三元組抽取的一次嘗試。
本項目已經開源至Github,文章最后會給出相應的網址。本項目的項目結構如下:
本項目一共分為四部分,主要模塊介紹如下:
- extract_example: 利用訓練好的模型對基本小說和新聞進行三元組抽取,形成知識圖譜例子;
- sequence_labeling:訓練標注,對標注的實體數據進行序列標注算法訓練;
- spo_tagging_platform:標注平台,標注subject,predicate和object以及三元組是否有效;
- text_classification:文本分類,用於判別抽取的三元組是否有效。
本項目的抽取系統流程圖如下:
接下來筆者將逐一介紹。
標注平台
筆者用tornado搭建了簡易的標注平台,在標注頁面中,標注人員需要輸入標注的句子(句子級別的抽取)以及subject,predicate,object,點擊“顯示SPO”,將有效的三元組標注為1,無效的三元組標注為0。之所以采取這種標注方法,是因為我們可以在句子中標注subject,predicate,object,這些標注的實體就會形成可能的三元組組合,再利用0,1來標注這種三元組是否有效,這樣就能做到在開放領域進行三元組抽取。
一個簡單的標注例子如下:
再對以上的標注結果做一些說明,我們的標注是以句子為單位,進行句子級別的標注,不同要素在標注的時候加#區分,標注了兩個subject,1個predicate(共用)和2個object,其中predidate是這些subject和object公用的,所以只需要標注一次。這樣,點擊“顯示SPO”,一共會顯示4個三元組,s,p,o用#隔開,0,1表示是否是有效三元組,默認為0。
筆者利用空余時間,一共標注了3200多個樣本,對於序列標注來說,就是3200多個樣本,對於文本分類來說,就是9000多個樣本了。
序列標注
對於上述的標注例子,會形成如下的標注序列:
美 B-SUBJ
國 I-SUBJ
疾 I-SUBJ
控 I-SUBJ
中 I-SUBJ
心 I-SUBJ
主 B-PRED
任 I-PRED
雷 B-OBJ
德 I-OBJ
菲 I-OBJ
爾 I-OBJ
德 I-OBJ
( O
左 O
圈 O
) O
和 O
美 B-SUBJ
國 I-SUBJ
國 I-SUBJ
立 I-SUBJ
衛 I-SUBJ
生 I-SUBJ
研 I-SUBJ
究 I-SUBJ
院 I-SUBJ
過 I-SUBJ
敏 I-SUBJ
和 I-SUBJ
傳 I-SUBJ
染 I-SUBJ
病 I-SUBJ
研 I-SUBJ
究 I-SUBJ
所 I-SUBJ
主 B-PRED
任 I-PRED
福 B-OBJ
西 I-OBJ
( O
右 O
圈 O
) O
將數據集分為訓練集和測試集,比例為8:2.采用經典的深度學習模型ALBERT+Bi-LSTM+CRF進行實體識別,設置最大文本長度為128,訓練100個epoch。關於該模型的介紹,可以參考文章NLP(二十五)實現ALBERT+Bi-LSTM+CRF模型 。
在測試集上的訓練結果如下:
accuracy: 93.69%; precision: 76.26%; recall: 82.33%; FB1: 79.18
OBJ: precision: 80.47%; recall: 88.81%; FB1: 84.44 927
PRED: precision: 76.89%; recall: 83.69%; FB1: 80.14 1021
SUBJ: precision: 71.72%; recall: 75.32%; FB1: 73.48 983
在測試集上的總體F1值接近80%。
文本分類
關於文本分類,需要多做一些說明。
雖然本文的題目是關於在開發領域的三元組抽取的嘗試,但實際我在標注的時候,還是更多地標注人物頭銜,人物關系,公司與人的關系,影視劇主演、導演信息等。形成的有效的文本分類的樣本為9000多個,一共有關系1365個,數量最多的前20個關系如下圖:
以上述的標注數據為例,形成的標注數據如下:
美國疾控中心#主任#雷德菲爾德#1#美國疾控中心主任雷德菲爾德(左圈)和美國國立衛生研究院過敏和傳染病研究所主任福西(右圈)
美國疾控中心#主任#福西#0#美國疾控中心主任雷德菲爾德(左圈)和美國國立衛生研究院過敏和傳染病研究所主任福西(右圈)
美國國立衛生研究院過敏和傳染病研究所#主任#雷德菲爾德#0#美國疾控中心主任雷德菲爾德(左圈)和美國國立衛生研究院過敏和傳染病研究所主任福西(右圈)
美國國立衛生研究院過敏和傳染病研究所#主任#福西#1#美國疾控中心主任雷德菲爾德(左圈)和美國國立衛生研究院過敏和傳染病研究所主任福西(右圈)
在實際模型訓練的時候,會將原文中的subject用S*len(subject)代替,predicate用P,object用O。
將數據集分為訓練集和測試集,比例為8:2。采用經典的深度學習模型ALBERT+Bi-GRU+ATT+FC,設置文本的最大長度為為128,訓練30個epoch,采用early stopping機制,訓練過程的loss和acc圖像如下:
最終在測試集上的accuracy約為96%。
新數據進行三元組抽取
上述的模型訓練完畢后,我們就可以將其封裝成HTTP服務。對於新輸入的句子,我們先利用序列標注模型預測出其中的subject,predicate和object,組合成三元組與句子的拼接,輸入到文本分類模型,判別該三元組是否有效,0為無效,1為有效。
從網上找幾個例子,預測的結果如下:
extract_example
目錄中為抽取的效果,包括幾本小說和一些新聞上的效果,關於這方面的演示,可以參考另一個項目:https://github.com/percent4/knowledge_graph_demo 。也可以參考文章知識圖譜構建舉例 中給出的幾個知識圖譜的建構的例子。
總結
本文寫的過程較為簡單,也沒有代碼,這是因為筆者在之前的文章中做了大量的鋪墊,主要是集中在模型方面。況且,這個項目比較大,也不適合在這里詳細講述,筆者只在這里給出思路和大概的處理流程,具體的實現代碼可以參考下方的Github地址。
在實際的抽取過程中,一些句子也存在抽取出大量無用的三元組的情況,導致召回率高,這是因為本項目針對的是開放領域的三元組抽取,因此效果比不會有想象中的那么好,提升抽取效果的辦法如下:
- 增加數據標注量,目前序列標注算法的樣本僅3200多個;
- 模型方面:現在是pipeline形式,各自的效果還行,但總體上不如Joint形式好;
- 對於自己想抽的其他三元組的情形,建議增加這方面的標注;
- 文本預測耗時長(該問題已經解決)。
本項目作為筆者在開放領域的三元組抽取的一次嘗試,在此之前關於這方面的文章或者項目還很少,因此可以說是探索階段。
源碼和數據已經在Github項目中給出,網址為 https://github.com/percent4/spo_extract_platform 。
本人的微信公眾號為Python爬蟲與算法
,歡迎關注~
參考文獻
- 利用關系抽取構建知識圖譜的一次嘗試: https://www.cnblogs.com/jclian91/p/11107323.html
- NLP(二十六)限定領域的三元組抽取的一次嘗試: https://blog.csdn.net/jclian91/article/details/104874488
- NLP(二十五)實現ALBERT+Bi-LSTM+CRF模型: https://blog.csdn.net/jclian91/article/details/104826655
- 知識圖譜構建舉例: https://blog.csdn.net/jclian91/article/details/104685424
- NLP(二十一)人物關系抽取的一次實戰:https://blog.csdn.net/jclian91/article/details/104380371
- 《知識圖譜 方法、實踐與應用》 王昊奮、漆桂林、陳華鈞著,中國工信出版集團、電子工業出版社出版。