圖遊走類模型
阿新 • • 發佈:2020-12-06
1、圖與圖學習
1)圖的兩個基本元素是點和邊,是一種統一描述複雜事務的語言,常見的圖有社交網路、推薦系統、化學分子結構。
2)圖學習: Graph Learning。深度學習中的一個子領域,強調處理的資料物件為圖;與一般深度學習的區別:能夠方便地處理不規則資料(樹、圖),同時也可以處理規則資料(如影象)。
3)圖學習的應用:
- 節點級別任務:金融詐騙檢測(典型的節點分類)、自動駕駛中的3D點雲目標檢測
- 邊級別任務:推薦系統(典型的邊預測)
- 圖級別任務:氣味識別(典型的圖分類)、發現“宇宙”
4)圖學習是怎麼做的:
- 圖遊走類演算法:通過在圖上的遊走,獲得多個節點序列,再利用 Skip Gram 模型訓練得到節點表示(下節課內容)
- 圖神經網路演算法:端到端模型,利用訊息傳遞機制實現。
- 知識圖譜嵌入演算法:專門用於知識圖譜的相關演算法。
2、圖遊走類模型(得到節點表示(Node Embedding)用於下游任務)
1)DeepWalk取樣演算法
class UserDefGraph(Graph): def random_walk(self, nodes, walk_len): """ 輸入:nodes - 當前節點id list (batch_size,) walk_len - 最大路徑長度 int 輸出:以當前節點為起點得到的路徑 list (batch_size, walk_len) 用到的函式 1. self.successor(nodes) 描述:獲取當前節點的下一個相鄰節點id列表 輸入:nodes - list (batch_size,) 輸出:succ_nodes - list of list ((num_successors_i,) for i in range(batch_size)) 2. self.outdegree(nodes) 描述:獲取當前節點的出度 輸入:nodes - list (batch_size,) 輸出:out_degrees - list (batch_size,)""" walks = [[node] for node in nodes] # 儲存遊走路徑? walks_ids = np.arange(0, len(nodes)) # 有多少起始節點 cur_nodes = np.array(nodes) # 所有的起始節點 for l in range(walk_len): """選取有下一個節點的路徑繼續取樣,否則結束""" outdegree = self.outdegree(cur_nodes) # 當前節點出度 walk_mask = (outdegree != 0)if not np.any(walk_mask): break cur_nodes = cur_nodes[walk_mask] walks_ids = walks_ids[walk_mask] outdegree = outdegree[walk_mask] ###################################### # 請在此補充程式碼取樣出下一個節點 succ_nodes = self.successor(cur_nodes) sample_index = np.floor( np.random.rand(outdegree.shape[0]) * outdegree).astype("int64") next_nodes = [] for s, ind, walk_id in zip(succ_nodes, sample_index, walks_ids): walks[walk_id].append(s[ind]) next_nodes.append(s[ind]) ###################################### cur_nodes = np.array(next_nodes) return walks
2)Node2vec取樣演算法(DeepWalk的改進)
def node2vec_sample(succ, prev_succ, prev_node, p, q): """ 輸入:succ - 當前節點的下一個相鄰節點id列表 list (num_neighbors,) prev_succ - 前一個節點的下一個相鄰節點id列表 list (num_neighbors,) prev_node - 前一個節點id int p - 控制回到上一節點的概率 float q - 控制偏向DFS還是BFS float 輸出:下一個節點id int """ ################################## # 請在此實現node2vec的節點取樣函式 succ_len = len(succ) prev_succ_len = len(prev_succ) probs=[] prob_sum = 0 prob = 0 prev_succ_set = np.asarray([]) for i in range(prev_succ_len): prev_succ_set= np.append(prev_succ_set, prev_succ[i]) for i in range(succ_len): if succ[i] == prev_node: prob = 1. / p elif np.where(prev_succ_set==succ[i]): prob = 1. elif np.where(prev_succ_set!=succ[i]): prob = 1. / q else: prob=0 probs.append(prob) prob_sum += prob RAND_MAX = 65535 rand_num = float(np.random.randint(0, RAND_MAX+1))/RAND_MAX*prob_sum sample_succ = 0 for i in range(succ_len): rand_num -= probs[i] if rand_num <= 0: sample_succ = succ[i] return sample_succ ################################## return sampled_succ