知識圖譜關係抽取之PCNN——tensorflow實現

知識圖譜( Knowledge Graph)以結構化的形式描述客觀世界中概念、實體及其關係,將互聯網的信息表達成更接近人類認知世界的形式,提供了一種更好地組織、管理和理解互聯網海量信息的能力。上述一大段是我從2018知識圖譜發展報告中copy下來的一段話,用普通人能聽懂的人話來描述:知識圖譜就是把去發現世間萬物的之間的聯繫。 在技術上就是將數據以一個一個的<subject,relation,object>的三元組形式存儲起來。

不知道大家有沒有這樣一種感受,如果你在某一領域的學習瞭解到很多的知識碎片,卻無法將他們關聯起來,這些知識碎片並不會加深你對這一領域的認知。而如果你能將他們聯繫起來,串聯成一張知識網,那很有可能你就是這個領域決定的專家。因為你的腦中有這個領域的知識網,你就能知道這個領域的邊界在哪。知識圖譜就是要將知識串聯起來,形成一張知識網。

知識圖譜的應用場景:

知識圖譜主要分為兩類:

通用知識圖譜和領域知識圖譜。通用知識圖譜主要需要知識的廣度,而領域知識圖譜需要知識具有深度。

  • 通用知識圖譜最普遍的應用場景就是:搜索引擎,
  • 領域知識圖譜的應用場景則比較豐富多樣:司法,醫療,金融,電商等各行各業都可以構建屬於自己行業的知識圖譜,而這些知識圖譜可以用於智能問答,輔助決策,風險規避等。

當然以上只是知識圖譜被應用最多的場景,還有一些很有潛力的應用場景,比如將知識圖譜和深度學習結合等。知識圖譜這個新的,年輕的概念還等著大家去探索更多的應用可能性。

知識圖譜的構建簡介

這裡筆者就不沒有考慮業務邏輯,也不考慮構建過程中一下細節技術,直接講一個簡單粗暴版的構建流程。

  • 實體抽取,實體鏈接(兩個實體同一個含義需要規整),目前最主流的算法就是CNN+LSTM+CRF進行實體識別。
  • 實體之間,關係抽取,拿到知識圖譜最小單元三元組,比較經典算法的就是Piece-Wise-CNN,和 LSTM+ Attention 。
  • 知識存儲,一般採用圖數據庫(neo4j等)。

但是要注意的是,知識圖譜一定要最先定義好構建它是用來幹什麼,目標業務導向,定義好符合業務邏輯schema層才是最最重要的。有了schema之後接下來的任務就是實體抽取和關係抽取囉,其中關係抽取是把知識點串聯成一張知識網的重要過程,所以這裡筆者著重介紹一下最近在知識圖譜領域很火的有監督的關係抽取任務的一個模型PCNN。

關係抽取之PCNN(Piece-Wise-CNN)

這裡筆者仔細解釋一下有監督的關係抽取的任務的數據樣式,任務形式,以及PCNN(Piece-Wise-CNN)的思想和tensorflow實現。

關係抽取數據:

知識圖譜關係抽取之PCNN——tensorflow實現

data.png

input : 句子 Steve Jobs was the co-founder of Apple Inc和兩個entities Steve Jobs 和 Apple Inc

out: 實體之間關係 : /business/company/founder

所以我們可以將其抽象成一個分類問題,輸入句子和實體信息,然後讓模型分出這兩個實體之間的關係屬於哪一類。

PCNN

下圖清晰了顯示了PCNN的整個網絡架構,原文鏈接在這裡,下面我對著下圖介紹一下PCNN的實現過程:

  • 數據預處理:首先對數據進行位置編碼,按句子中各個詞離entity的距離進行編碼。
  • 例如:“As we known,Steve Jobs was the co-founder of Apple Inc which is a great company in America.”
  • 由於句子中有兩個entity,所以這條句子就會產生兩個和句子長度相同的編碼。
  • pos_1:[-4,-3,-2,-1,0,1,2,3......] ,其中0就是Steve Jobs的位置。
  • pos_2:[-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3......] 其中0就是Apple Inc的位置。
  • 切分句子:其中最主要的就是將一條文本數據在兩個entity處各切一刀將文本且成了3段
  • 比如 As we known,Steve Jobs was the co-founder of Apple Inc which is a great company in America,將被切成:
  1. As we known,Steve Jobs
  2. Steve Jobs was the co-founder of Apple Inc
  3. Apple Inc which is a great company in America.
  4. 注意,位置向量也同樣進行了切分操作。
  • 特徵提取:將位置特徵和文本特徵拼接之後,然後將上面三個數據分別通過CNN 提取特徵,
  • 關係分類:提取出來的特徵通過maxpooling層之後進行拼接後送入softmax層,最終得到relation的分類。
