0%

GNN从入门到入门01:图的基础与图嵌入

关于GNN相关的前置知识

首先非常建议大家去读一读下面这篇文章 A Gentle Introduction to Graph Neural Networks ,指路 https://distill.pub/2021/gnn-intro/

图 Graph

图的基础表述

从数学上讲,一个可以简单地表示为 G=(V,E)G = (V, E)

  • VV (Vertex/Node): 节点。代表实体,比如社交网络里的一位用户、分子结构里的一个原子。
  • EE (Edge/Link): 边。代表实体间的关系,比如用户间的关注、原子间的化学键。

我们通常用两个矩阵来描述图:

  • 邻接矩阵 (Adjacency Matrix, AA): 描述谁和谁相连。如果节点 iijj 相连,则 Aij=1A_{ij} = 1,否则为 00

A{0,1}n×nA \in \{0, 1\}^{n \times n}

  • 特征矩阵 (Feature Matrix, XX): 描述节点自身的属性。

XRn×dX \in \mathbb{R}^{n \times d}

图的拓扑特性

子图:给定图 G=(V,E)G=(V, E),若 VVV' \subseteq VEEE' \subseteq E,且 EE' 中的边所关联的顶点都在 VV' 中,则 G=(V,E)G'=(V', E')GG 的子图。

连通图:在无向图中,如果任意两个节点 u,vu, v 之间都存在路径,则图是连通的。对于有向图,若任意两点双向可达,称为强连通

连通分量:图中最大的连通子图。可以把它想象成社交网络中的小圈子,圈子内部相互认识,但圈子之间没有任何交集。

最短路径:两点之间边数最少的路径(或权值和最小)。

直径 (Diameter):图中任意两点间最短路径的最大值。

度 (Degree):对于无向图 G=(V,E)G = (V, E),节点 vv 的度 d(v)d(v) 定义为连接到该节点的边的数目。在有向图中,边的方向性使得度被拆分为两个独立的概念:入度出度。入度 (In-degree, din(v)d^{in}(v)) 为指向节点 vv 的边的数量;出度 (Out-degree, dout(v)d^{out}(v)) 为从节点 vv 出发的边的数量;总度为节点入度与出度的加和。

图中心性

在图论分析中,中心性(Centrality)是用于量化图中顶点重要程度或影响力的一类指标。由于重要性在不同的应用语境下有不同的定义,图论中演化出了多种中心性度量方法。

度中心性 (Degree Centrality) 是最基础、最直观的中心性度量指标。它基于一个朴素的假设:一个节点的连接数越多,其在网络中的地位就越重要。

对于一个拥有 nn 个节点的无向图 G=(V,E)G=(V, E),节点 viv_i 的度中心性 CD(vi)C_D(v_i) 定义为该节点的度数 d(i)d(i)

CD(vi)=d(i)C_D(v_i) = d(i)

为了便于在不同规模的图之间进行比较,通常会对该指标进行归一化处理。归一化后的度中心性定义为节点实际度数与图中可能的最大度数(即 n1n-1)之比:

CD(vi)=d(i)n1C'_D(v_i) = \frac{d(i)}{n-1}

紧密中心性 (Closeness Centrality) 是从距离的角度出发,衡量一个节点到达图中其他所有节点的效率。如果一个节点到其他节点的平均最短路径距离越小,则该节点在网络中越接近几何中心。

d(vi,vj)d(v_i, v_j) 为节点 viv_ivjv_j 之间的最短路径长度。节点 viv_i 的紧密中心性定义为其到所有其他节点距离之和的倒数:

CC(vi)=n1j=1,jind(vi,vj)C_C(v_i) = \frac{n-1}{\sum_{j=1, j \neq i}^{n} d(v_i, v_j)}

中介中心性 (Betweenness Centrality) (亦称间距中心性)衡量的是一个节点在网络中担任桥梁角色的程度。它关注的是节点对网络中信息流动的控制能力。

定义 σst\sigma_{st} 为节点 ss 到节点 tt 之间所有的最短路径总数,σst(vi)\sigma_{st}(v_i) 为这些最短路径中经过节点 viv_i 的数量。节点 viv_i 的中介中心性定义为:

CB(vi)=svitσst(vi)σstC_B(v_i) = \sum_{s \neq v_i \neq t} \frac{\sigma_{st}(v_i)}{\sigma_{st}}

