【图嵌入】DeepWalk原理与代码实战
DeepWalk
基礎(chǔ)理論
了解過(guò) NLP 的同學(xué)對(duì) word2vec 應(yīng)該不陌生,word2vec 通過(guò)句子中詞與詞之間的共現(xiàn)關(guān)系來(lái)學(xué)習(xí)詞的向量表示,如果你忘記了,可以看看我之前的博客:
DeepWalk 出自論文:DeepWalk: Online Learning of Social Representations,它的思想與 word2vec 類似,從一個(gè)初始節(jié)點(diǎn)沿著圖中的邊隨機(jī)游走一定的步數(shù),將經(jīng)過(guò)的節(jié)點(diǎn)序列視為句子。那么,從不同的起點(diǎn)開(kāi)始的不同游走路線就構(gòu)成了不同的句子。當(dāng)獲取到足夠數(shù)量的句子(節(jié)點(diǎn)訪問(wèn)序列)后,可以使用 skip-gram 模型對(duì)每個(gè)節(jié)點(diǎn)學(xué)習(xí)其向量表示。這個(gè)過(guò)程如下圖所示:
以下是對(duì) DeepWalk 的一些思考與個(gè)人理解:
DeepWalk 利用類似深度優(yōu)先遍歷的方式將復(fù)雜的圖結(jié)構(gòu)轉(zhuǎn)換為序列,進(jìn)而實(shí)現(xiàn)節(jié)點(diǎn)的Embedding。這個(gè)遍歷的過(guò)程相當(dāng)于對(duì)圖中的節(jié)點(diǎn)進(jìn)行采樣,捕獲局部上下文信息。上圖中B與D都是A與E共有的鄰居,那么在經(jīng)過(guò)節(jié)點(diǎn)B、D的隨機(jī)游走序列中,節(jié)點(diǎn)A或者節(jié)點(diǎn)E出現(xiàn)的頻率也比較高,說(shuō)明節(jié)點(diǎn)A和E具有相似的上下文語(yǔ)境,那么A和E的Embedding表示也應(yīng)該相似。
下面再來(lái)看個(gè)更直觀的例子,如下圖中的節(jié)點(diǎn)1、4是節(jié)點(diǎn)2、3共有的鄰居:
那么在經(jīng)過(guò)節(jié)點(diǎn)1、4的隨機(jī)游走序列中,節(jié)點(diǎn)2或者節(jié)點(diǎn)3出現(xiàn)的頻率也比較高,例如:
- 0,4,3
- 0,4,2
- 1,2
- 1,3
- 1,4,3
- 1,4,2
- …
那么根據(jù) skip-gram 模型的思想,節(jié)點(diǎn)2,3的局部上下文語(yǔ)境比較相似,于是最終學(xué)習(xí)到的節(jié)點(diǎn)2、3的Embedding表示也就比較相似。這也意味著,當(dāng)兩個(gè)節(jié)點(diǎn)共有的鄰居節(jié)點(diǎn)越多,那么這兩個(gè)節(jié)點(diǎn)就越相似。
代碼實(shí)現(xiàn)
結(jié)合上面的理論基礎(chǔ),要使用 DeepWalk 得到節(jié)點(diǎn)的向量表示,需要分為三個(gè)步驟:
1,構(gòu)造圖
主要是使用 networkx 這個(gè)庫(kù)來(lái)從文件中讀取邊的信息來(lái)構(gòu)造圖,文件的每一行分別是:
node1 node2 <edge_weight> node1 node3 <edge_weight> ......其中,邊的權(quán)重 edge_weight 不是必須有的。具體讀取數(shù)據(jù)并構(gòu)造圖的代碼如下:
import networkx as nx # create_using=nx.DiGraph() 表示構(gòu)造的是有向圖 G = nx.read_edgelist('data/wiki/Wiki_edgelist.txt', create_using=nx.DiGraph())2,隨機(jī)游走
下面是生成隨機(jī)游走序列的代碼:
import random# 從 start_node 開(kāi)始隨機(jī)游走 def deepwalk_walk(walk_length, start_node):walk = [start_node]while len(walk) < walk_length:cur = walk[-1]cur_nbrs = list(G.neighbors(cur))if len(cur_nbrs) > 0:walk.append(random.choice(cur_nbrs))else:breakreturn walk# 產(chǎn)生隨機(jī)游走序列 def _simulate_walks(nodes, num_walks, walk_length):walks = []for _ in range(num_walks):random.shuffle(nodes)for v in nodes:walks.append(deepwalk_walk(walk_length=walk_length, start_node=v))return walks# 得到所有節(jié)點(diǎn) nodes = list(G.nodes()) # 得到序列 walks = _simulate_walks(nodes, num_walks=80, walk_length=10)3,嵌入
為了方便起見(jiàn),這里就使用 gensim 中的 Word2Vec 來(lái)實(shí)現(xiàn)節(jié)點(diǎn)的 Embedding 了:
from gensim.models import Word2Vec # 默認(rèn)嵌入到100維 w2v_model = Word2Vec(walks,sg=1,hs=1) # 打印其中一個(gè)節(jié)點(diǎn)的嵌入向量 print(w2v_model['1397'])輸出為:
array([-3.57212842e-01, -4.52286422e-01, 1.20047189e-01, 9.33077093e-03,-4.87361886e-02, 6.53029561e-01, 3.87212396e-01, -4.35320556e-01,4.67856340e-02, -4.55924332e-01, -5.82973696e-02, 1.50977358e-01,......,-1.48566559e-01, 4.78760689e-01, 9.73562971e-02, -5.75734824e-02,-2.45316476e-01, -2.85568893e-01, 2.79851675e-01, 3.75600569e-02],dtype=float32)優(yōu)點(diǎn)分析
使用隨機(jī)游走有兩個(gè)好處:
- 并行化,隨機(jī)游走是局部的,對(duì)于一個(gè)大的網(wǎng)絡(luò)來(lái)說(shuō),可以同時(shí)在不同的頂點(diǎn)開(kāi)始進(jìn)行一定長(zhǎng)度的隨機(jī)游走,多個(gè)隨機(jī)游走同時(shí)進(jìn)行,可以減少采樣的時(shí)間。
- 適應(yīng)性,可以適應(yīng)網(wǎng)絡(luò)局部的變化。網(wǎng)絡(luò)的演化通常是局部的點(diǎn)和邊的變化,這樣的變化只會(huì)對(duì)部分隨機(jī)游走路徑產(chǎn)生影響,因此在網(wǎng)絡(luò)的演化過(guò)程中不需要每一次都重新計(jì)算整個(gè)網(wǎng)絡(luò)的隨機(jī)游走。
參考文章:
Graph Embedding:從DeepWalk到SDNE - 知乎
【Graph Embedding】DeepWalk:算法原理,實(shí)現(xiàn)和應(yīng)用
總結(jié)
以上是生活随笔為你收集整理的【图嵌入】DeepWalk原理与代码实战的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: linux安装卸载软件的命令_shell
- 下一篇: 【图嵌入】Graph Embedding