知識圖譜關係抽取之PCNN——tensorflow實現


  • pcnn.png
  • 從上面PCNN的流程我們可以發現,這個網絡結構很注重entitiy之間的距離信息,位置信息,以及entitiy之間或者左右的信息。其實這些都是是關係抽取中最重要的特徵。
  • 一般來說兩個entitiy之間距離越近,則他們有關係的可能性越大。
  • 而透露出entities之間有關係的詞一般會出現在兩個entity之間,左側,或者右側。
  • 例如:Steve Jobs was the co-founder of Apple Inc , 關係詞 co-founder就在兩個entity之間

tensorflow 代碼實現

由於之前對PCNN的整個流程有了比較詳細的解釋,這裡筆者只是簡單的介紹一下代碼構成。

下方這一步是已經將文本向量和位置向量進行了切分,由於文本被兩個entity分成了三段,再這三段加上各自的兩個位置向量。所以網絡一共有9個輸入,加上關係label輸出,一共需要定義10個placeholder。

import tensorflow as tf
import os
os.environ['CUDA_VISIBLE_DEVICES'] = '1'
tf.reset_default_graph()
word_ids_left = tf.placeholder(tf.float32, shape=[None, maxlen, word_emb_size])
word_ids_mid = tf.placeholder(tf.float32, shape=[None, maxlen, word_emb_size])
word_ids_right = tf.placeholder(tf.float32, shape=[None, maxlen, word_emb_size])
pos_l_1 = tf.placeholder(tf.int32, shape=[None, maxlen])
pos_l_2 = tf.placeholder(tf.int32, shape=[None, maxlen])
pos_m_1 = tf.placeholder(tf.int32, shape=[None, maxlen])
pos_m_2 = tf.placeholder(tf.int32, shape=[None, maxlen])
pos_r_1 = tf.placeholder(tf.int32, shape=[None, maxlen])
pos_r_2 = tf.placeholder(tf.int32, shape=[None, maxlen])
pos_r_2 = tf.placeholder(tf.int32, shape=[None, maxlen])
label = tf.placeholder(dtype=tf.int32,shape=[None,n_class])

下方代碼這是PCNN的實現,其中Piece_Wise_CNN函數是對PCNN的實現。

def get_sentence_emb(word_ids,pos_1,pos_2):
pos_emb_l1 = tf.keras.layers.Embedding(input_dim=498,output_dim=10,input_length=100)(pos_l_1)
pos_emb_l2 = tf.keras.layers.Embedding(input_dim=498,output_dim=10,input_length=100)(pos_l_2)
return tf.concat([word_ids,pos_emb_l1,pos_emb_l2],2)#[batch_size,maxlen,word_emb_size+2*pos_emb_size(10)]
def Piece_Wise_CNN(left_emb,mid_emb,right_emb,feature_map,n_class):
left = tf.keras.layers.Conv1D(filters=feature_map,kernel_size=3)(left_emb)#[batch_size,maxlen,word_emb_size+2*pos_emb_size(10)]
left = tf.keras.layers.GlobalMaxPool1D()(left)#[batch_size,feature_map]
mid = tf.keras.layers.Conv1D(filters=feature_map,kernel_size=3)(mid_emb)#[batch_size,maxlen,word_emb_size+2*pos_emb_size(10)]
mid = tf.keras.layers.GlobalMaxPool1D()(mid)#[batch_size,feature_map]
right = tf.keras.layers.Conv1D(filters=feature_map,kernel_size=3)(right_emb)#[batch_size,maxlen,word_emb_size+2*pos_emb_size(10)]
right = tf.keras.layers.GlobalMaxPool1D()(right)#[batch_size,feature_map]
final_feature = tf.concat([left,mid,right],1)#[batch_size,3*feature_map]
out = tf.keras.layers.Dense(n_class,activation="softmax")(final_feature) #[batch_size,n_class]
return out
def train_op(out,label,lr):
losses = tf.nn.softmax_cross_entropy_with_logits_v2(
logits=out, labels=label)
loss = tf.reduce_mean(losses)
train_op = tf.train.GradientDescentOptimizer(learning_rate=lr).minimize(loss)
return train_op,loss

這裡是定義train_op部分。

left_emb = get_sentence_emb(word_ids_left,pos_l_1,pos_l_2)
mid_emb = get_sentence_emb(word_ids_mid,pos_m_1,pos_m_2)
right_emb = get_sentence_emb(word_ids_right,pos_r_1,pos_r_2)
out = Piece_Wise_CNN(left_emb,mid_emb,right_emb,20,n_class)
train_op,loss = train_op(out,label,lr = 0.01)

結語

這裡筆者主要是想通過PCNN這個經典的關係抽取網絡說明:其實有監督的關係抽取任務的關鍵是需要神經網絡理解兩個entity之間的語義連結,所以,而如何利用好句子中entity周圍的詞語的語義信息和entity之間的位置信息,可能是解決這類任務的關鍵。筆者在之前的文章中多次強調過自然語言處理最終目標還是希望算法能夠理解語義。像PCNN這個網絡則提出了切分句子,集中注意力關注句子提供關鍵信息的部分(自己的理解),也許是一個好的方向。

作者:王鵬你妹

鏈接:https://www.jianshu.com/p/f29bc334c4f9

相關推薦

推薦中...