特征向量中心性 (Eigenvector Centrality) 特征向量中心性是一种递归定义的指标。其核心思想是:一个节点的重要性不仅取决于其邻居的数量,还取决于其邻居的重要性。

xix_i 为节点 viv_i 的重要性得分,其值正比于其所有邻居的重要性得分之和:

xi=1λj=1nAijxjx_i = \frac{1}{\lambda} \sum_{j=1}^{n} A_{ij} x_j

其中 AA 为图的邻接矩阵,λ\lambda 为常数。将其写成矩阵形式,即:

Ax=λxAx = \lambda x

这表明,节点重要性向量 xx 实际上是邻接矩阵 AA 的特征向量。根据 Perron-Frobenius 定理,对于一个连通图,对应于最大特征值 λmax\lambda_{max} 的特征向量的所有分量均为正值。因此,特征向量中心性通常取邻接矩阵最大特征值对应的特征向量。该指标不仅考虑了节点的局部结构,还融合了全网的拓扑结构信息。

PageRank

既然是介绍图,那么肯定绕不开经典的 PageRank ,如果将万维网看作一个巨大的有向图,其中网页是节点,网页之间的超链接是有向边,那么网页的重要性就可以通过图的拓扑结构来推导。

PageRank 由 Google 创始人 Larry Page 和 Sergey Brin 提出。其核心假设基于随机游走模型(Random Surfer Model):一个网页的重要性取决于指向它的其他网页的重要性,以及这些网页包含的外链数量。

假设网络中有一个冲浪者,他在当前页面 uu 时,会等概率地随机点击页面上的任意一个超链接跳转到下一个页面。如果页面 uuL(u)L(u) 个出链(Out-degree),那么他点击其中任何一个链接的概率为 1L(u)\frac{1}{L(u)}

基于此,一个页面 vv 的 PageRank 值(记为 PR(v)PR(v))可以通过所有指向它的页面 uu 的 PageRank 值来定义:

PR(v)=uBvPR(u)L(u)PR(v) = \sum_{u \in B_v} \frac{PR(u)}{L(u)}

其中,BvB_v 表示所有包含指向页面 vv 的链接的页面集合(即 vv 的入邻居)。可以看出,PageRank 的计算是一个递归过程,通常通过迭代来求解稳定值。

然而,上述基本模型在实际网络中会遇到两个问题,一是某些网页没有出链,导致全网的 PR 值在迭代中逐渐趋零;二是某些网页集合只在内部相互链接,形成封闭循环。

为了解决这两个问题,PageRank 引入了阻尼因子 (Damping Factor, 通常记为 dd),意味着游走者在任何一个页面时,有 dd 的概率继续点击链接,有 1d1-d 的概率感到厌倦,并在地址栏随机输入网址跳转到全网的任意一个页面。

加入了阻尼因子后的 PageRank 完整公式为:

PR(v)=1dN+duBvPR(u)L(u)PR(v) = \frac{1-d}{N} + d \sum_{u \in B_v} \frac{PR(u)}{L(u)}

其中,NN 是网络中所有网页的总数。通常经验上取 d=0.85d = 0.85

PageRank 的计算等价于求解马尔可夫链的平稳分布。设 P\mathbf{P} 为状态转移矩阵,r\mathbf{r} 为所有网页的 PR 值列向量,则迭代过程可表示为:

r(t+1)=(1dNE+dPT)r(t)\mathbf{r}^{(t+1)} = \left( \frac{1-d}{N}\mathbf{E} + d\mathbf{P}^T \right) \mathbf{r}^{(t)}

(其中 E\mathbf{E} 为全 1 矩阵)。当 tt \to \infty 时,r\mathbf{r} 收敛于修正后转移矩阵的最大特征值(即 1)对应的特征向量。

扯远了,这一章我们大概了解了图的一些基本性质,在下一章中,我们将了解到如何表征一个图,即 Graph Embedding 。

图嵌入 Graph Embedding

正如 Distill 的 GNN 综述中所指出的,传统深度学习模型(如 CNN 处理图像、RNN 处理文本)依赖于数据具有固定的、规则的空间结构。而图数据具有高度的灵活性和无序性(其具有置换不变性,改变其空间结构不回对其造成影响)。

