1. 程式人生 > >NLP(二十七)開放領域的三元組抽取的一次嘗試

NLP(二十七)開放領域的三元組抽取的一次嘗試

  當我寫下這篇文章的時候,我的內心是激動的,這是因為,自從去年6月份寫了文章[利用關係抽取構建知識圖譜的一次嘗試](https://www.cnblogs.com/jclian91/p/11107323.html) 後,我就一直在試圖尋找一種在開放領域能夠進行三元組抽取的辦法,也有很多讀者問過我這方面的問題,今天,筆者將給出答覆,雖然不是正確答案(現在也沒有正確答案),但至少,我寫下了自己的答案。   離我想出這個抽取系統雖然才過去不久,但我的心情,已經由開始的激動狂喜,轉化為後來的平淡,直到現在的不滿。事實證明,開放領域的三元組抽取實在太難,以筆者個人的努力和智商,實在沒法給出完美的答案,所以,文章的題目是嘗試,僅僅作為嘗試,並不能解決好這個問題。但,我還是想寫些什麼,希望能夠對筆者有一點點啟發,同時,也是對自己近半年的探尋做一個總結。   關於三元組抽取的基本介紹和常用辦法,筆者之前已經在不少文章中描述過,這裡不再過多介紹,有興趣的讀者可以參考文章[利用關係抽取構建知識圖譜的一次嘗試](https://www.cnblogs.com/jclian91/p/11107323.html) 和 [NLP(二十六)限定領域的三元組抽取的一次嘗試](https://blog.csdn.net/jclian91/article/details/104874488) 。本文將會介紹筆者在開放領域做三元組抽取的一次嘗試。    本專案已經開源至Github,文章最後會給出相應的網址。本專案的專案結構如下: ![專案結構](https://img-blog.csdnimg.cn/20200320153327338.png) 本專案一共分為四部分,主要模組介紹如下: - extract_example: 利用訓練好的模型對基本小說和新聞進行三元組抽取,形成知識圖譜例子; - sequence_labeling:訓練標註,對標註的實體資料進行序列標註演算法訓練; - spo_tagging_platform:標註平臺,標註subject,predicate和object以及三元組是否有效; - text_classification:文字分類,用於判別抽取的三元組是否有效。   本專案的抽取系統流程圖如下: ![抽取系統流程圖](https://img-blog.csdnimg.cn/20200320162852951.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2pjbGlhbjkx,size_16,color_FFFFFF,t_70)   接下來筆者將逐一介紹。 ### 標註平臺   筆者用tornado搭建了簡易的標註平臺,在標註頁面中,標註人員需要輸入標註的句子(句子級別的抽取)以及subject,predicate,object,點選“顯示SPO”,將有效的三元組標註為1,無效的三元組標註為0。之所以採取這種標註方法,是因為我們可以在句子中標註subject,predicate,object,這些標註的實體就會形成可能的三元組組合,再利用0,1來標註這種三元組是否有效,這樣就能做到在開放領域進行三元組抽取。   一個簡單的標註例子如下: ![標註例子](https://img-blog.csdnimg.cn/20200320170755153.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2pjbGlhbjkx,size_16,color_FFFFFF,t_70) 再對以上的標註結果做一些說明,我們的標註是以句子為單位,進行句子級別的標註,不同要素在標註的時候加#區分,標註了兩個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模型](https://blog.csdn.net/jclian91/article/details/104826655) 。   在測試集上的訓練結果如下: ``` 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個關係如下圖: ![數量最多的20個關係](https://img-blog.csdnimg.cn/20200320172641894.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2pjbGlhbjkx,size_16,color_FFFFFF,t_70)   以上述的標註資料為例,形成的標註資料如下: ``` 美國疾控中心#主任#雷德菲爾德#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影象如下: ![訓練過程的loss和acc影象](https://img-blog.csdnimg.cn/20200320173129694.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2pjbGlhbjkx,size_16,color_FFFFFF,t_70) 最終在測試集上的accuracy約為96%。 ### 新資料進行三元組抽取   上述的模型訓練完畢後,我們就可以將其封裝成HTTP服務。對於新輸入的句子,我們先利用序列標註模型預測出其中的subject,predicate和object,組合成三元組與句子的拼接,輸入到文字分類模型,判別該三元組是否有效,0為無效,1為有效。   從網上找幾個例子,預測的結果如下: ![例子1](https://img-blog.csdnimg.cn/2020032017361981.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2pjbGlhbjkx,size_16,color_FFFFFF,t_70) ![例子2](https://img-blog.csdnimg.cn/20200320173633503.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2pjbGlhbjkx,size_16,color_FFFFFF,t_70) ![例子3](https://img-blog.csdnimg.cn/20200320173652878.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2pjbGlhbjkx,size_16,color_FFFFFF,t_70)   `extract_example`目錄中為抽取的效果,包括幾本小說和一些新聞上的效果,關於這方面的演示,可以參考另一個專案:[https://github.com/percent4/knowledge_graph_demo](https://github.com/percent4/knowledge_graph_demo) 。也可以參考文章[知識圖譜構建舉例](https://blog.csdn.net/jclian91/article/details/104685424) 中給出的幾個知識圖譜的建構的例子。 ### 總結   本文寫的過程較為簡單,也沒有程式碼,這是因為筆者在之前的文章中做了大量的鋪墊,主要是集中在模型方面。況且,這個專案比較大,也不適合在這裡詳細講述,筆者只在這裡給出思路和大概的處理流程,具體的實現程式碼可以參考下方的Github地址。   在實際的抽取過程中,一些句子也存在抽取出大量無用的三元組的情況,導致召回率高,這是因為本專案針對的是開放領域的三元組抽取,因此效果比不會有想象中的那麼好,提升抽取效果的辦法如下: - 增加資料標註量,目前序列標註演算法的樣本僅3200多個; - 模型方面:現在是pipeline形式,各自的效果還行,但總體上不如Joint形式好; - 對於自己想抽的其他三元組的情形,建議增加這方面的標註; - 文字預測耗時長(該問題已經解決)。   本專案作為筆者在開放領域的三元組抽取的一次嘗試,在此之前關於這方面的文章或者專案還很少,因此可以說是探索階段。   原始碼和資料已經在Github專案中給出,網址為 [https://github.com/percent4/spo_extract_platform](https://github.com/percent4/spo_extract_platform) 。   本人的微信公眾號為`Python爬蟲與演算法`,歡迎關注~ ### 參考文獻 1. 利用關係抽取構建知識圖譜的一次嘗試: https://www.cnblogs.com/jclian91/p/11107323.html 2. NLP(二十六)限定領域的三元組抽取的一次嘗試: https://blog.csdn.net/jclian91/article/details/104874488 3. NLP(二十五)實現ALBERT+Bi-LSTM+CRF模型: https://blog.csdn.net/jclian91/article/details/104826655 4. 知識圖譜構建舉例: https://blog.csdn.net/jclian91/article/details/104685424 5. NLP(二十一)人物關係抽取的一次實戰:https://blog.csdn.net/jclian91/article/details/104380371 6. 《知識圖譜 方法、實踐與應用》 王昊奮、漆桂林、陳華鈞著,中國工信出版集團、電子工業出版社