第五天學習進度--(KBQA)初接觸知識圖譜之靜態知識提取(二)
阿新 • • 發佈:2020-07-13
昨天學習到對應的知識圖譜在networkx的構建,在此先前的程式碼上,新增一部分的程式碼,用來完成靜態知識的提取。
通過昨天的程式碼,已經有了基礎的節點的增刪功能,現在再新增對於節點之間關係的判斷,還有一些簡單的自然語言的處理如下。
因為現在的關係並沒有知識提取的功能,我們現在來新增一些回答的規則用來讓回答有一些邏輯的問題。
import difflib
#判斷A,B字元間的相似度
def get_str_equal_rate(A,B):
return difflib.SequenceMatcher(None, A, B).quick_ratio()
#獲得鄰接節點之間的關係,0無連通,1單向連通,2反向連通,3雙向連通
def get_nodes_relation(digraph: nx.DiGraph,node1,node2,relation="relation"):
throught_over=False
throught_unti=False
try:
temp=digraph[node1][node2][relation]
if temp:
throught_over=True
except Exception:
throught_over=False
try:
temp=digraph[node2][node1][relation]
if temp:
throught_unti=True
except Exception:
throught_unti=False
if(throught_over and throught_unti):
if(digraph[node2][node1][relation]==digraph[node1][node2][relation]):
return 4
else:
return 3
elif throught_unti:
return 2
elif throught_over:
return 1
else:
return 0
#原子資訊處理
def nlp_atom_handle(digraph: nx.DiGraph,node1,node2,relation="relation"):
ptype = get_nodes_relation(digraph, node1, node2, relation)
if (ptype == 4):
return "是" + str(node2) + "的" + str(digraph[node1][node2][relation])
elif (ptype == 3):
return str(digraph[node1][node2][relation]) + str(node2) + ";" + str(node2) + str(
digraph[node2][node1][relation]) + str(node1)
elif (ptype == 2):
return str(node2) + str(digraph[node2][node1][relation]) + str(node1)
elif (ptype == 1):
return str(digraph[node1][node2][relation]) + str(node2)
#處理長距離節點關係
def nlp_nodes(digraph: nx.DiGraph,node1,node2,relation="relation"):
try:
path=nx.dijkstra_path(G, node1, node2, weight='weight')
result=str(node1)
for i in range(len(path)-1):
result+=nlp_atom_handle(digraph,path[i],path[i+1],relation)
if(i!=len(path)-2):
result+=","
else:
result+="。"
except Exception:
result = str(node1)+"和"+str(node2)+"沒有任何關係。"
return result
#單節點釋義(What)
def nlp_node(digraph: nx.DiGraph,node1,relation="relation"):
try:
result=str(node1)+"("+str(digraph.nodes[node1]['attribute'])+")"
path=[one for one in digraph.neighbors(node1)]
for i in range(len(path)):
result += nlp_atom_handle(digraph, node1, path[i], relation)
if (i != len(path) - 1):
result += ","
result += "。"
prepath=path
path = [one for one in digraph.predecessors(node1) if one not in prepath]
for i in range(len(path)):
result += nlp_atom_handle(digraph, node1, path[i], relation)
if (i != len(path) - 1):
result += ","
else:
result += "。"
except Exception:
result="知識圖譜中不存在"+str(node1)
return result
#根據節點的關係得到對應節點列表
def get_relation_nodes(digraph: nx.DiGraph,node,info,relation="relation"):
pnodelist=[]
web=digraph[node]
for one in web:
if web[one][relation]==info:
pnodelist.append(one)
return pnodelist
#得到屬性為info的鄰居節點
def get_neighbors_attribute_nodes(digraph: nx.DiGraph,node,info):
nlist=[one for one in digraph.successors(node)]
result=[]
for one in nlist:
if digraph.nodes[one]['attribute']==info:
result.append(one)
return result
新增完上述對語言進行處理的一些簡單函式之後,我們繼續新增對應的節點關係,同時讓其回答一些問題看看效果
再次基礎上新增電影節點 阿凡達和復仇者聯盟,並設定小四喜歡看阿凡達
#知識圖譜知識提取測試
#根據知識圖譜得到小四和小五的關係
print("小四和小五有什麼關係?",nlp_nodes(G, "小四", "小五"))
#釋義騰訊節點
print("騰訊是什麼?",nlp_node(G,"騰訊"))
#釋義張三節點
print("張三是什麼?",nlp_node(G,"張三"))
#在知識圖譜中新增電影節點,並且設定小四喜歡看阿凡達
add_node_attribute(G,['阿凡達','復仇者聯盟'],'電影')print("所有的節點屬性:",get_nodes_attribute(G))
add_edge(G,"小四","阿凡達","喜歡看")
#釋義小四節點
print("小四是什麼?",nlp_node(G,"小四"))
#釋義阿凡達節點
print("阿凡達是什麼?",nlp_node(G,"阿凡達"))
print("李四的朋友有?",get_relation_nodes(G,"李四",'朋友'))
print("張三有關的公司有?",get_neighbors_attribute_nodes(G,"張三","公司"))
執行上述程式碼之後,執行的結果如下所示
執行結果如上。(在圖的基礎上添加了小四喜歡看阿凡達)
可以看到對應的知識已經能夠被簡單地進行回答了。但是現在還是處於靜態方面的文件,如果我想設定一個動態問答呢?如廣東的天氣現在如何?很明顯,這個時候就需要用到對應的函式對應的關係了。