那能否直接使用邻接矩阵 ARV×VA \in \mathbb{R}^{|V| \times |V|} 作为特征输入呢?显然是不行的,真实世界的网络(如微信社交网)包含数亿节点,其邻接矩阵极大且极其稀疏;同时,在邻接矩阵中,每个节点可看作一个独热编码(One-hot)向量。任何两个不同节点的向量内积都为 0,这完全丢失了图的连通结构;最后,一旦网络中新增节点,整个矩阵的维度都会随之改变,模型必须重新训练。

因此,我们需要使用 图嵌入(Graph Embedding) ,图嵌入的目标是寻找一个映射函数 f:VRdf: V \to \mathbb{R}^d,将图中的离散节点映射到一个低维、稠密、连续的向量空间中(通常 dVd \ll |V|),并在向量空间中,保持图中原有的拓扑结构信息和节点相似性。

随机游走 RandomWalk

在图 G=(V,E)G=(V,E) 中,从节点 v0v_0 开始的随机游走可以定义为一个节点序列 W=(v0,v1,,vL)W = (v_0, v_1, \dots, v_L),其中 LL 是游走的步数。在最朴素的设定下,如果当前停留在节点 vtv_t,那么下一个节点 vt+1v_{t+1} 将从 vtv_t 的邻居节点集中等概率地随机选取。

在随机游走序列中,如果两个节点经常出现在彼此的上下文中(即距离很近),那么它们在图中的结构作用或所属类别(如果要分类的话)区也非常相似。

DeepWalk

从图中的每一个节点出发,生成指定数量(如 γ\gamma 个)、指定长度(如 LL 步)的均匀随机游走序列。由于是等概率选择邻居,我们称之为无偏游走(Unbiased Random Walk)

将这些游走序列视作“句子”,投入 Skip-Gram 模型中。在 NLP 中,Skip-Gram 的目标是:给定序列中的一个中心节点 viv_i,最大化其前后窗口大小为 ww 内的上下文节点出现的概率。为什么可以借鉴 NLP 的模型 Skip-Gram(Word2Vec最常见的模型),其实是由于图中的随机游走序列,在统计特性上与人类语言的句子非常相似,比如人类的句子是单词的排列,如[我, 喜欢, 学习, 图, 神经网络],而通过随机有座,图中的节点也可以排列成序列,如[节点1, 节点5, 节点2, 节点8, 节点5]。这两者都遵循幂律分布,图中少数几个枢纽节点会频繁出现在大量随机游走序列中,就像人类语言中的高频词(如“的”、“是”)一样。

想象你手里拿着一条随机游走生成的序列:[A, B, C, D, E]。假设当前窗口大小 w=1w=1,我们关注中心节点 C。DeepWalk(基于 Word2Vec)的目标是,如果你手里只有节点 C 的向量 Φ(C)\Phi(C),你能不能通过这个向量,精准地预测出它的邻居 B 和 D 也是这条序列里的人?

如果模型预测对了(概率 PP 很高),说明 Φ(C)\Phi(C) 很好地捕捉了它的上下文信息,如果模型预测错了,我们就调整 Φ(C)\Phi(C),直到它能预测对为止。

用数学语言表达就是,设定一个窗口大小 ww,对于游走序列中的节点 viv_i,模型尝试利用其向量表示 Φ(vi)\Phi(v_i) 来预测它前后的邻居 {vi2,vi1,vi+1,vi+2}\{v_{i-2}, v_{i-1}, v_{i+1}, v_{i+2}\}。设 Φ(v)Rd\Phi(v) \in \mathbb{R}^d 为节点 vv 的连续型向量表示(即我们最终要求的 Embedding),DeepWalk 的优化目标是最大化以下对数似然函数:

maxΦviWwjw,j0logP(vi+jΦ(vi))\max_{\Phi} \sum_{v_i \in W} \sum_{-w \le j \le w, j \neq 0} \log P(v_{i+j} | \Phi(v_i))

其中,viW\sum_{v_i \in W}代表遍历序列里的每一个节点作为中心点。wjw,j0\sum_{-w \le j \le w, j \neq 0}代表对于选定的中心点,预测它左边 ww 个和右边 ww邻居。而那么 P(vi+jΦ(vi))P(v_{i+j} | \Phi(v_i)) 描述的是:在已知当前中心节点是 viv_i 的情况下,它的上下文邻居恰好是 vi+jv_{i+j} 的可能性。

P(vi+jΦ(vi))P(v_{i+j} | \Phi(v_i))又如何计算呢?我们知道,在向量空间里,衡量两个向量像不像最简单的方法就是内积(点积)。两个向量越接近,它们的内积就越大。为了把这个内积变成一个 0 到 1 之间的概率,我们使用 Softmax 函数:

