1. 程式人生 > 實用技巧 >第五天學習進度--(KBQA)初接觸知識圖譜之靜態知識提取(二)

第五天學習進度--(KBQA)初接觸知識圖譜之靜態知識提取(二)

昨天學習到對應的知識圖譜在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,"張三","公司"))

執行上述程式碼之後,執行的結果如下所示

執行結果如上。(在圖的基礎上添加了小四喜歡看阿凡達)

可以看到對應的知識已經能夠被簡單地進行回答了。但是現在還是處於靜態方面的文件,如果我想設定一個動態問答呢?如廣東的天氣現在如何?很明顯,這個時候就需要用到對應的函式對應的關係了。