圖學習【參考資料2】-知識補充與node2vec代碼注解

本項目參考:https://aistudio.baidu.com/aistudio/projectdetail/5012408?contributionType=1
*一、正題篇:DeepWalk、word2vec、node2vec其它相關項目:
關于圖計算&圖學習的基礎知識概覽:前置知識點學習(PGL)[系列一] https://aistudio.baidu.com/aistudio/projectdetail/4982973?contributionType=1
圖機器學習(GML)&圖神經網絡(GNN)原理和代碼實現(前置學習系列二):https://aistudio.baidu.com/aistudio/projectdetail/4990947?contributionType=1
1.1DeepWalk算法流程【圖來源:網絡,筆記由筆者添上】
算法流程:

圖學習【參考資料2】-知識補充與node2vec代碼注解

文章插圖
【其中使用skip-gram模型是為了利用梯度的方法對參數進行更新訓練】
1.2 Skip Gram算法流程【圖來源:網絡,筆記由筆者添上】
算法流程:
圖學習【參考資料2】-知識補充與node2vec代碼注解

文章插圖
【其中使用skip-gram模型是為了利用梯度的方法對參數進行更新訓練】
此外,關于以上兩個算法的定義和概念就不一一展示說明了,后邊等有空了補上 。下邊說一下我學習的一些參考資料,希望對大家有幫助 。
參考資料1.【論文筆記】DeepWalk——陌上疏影涼1.【網絡圖模型綜述1.【異構圖神經網絡簡介--機器之心1.【Graph Embedding之metapath2vec--圈圈_Master1.【從Random Walk談到Bacterial foraging optimization algorithm(BFOA),再談到Ramdom Walk Graph Segmentation圖分割算法
二 程序注解【注解展示,是為了方便自己理解,同時也希望能幫到和自己一樣在學習這塊知識的小伙伴】
1.0 DeepWalk隨機游走的實現
圖學習【參考資料2】-知識補充與node2vec代碼注解

文章插圖
實現Graph類的random_walk函數--可參考
1.1 實現的參考代碼--DeepWalk的隨機游走算法實現思路
  1. 理清successor,outdegree函數的輸入輸出
  2. 查看補全函數的返回類型--分析可能的結果--我最初的猜測:這walks應該是多個向量的集合,最后確實也是【[[],..]這樣的結構多用于擴充,然后聯想需要學習向量,所以想到向量遞推的那種向量集合】
  3. 生成隨機采樣索引序列集 -- 這個需要匹配采樣形狀,以及索引閾值--我是參考一個示例修改的,感悟是: 利用隨機數0~1,給rand傳入指定shape , 再乘以一個相同shape的數據,可以得到一個>=0, <=最大出度-1的值 , 這樣就可以用來索引采樣了
  4. 理清上下文變量關系,進行zip打包遍歷到一起,然后進行聚合操作即可 。
具體注解在代碼中 , 可查閱,基本都是按照一行行注解的
from pgl.graph import Graphimport numpy as npclass 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))# 游走路徑中節點對應id號cur_nodes = np.array(nodes)# 當前節點情況for l in range(walk_len):# 根據游走長度進行遍歷--破出條件:1. range結束;2. outdegree==0【出度為零,沒有可繼續的節點】"""選取有下一個節點的路徑繼續采樣 , 否則結束"""outdegree = self.outdegree(cur_nodes)# 計算當前節點的出度--也就是對應有哪些位置的鄰近節點walk_mask = (outdegree != 0)# 根據出度來確定掩碼--True,False--將出度為0的部分復制為False,反之Trueif not np.any(walk_mask):# 判斷是否沒有可繼續的節點情況--出度為0breakcur_nodes = cur_nodes[walk_mask]# 根據掩碼獲取可繼續前進的節點,作為后邊討論的當前可前行節點walks_ids = walks_ids[walk_mask]# 獲取掩碼下,原節點id,組成新的work_ids用于后邊討論,但本身還是作為一個節點的標記,對應這是第幾個節點outdegree = outdegree[walk_mask]# 根據掩碼獲取相應的不為0的出度--用于后邊計算前行的路徑####################################### 請在此補充代碼采樣出下一個節點'''[注解有點多 , 所以放外邊了]PS:1. successor 可獲取當前節點的下一個相鄰節點id列表 , 那么successor 計算出下一節點的集合后,我們需要從中隨機取出一個節點--所以我們要創建隨機采樣的index_list(索引序列集)2. 創建index_list=>為了才到合適的index信息,采用np.floor與np.random,rand()實現:eg: np.floor(np.random.rand(outdegree.shape[0]) * outdegree).astype('int64')np.random.rand(outdegree.shape[0]): 根據出度集的形狀來取得相應形狀的隨機數--這里體現游走的隨機性np.random.rand(outdegree.shape[0]) * outdegree:利用生成的隨機數與出度集對應元素相乘——這里得到一些列的隨機數,隨機數范圍在0~最大出度值--保證路徑有效np.floor(np.random.rand(outdegree.shape[0]) * outdegree)——實現向下取整,這樣就得到了相應游走路徑中接下來那個點的索引具體實例:np.floor(np.random.rand(20) * 3).astype('int64')result: array([0, 1, 2, 1, 0, 0, 0, 0, 1, 1, 1, 2, 0, 2, 2, 2, 2, 1, 2, 0])3. 既然知道了隨機采樣的序列集了,那么接下就是分配新的游走路徑了next_nodes = []# 用于后邊存放—— 裝配有下一個節點的新路徑# 參數說明:succ_nodes:相鄰節點id列表sample_index:對應出度生成的隨即索引集walks_ids:游走路徑中節點對應id號# 接下來的循環指的是,將節點列表、隨機采樣序列、游走路徑中節點對應id號一一對應進行填充--得到一個游走情況for s, ind, walk_id in zip(succ_nodes, sample_index, walks_ids):walks[walk_id].append(s[ind])# 注意: 從開始已經知道walks=>[[], [], []]是這種形式的,這樣這里的append,就很容易理解成為相應節點添加可以繼續前行的節點,形成一條路徑next_nodes.append(s[ind])# 同時獲取接下來要重新討論游走時所需的新節點--即:如:從1走到了2,從3走到了7: [[1], [3]]=>[[1, 2], [3, 7]]# 接下來自然就該考慮把新的2, 7 作為下一次游走時討論出度的節點啦'''succ_nodes = self.successor(cur_nodes)# 返回可繼續的節點集合# next_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)# 將節點轉換為np類型,方便一些操作運算--同時保證前后數據類型# 遍歷完游走長度的次數,就可以返回得到的隨機游走路徑啦return walks

推薦閱讀