P(uΦ(v))=exp(Φ(u)Φ(v))kVexp(Φ(k)Φ(v))P(u | \Phi(v)) = \frac{\exp(\Phi(u) \cdot \Phi(v))}{\sum_{k \in V} \exp(\Phi(k) \cdot \Phi(v))}

其中的分母则是中心节点 vv 和图中所有节点(包括那些不相关的点)的内积总和。

理解了公式,但我们仍然需要理解为什么 DeepWalk 的优化目标是最大化上面的对数似然函数。想象你是一个侦探,你在空手道俱乐部潜伏了几天。你并不认识每个人,但你看到了很多真实的活动轨迹:小明、小红、小刚在一起喝咖啡,小刚、小强、老王在一起打球。这相当于随机游走路径集合WW

而现在,你手里有一个包含所有节点向量的模型,向量点积大就代表两个人关系较为接近,那么就意味着他们出现在一个随机游走路径中的概率更高。而最大化总概率(即上面的对数似然函数)就意味着我们要不断调整模型里的那些向量坐标,直到模型预测的结果和我们观察到的事实接近(和随机游走出的集合接近)。

DeepWalk 使用的 Word2Vec (Skip-Gram) 模型是一个只有 3 层的神经网络。其输入层是节点的 One-hot 编码向量(维度是 V|V|,全图节点数)。隐藏层没有激活函数,它的神经元个数就是你想要的 Embedding 维度,比如128。输出层为Softmax 层,维度也是 V|V|,用来预测周围每个节点出现的概率。

训练的过程为:

  • 把节点 viv_i 的 One-hot 向量喂给网络。
  • 网络通过当前的权重 W\mathbf{W} 计算出预测概率。
  • 将预测结果与真实的游走序列对比,计算误差。
  • 使用反向传播调整权重 W\mathbf{W}

当训练结束,权重矩阵 W\mathbf{W} 里的每一行就是我们要的 Embedding。也就是说,和一般情况下使用神经网络不同,该任务不训练预测工具,只是通过预测任务,让神经网络生成一组特征向量,这组特征向量可以做各种任务,比如分类。

DeepWalk简单实战

为了能够更好的理解deepwalk的应用,我们做一个简单的例子。我们通过:

1
G = nx.karate_club_graph()

可以加载著名的 Toy Dataset 空手道俱乐部网络。其图结构可以被可视化为图2(a)。在下面的代码实践中,我们需要设计一个DeepWalk类,包含多次随机游走生成序列,并利用 gensim 库的 Word2Vec 类实现训练 Skip-gram 模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import networkx as nx
import random
import numpy as np
from gensim.models import Word2Vec

class DeepWalk:
def __init__(self, graph, walk_length, num_walks, embedding_size):
self.graph = graph
self.walk_length = walk_length
self.num_walks = num_walks
self.embedding_size = embedding_size
self.w2v_model = None

def _single_walk(self, start_node):
"""执行单次随机游走"""
walk = [str(start_node)] # Word2Vec 接收字符串序列
while len(walk) < self.walk_length:
cur = int(walk[-1])
neighbors = list(self.graph.neighbors(cur))
if len(neighbors) > 0:
walk.append(str(random.choice(neighbors)))
else:
break
return walk

def train(self, window_size=5, workers=4):
"""生成序列并训练 Word2Vec"""
nodes = list(self.graph.nodes())
all_walks = []

# 打乱节点顺序增加随机性,提高 Embedding 的鲁棒性
for _ in range(self.num_walks):
random.shuffle(nodes)
for node in nodes:
all_walks.append(self._single_walk(node))

# 训练 Skip-gram 模型 (sg=1)
self.w2v_model = Word2Vec(
all_walks,
vector_size=self.embedding_size,
window=window_size,
sg=1, # Skip-gram 核心
hs=1, # 分层 Softmax 加速
workers=workers,
min_count=0
)
return self.w2v_model

def get_embeddings(self):
"""提取所有节点的 Embedding"""
if not self.w2v_model:
raise ValueError("Model not trained yet!")
return {node: self.w2v_model.wv[str(node)] for node in self.graph.nodes()}

我们来执行一下:

1
2
3
4
G = nx.karate_club_graph()
dw = DeepWalk(G, walk_length=10, num_walks=80, embedding_size=64)
model = dw.train()
embeddings = dw.get_embeddings()

生成了 34 个节点的 64 维向量,可以用于下游任务了,这里以分类任务为例,使用经典的逻辑回归分类器进行分类。为了展示 embedding 的效果,我们仅用20%的数据,就是区区几个点,进行训练。

1
2
3
4
5
6
7
8
9
10
11
12
13
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report, accuracy_score

X = np.array([embeddings[i] for i in G.nodes()])
y = np.array([0 if G.nodes[i]['club'] == 'Mr. Hi' else 1 for i in G.nodes()])

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.8, random_state=42)

clf = LogisticRegression(solver='lbfgs')
clf.fit(X_train, y_train)

y_pred = clf.predict(X_test)

对predict结果做一下评估,显示仅使用 20% 标注样本下的准确率: 0.8571,还是非常不错的。下图(b)展示了分类结果和分类错误的点。

Node2vec

在上文中,我们简单介绍了RandomWalk的实现DeepWalk,然而,DeepWalk 的完全随机游走真的是最优解吗?在真实世界的网络中,当我们说两个节点很相似时,通常包含两种截然不同的物理含义:

  • 一是距离相近、互为邻居、同属一个社区的节点应该具有相似的 Embedding。
  • 二是在网络拓扑中扮演类似角色的节点应该具有相似的 Embedding,哪怕它们在空间上相隔十万八千里。

用文章中专业的语言来说,在复杂网络理论中,节点的相似性通常被归结为两种物理范式:同质性(Homophily)与结构等价性(Structural Equivalence)。

同质性强调物以类聚,即距离相近、同属一个密集社区的节点应当具有高度相似的表征;要捕获这种特征,游走策略需要倾向于深度优先搜索(DFS),以探索社区的宏观边界。相反,结构等价性关注节点在网络拓扑中所扮演的角色(如中心枢纽或边缘节点),即使两个节点在物理空间上相距甚远,只要它们的局部网络结构相似,其表征亦应趋同;捕获这一特征则要求游走策略偏向广度优先搜索(BFS),以充分描绘节点的微观邻域轮廓。

Node2vec 的核心贡献,就是设计了一种有偏的二阶随机游走机制。

假设游走者刚刚通过边 (t,v)(t, v) 从节点 tt 来到了当前节点 vv。现在他站在 vv 上,思考着下一步走向 xx 的概率,这个转移概率定义为πvx\pi_{vx}

πvx=α(t,x)wvx\pi_{vx} = \alpha(t, x) \cdot w_{vx}

其中,wvxw_{vx} 是边 (v,x)(v, x) 的固有权重(如果是无权图,则 wvx=1w_{vx} = 1)。真正的核心在于搜索偏好系数 α(t,x)\alpha(t, x)

Node2vec 引入了两个极其关键的超参数(Hyperparameters)来定义 α(t,x)\alpha(t, x)

  • 返回参数 (Return parameter, pp):控制游走者折返回上一个节点 tt 的概率。
  • 进出参数 (In-out parameter, qq):控制游走者向更远方探索的概率。

根据候选节点 xx 与上一步节点 tt 之间的最短路径距离 dtxd_{tx},系数 α(t,x)\alpha(t, x) 被定义为一个分段函数:

α(t,x)={1pif dtx=0 (即 x=t,退回上一步)1if dtx=1 (即 x 是 t 的直接邻居,在原地打转)1qif dtx=2 (即 x 不与 t 相连,走向更远方)\alpha(t, x) = \begin{cases} \frac{1}{p} & \text{if } d_{tx} = 0 \text{ (即 } x=t \text{,退回上一步)} \\ 1 & \text{if } d_{tx} = 1 \text{ (即 } x \text{ 是 } t \text{ 的直接邻居,在原地打转)} \\ \frac{1}{q} & \text{if } d_{tx} = 2 \text{ (即 } x \text{ 不与 } t \text{ 相连,走向更远方)} \end{cases}

这里我们就不深入展开了,作为DeepWalk的一个升级,我们暂时先大概了解一下其核心方法。

LINE

随机游走方法首先构造了游走序列,再基于序列进行学习,从而得到特征,这样的方法面临着两个问题:

无法处理带权图: 随机游走很难较好的融合边的权重。
缺乏明确的客观函数:Skip-gram 优化的是路径上的共现概率,而不是图拓扑结构本身的概率。

为了解决这些问题,LINE 抛弃了游走,通过定义相似度并优化概率分布的KL散度,来对齐模型的预测结果和真实数据,这两种相似度分别为一阶相似度和二阶相似度。

一阶相似度

一阶相似度描述的是图中有直接边连接的两个节点之间的局部相似性。如果节点 viv_ivjv_j 之间边的权重 wijw_{ij} 很大,那么它们在向量空间中的距离就应该很近。

对于每一条无向边 (i,j)(i, j),LINE 使用 Sigmoid 函数来定义它们在低维向量空间中相连的联合概率:

p1(vi,vj)=11+exp(uiuj)p_1(v_i, v_j) = \frac{1}{1 + \exp(-\vec{u}_i \cdot \vec{u}_j)}

其中,ui\vec{u}_i 为节点 viv_i 的 Embedding 向量。

而在真实网络中,这对节点相连的经验联合概率为该边权重在全图权重中的占比:

p^1(i,j)=wijW\hat{p}_1(i, j) = \frac{w_{ij}}{W}

其中,全图总权重 W=(i,j)EwijW = \sum_{(i,j) \in E} w_{ij}

为了使两个分布对齐,LINE 最小化它们之间的 KL 散度 (Kullback-Leibler Divergence)。省略掉 KL 散度中与参数无关的常数项后,一阶相似度的目标函数被简化为:

O1=(i,j)Ewijlogp1(vi,vj)O_1 = -\sum_{(i, j) \in E} w_{ij} \log p_1(v_i, v_j)

二阶相似度

二阶相似度考察的是节点与邻居的关系。借鉴 NLP 领域的思想,LINE 为每个节点引入了两个角色的向量表示:作为中心节点时的向量 ui\vec{u}_i,以及作为上下文(邻居)时的向量 ui\vec{u}'_i

给定中心节点 viv_i,产生上下文节点 vjv_j预测条件概率通过 Softmax 函数定义:

p2(vjvi)=exp(ujui)k=1Vexp(ukui)p_2(v_j | v_i) = \frac{\exp(\vec{u}'_j \cdot \vec{u}_i)}{\sum_{k=1}^{|V|} \exp(\vec{u}'_k \cdot \vec{u}_i)}

对应地,真实网络中的经验条件概率为:

p^2(vjvi)=wijdi\hat{p}_2(v_j | v_i) = \frac{w_{ij}}{d_i}

其中 di=kN(i)wikd_i = \sum_{k \in N(i)} w_{ik},即节点 viv_i 的出度。

同样使用 KL 散度进行对齐,并且考虑到不同节点的重要性不同(度数越大的节点在网络中越重要),LINE 引入节点的度数 did_i 作为惩罚权重 λi\lambda_i,推导出二阶目标函数:

O2=iVλid(p^2(vi),p2(vi))=(i,j)Ewijlogp2(vjvi)O_2 = \sum_{i \in V} \lambda_i d(\hat{p}_2(\cdot | v_i), p_2(\cdot | v_i)) = -\sum_{(i, j) \in E} w_{ij} \log p_2(v_j | v_i)

模型训练

在分别定义了基于 KL 散度的一阶与二阶目标函数后,LINE 面临的核心问题是如何在低维向量空间中同时兼顾这两种尺度迥异的拓扑信息。理论上,可以通过引入权重超参数将两个目标函数进行线性组合,从而进行联合优化,但实现上在大规模网络中优化这两个函数不太可行。

因此,LINE选择分别训练两次以优化这两个函数。首先是一阶目标函数。在这一阶段,只看图里的直接连边,纯粹使用一阶目标函数 O1O_1 训练模型。经过几轮迭代,全图每个节点都获得了一个 dd 维的向量,称之为一阶 Embedding ui(1)\vec{u}_i^{(1)}

随后是二阶目标函数,这次纯粹使用二阶目标函数 O2O_2 训练模型。同样,每个节点又获得了一个 dd 维的向量。称之为二阶 Embedding ui(2)\vec{u}_i^{(2)}。并最终将两个向量结果首尾拼接:

ufinal=[ui(1),ui(2)]\vec{u}_{final} = [\vec{u}_i^{(1)}, \vec{u}_i^{(2)}]

使用 ufinal\vec{u}_{final} 即可完成接下来的下游任务。

小结

本文简单介绍了图的基本结构,一些指数,以及graph embedding的几个经典方法,虽然不够全面,但获取可以通过这些方法大致了解处理图的一些思想。在下一章中,我们将开始介绍图神经网络。再见。