CS224W摘要17.Scaling Up GNNs


CS224W: Machine Learning with Graphs
公式输入请参考: 在线Latex公式
这节内容貌似也很重要,是针对大规模图数据的优化。之前对这方面的了解只知道用GraphSAGE可以分Batch,貌似还有别的方法。
针对无法对GNN进行随机梯度下降的问题,搞出了GraphSAGE;
针对无法将大图直接进行full batch计算的问题,搞出了Cluster-GCN;
针对GCN模型本身进行了简化,去掉了非线性的计算,并进行了化简。

Scaling Up GNNs to Large Graphs

当前图应用的数据量

应用数据集数据量常见任务
Recommender systemsAmazon
YouTube
Pinterest
Users(绿圆): 100M~1B
Products/Videos(红方):10M ~ 1B
Recommend items(link prediction)
Classify users/items(node classification)
在这里插入图片描述
Social networksFacebook
Twitter
Instagram
Users:300M~3BFriend recommendation (link-level)
User property prediction(node-level)
在这里插入图片描述
Academic graphMicrosoft Academic GraphPapers:120M
Authors:120M
Paper categorization(node classification)
Author collaboration recommendation
Paper citation recommendation(link prediction)
在这里插入图片描述
Knowledge GraphsWikidata
Freebase
Entities:80M~90MKG completion
Reasoning
在这里插入图片描述

特点

尺寸大:节点数从10M到10B;边数量从100M到100B。
常见任务:
节点级别:User/item/paper classification
边级别:Recommendation, completion

SGD for GNN?

对于传统的ML优化方法当然就是GD:
l ( θ ) = 1 N ∑ i = 0 N − 1 l i ( θ ) \mathcal{l}(\theta)=\cfrac{1}{N}\sum_{i=0}^{N-1}l_i(\theta) l(θ)=N1i=0N1li(θ)
对于数据量较大的时候,要计算所有的点再进行梯度更新效率很低,因此常用随机梯度下降法,每次随机取 M ( < < N ) M(<<N) M(<<N)个样本形成mini-batches,这个时候计算 M M M个样本的梯度 l s u b ( θ ) l_{sub}(\theta) lsub(θ)更新即可: θ ← θ − ▽ l s u b ( θ ) \theta\leftarrow\theta-\triangledown l_{sub}(\theta) θθlsub(θ)
那用这个思路把SGD用在GNN上来解决GNN面临的大数据量的问题可以吗?
假设我们从图中随机取 M ( < < N ) M(<<N) M(<<N)独立的节点
在这里插入图片描述
既然是独立的节点,那么采样出来的节点就是孤立的点,这样就没有办法做消息的聚合与传递了,GNN也没法玩了。
因此,原始的SGD无法用在GNN上。

Naïve full-batch implementation for GNN?

我们再看看Naïve full-batch的方式,每次生成所有节点的表征。
在这里插入图片描述
可以看到
1.训练过程需要加载全图的所有节点及特征
2.在每个GNN层中,都要基于前一层的所有节点的embedding计算当前层所有节点的embedding
3.计算损失
4.做GD
当前一般的DL都是用GPU来加速运算,GPU的内存一般是(10GB–20GB)6GB显存本本默默流泪。。。。这个数据量根本加载不进来:
在这里插入图片描述
看了直接硬train也不行,下面看三种解决方案。

Neighbor Sampling: GraphSAGE1

之前写过2,这里看了讲解有新的领悟,重新整理一下。
这个方法改进有三个部分:

基于邻域的随机梯度下降

SGD之所以无法用在GNN上是因为单个节点的采样会丢失邻居的信息,导致GNN的消息汇聚然并卵。
从GNN的计算图中可以看到,一个K层GNN的消息汇聚只涉及到该节点的K跳邻居:
在这里插入图片描述
那么采样的时候不单单采样某个节点,而是直接将该节点以及其K跳邻域信息包含进来,形成mini-batch:
在这里插入图片描述
这样就得到了基于邻域的SGD算法,具体描述如下:
1.随机采样 M ( < < N ) M(<<N) M(<<N)个节点
2.对于每个采样节点 v v v
2.1获取其K跳邻居,并构造计算图
2.2用计算图生成节点 v v v的embedding
3.计算 M M M个节点的梯度 l s u b ( θ ) l_{sub}(\theta) lsub(θ)
4.更新梯度: θ ← θ − ▽ l s u b ( θ ) \theta\leftarrow\theta-\triangledown l_{sub}(\theta) θθlsub(θ)

好处与问题

这里将计算图代替单个节点,即可实现mini-batch,又能保证图的信息汇聚不变,当然是效率提高的,但是也存在一个问题。在2.1步中,生成计算图非常耗费资源,因为图的邻居节点数量增长是K跳的指数级:
在这里插入图片描述
另外对于一些图中的超级节点,例如某个大V的粉丝好几百万,意味该节点的邻居超多,做2.2步的时候会很慢:
在这里插入图片描述

邻居采样

使用邻居采样进一步压缩计算图。这个也是SAGE的由来sample+aggregate。其思想就是在每跳邻居中采样 H H H个邻居,下面是 H = 2 H=2 H=2的例子
在这里插入图片描述
邻居采样(相当于计算树剪枝)后在进行SGD。这里只需要将前面的2.1换成下面的步骤:
对于K层GNN的邻居采样描述如下:
1.对于 k = 1 , 2 , ⋯   , K : k=1,2,\cdots,K: k=1,2,,K:
1.1对于每个第 k k k跳的邻居,最多随机采样 H k H_k Hk个邻居
2.得到最多包含 ∏ k = 1 K H k \prod_{k=1}^KH_k k=1KHk个叶子节点的计算图

好处与问题

较小的 H H H可以使得邻居汇聚效率大大增加,但会使得模型的训练不够稳定,因为每次随机出来邻居不一样。
虽然有了 H H H个邻居的上限,计算图大小的上限仍然和K跳(GNN的层数也是它)呈指数关系,K增加还是会使得计算图变很大。
最大的问题是随机采样,因为图中的节点明显有不一样的重要程度,采样到不重要的邻居得到embedding的结果明显不是最优的。

邻居的选择

为了解决随机采样的问题,这块研究还有待进一步研究,目前的解决方法是采取策略来采样重要的点:
在这里插入图片描述
例如上图中的策略是:
从绿色点开始可回原地随机游走,并计算Restarts score: R i R_i Ri(直觉上:这个玩意越高说明该节点涉及到的内部节点越多,就是random walk with restarts,RWR算法)
在每层GNN的邻居采样中对高 R i R_i Ri的邻居采样。

小结及改进思路

该方法是目前工业上应用较成熟的方法。pintrest?阿里都在用
但是该方法仍然有一些缺点:
1.计算图的大小仍然和GNN的层数成指数关系
2.计算过程非常冗余,尤其是当邻域中多个节点共享邻居的时候(在同一个mini-batch中),该邻居会在计算图中出现多次,例如:
在这里插入图片描述
可以看到C和D都是AB的公共邻居,每个都计算了两次,考虑某个大V节点岂不是要计算很多次?
再回头看full-batch GNN的实现过程,所有的节点都用前一层的embedding结果来更新当前层的embedding,不存在上面的重复计算问题:
在这里插入图片描述
而且,从计算公式可以看到,在每一层的消息汇聚,只用计算 2 × E 次 , E 2\times E次,E 2×E,E是边数量, u u u的消息汇聚给 v v v v v v的消息汇聚给 u u u
在这里插入图片描述
对于 K K K层的GNN,那么计算次数为: 2 K E 2KE 2KE,也就是说整个计算过程的复杂度分别与层数、边数成线性关系,非常快。
也就是说full-batch GNN的layer-wise node embedding update方法可重复使用前一层的embedding结果,不需要冗余的计算和邻居的采样。但是,它的问题在于内存放不下,下面看从full-batch如何解决GNN的大图训练问题。

PS:这里还有另外一个模型HAG,层次化聚合图模型也是类似思想,用的是层次化的划分思想。

Cluster-GCN

子图采样

既然上面讨论了大图有很多优势,但是由于内存方面的限制导致这个方法无法使用,那么可以考虑将大图拆分成可以放进内存的小图,然后再计算的思路:
在这里插入图片描述
那么这里就稍微看看这个方法的可行性如何,或者说拆分后效果会不会扑街。
由于GNN的计算是基于邻居节点的消息汇聚机制的,那么,如果切分后的子图能够最大限度的保留原图的邻域信息,那么切割后子图消息汇聚产生的embedding和原图应该是差不多的。
在这里插入图片描述
从上面的例子看,在子图采样要最大化保证原来的connectivity,分开但丢边少。
由于现实存在的图中包含较为丰富的社区结构,因此将图中的社区采样出来作为子图,每个子图可以包含原图的local connectivity pattern。
在这里插入图片描述

Cluster-GCN overview

给定图 G = ( V , E ) G=(V,E) G=(V,E),将其节点 V V V划分为 C C C个组: V 1 , V 2 , ⋯   , V C V_1,V_2,\cdots,V_C V1,V2,,VC
为了保证社区的完整性,可以使用已有的社区检验方法,例如:Louvain, METIS3
每个小组的节点 V 1 , V 2 , ⋯   , V C V_1,V_2,\cdots,V_C V1,V2,,VC生成对应的 C C C个子图: G 1 , G 2 , ⋯   , G C G_1,G_2,\cdots,G_C G1,G2,,GC,每个子图有以下关系:
G C ≡ ( V C , E C ) , where  E c = { ( u , v ) ∣ u , v ∈ V c } G_C\equiv (V_C,E_C),\\ \text{where }E_c=\{(u,v)|u,v\in V_c\} GC(VC,EC),where Ec={(u,v)u,vVc}
每个子图之间没有边相连:
在这里插入图片描述

Cluster-GCN: MIni-batch Training

1.对每个mini-batch,随机采样一个节点组: V c V_c Vc
2.构造induced subgraph: G c = ( V c , E c ) G_c= (V_c,E_c) Gc=(Vc,Ec)
在这里插入图片描述
3.对 G c G_c Gc使用GNN的layer-wise node embedding update(就是对这个子图用full batch的GNN进行计算),得到每个节点的embedding: h v , v ∈ V c h_v,v\in V_c hv,vVc
在这里插入图片描述
4.计算每个节点损失并取平均:
l s u b ( θ ) = 1 ∣ V c ∣ ⋅ ∑ v ∈ V c l v ( θ ) l_{sub}(\theta)=\cfrac{1}{|V_c|}\cdot\sum_{v\in V_c}l_v(\theta) lsub(θ)=Vc1vVclv(θ)
5.更新参数:
θ ← θ − ▽ l s u b ( θ ) \theta\leftarrow\theta-\triangledown l_{sub}(\theta) θθlsub(θ)

Cluster-GCN的问题

Graph community detection algorithm对图进行聚类后,每个社区只包含全部数据中的一小部分
在这里插入图片描述
生成的induced subgraph去掉了一些边,准确的说是去掉了社区与社区之间的边,也就是社区之间没有消息的汇聚了,这里就会降低GNN的性能。
在这里插入图片描述
也就是说子图中的节点没有足够的diverse来表达整个图的结构;
此外,由于节点的损失是在每个社区内部计算的,社区到社区的样本分布差异会使得梯度的方差很大,最终导致SGD的收敛性变差。

Cluster-GCN进阶版

对于上面问题的解决方案就是每个mini-batch一次性聚合多个组。
大白话就是大图放不进内存,就想法子切小了放,切太小图被切变样了,性能扑街,现在切不大不小,刚好。
除了切分方式不一样(Sampling multiple node groups),其他计算步骤都一样。
在这里插入图片描述

Cluster-GCN进阶版步骤

Pre-processing step:
给定图 G = ( V , E ) G=(V,E) G=(V,E),将其节点 V V V划分为 C C C个组: V 1 , V 2 , ⋯   , V C V_1,V_2,\cdots,V_C V1,V2,,VC
这里和原始的Cluster-GCN的划分相比,组的规模要小一些,因为待会要进行组合,单个组太大组合内存会爆。

Mini-batch training:
1.对于每个mini-batch,随机采样属于一个组集合的节点 q q q
{ V t 1 , ⋯   , V t q ⊂ } { V 1 , V 2 , ⋯   , V C } \{V_{t_1},\cdots,V_{t_q}\subset\} \{V_1,V_2,\cdots,V_C\} {Vt1,,Vtq}{V1,V2,,VC}
2.将所有节点组集合中的所有节点进行信息汇聚:(感觉这个步骤应该在后面,这里只是做集合)
V a g g r = V t 1 ∪ ⋯ ∪ V t q V_{aggr}=V_{t_1}\cup\cdots\cup V_{t_q} Vaggr=Vt1Vtq
3.构建induced subgraph
G a g g r = ( V a g g r , E a g g r ) where  E a g g r = { ( u , v ) ∣ u , v ∈ } V a g g r G_{aggr}=(V_{aggr},E_{aggr})\\ \text{where }E_{aggr}=\{(u,v)|u,v\in \}V_{aggr} Gaggr=(Vaggr,Eaggr)where Eaggr={(u,v)u,v}Vaggr
注意,这里的 E a g g r E_{aggr} Eaggr包含组间的边。
后面的步骤略。

时间复杂度比较GraphSAGE vs Cluster-GCN

假定:我们使用 K K K成生成 M ( < < N ) M(<<N) M(<<N)个节点的embedding。这里 N N N是总的节点数量。
基于Neighbor-sampling的GraphSAGE:
如果每层采样 H H H个节点,对于每个节点, K K K层计算图共有 H K H^K HK个节点
要计算 M M M个节点,总的计算量为: M ⋅ H K M\cdot H^K MHK
在这里插入图片描述
Cluster-GCN:
M M M个节点的induced subgraph执行消息传递,如果子图平均度为: D a v g D_{avg} Davg,那么子图边数量为: M ⋅ D a v g M\cdot D_{avg} MDavg,对于 K K K层的消息传递而言,计算量为: K ⋅ M ⋅ D a v g K\cdot M\cdot D_{avg} KMDavg
二者不同量纲无法比较优劣,我们假设 H = D a v g / 2 H=D_{avg}/2 H=Davg/2,也就是采样约50%的邻居,此时Cluster-GCN的计算量为: 2 M H K 2MHK 2MHK要远远小于GraphSAGE 的 M ⋅ H K M\cdot H^K MHK

Simplified GCN4

GCN回顾

这块之前有写过一点点笔记,但是重新听了一遍有新的领悟,记录一下。
从简化GCN模型的思路出发,还有FastGCN、 Light GCN,具体看笔记。
先复习一把GCN,这里不写了,直接上GCN的矩阵形式:
H ( k ) = [ h 1 ( 1 ) ⋯ h ∣ V ∣ ( k ) ] H^{(k)}=[h_1^{(1)}\cdots h_{|V|}^{(k)}] H(k)=[h1(1)hV(k)]
在这里插入图片描述
记图的邻接矩阵为 A A A,这里的邻接矩阵对角线为1,即包含self-loop
则节点的消息聚合可表示为:
∑ u ∈ N ( v ) h u ( k ) = A v , : H ( k ) \sum_{u\in N(v)}h_u^{(k)}=A_{v,:}H^{(k)} uN(v)hu(k)=Av,:H(k)
记度矩阵为对角矩阵 D D D
D v , v = Deg ( v ) = ∣ N ( v ) ∣ D_{v,v}=\text{Deg}(v)=|N(v)| Dv,v=Deg(v)=N(v)
当然, D − 1 D^{-1} D1也是对角矩阵:
D v , v − 1 = 1 ∣ N ( v ) ∣ D_{v,v}^{-1}=\cfrac{1}{|N(v)|} Dv,v1=N(v)1
消息聚合可以写成:
1 ∣ N ( v ) ∣ ∑ u ∈ N ( v ) h u ( k ) → 矩 阵 形 式 D − 1 A H ( k ) \cfrac{1}{|N(v)|}\sum_{u\in N(v)}h_u^{(k)}\xrightarrow[]{矩阵形式}D^{-1}AH^{(k)} N(v)1uN(v)hu(k) D1AH(k)

GCN的中第 v v v个节点在第 k k k层的embedding可以写为:
h v ( k + 1 ) = ReLU ( W k 1 ∣ N ( v ) ∣ ∑ u ∈ N ( v ) h u ( k ) ) h_v^{(k+1)}=\text{ReLU}\left(W_k\cfrac{1}{|N(v)|}\sum_{u\in N(v)}h_u^{(k)}\right) hv(k+1)=ReLUWkN(v)1uN(v)hu(k)
矩阵形式为:
H ( k + 1 ) = ReLU ( A ~ H ( k ) W k T ) where  A ~ = D − 1 (1) H^{(k+1)}=\text{ReLU}(\tilde AH^{(k)}W_k^T)\\ \text{where }\tilde A=D^{-1}\tag1 H(k+1)=ReLU(A~H(k)WkT)where A~=D1(1)
老师注明了一下:原始版本的 A ~ = D − 1 / 2 A D − 1 / 2 \tilde A=D^{-1/2}AD^{-1/2} A~=D1/2AD1/2
原始版本的 A ~ \tilde A A~性能要好,这里为啥?

Simplified GCN简化过程

下面看去掉公式1中的非线性ReLU,并化简:
在这里插入图片描述
最后结果写成:
H ( K ) = A ~ K X W T H^{(K)}=\tilde A^KXW^T H(K)=A~KXWT
由于 A ~ K X \tilde A^KX A~KX不包含可学习的参数,因此它可以提前先算好,这里的这个 A ~ K \tilde A^K A~K相当于邻接矩阵的 K K K次方,之前有分析过5这个代表 K K K阶邻居相连。
这个计算由于是一系列的稀疏矩阵的乘法,非常快。


X ~ = A ~ K X W T \tilde X=\tilde A^KXW^T X~=A~KXWT为预先计算好的矩阵,那么矩阵形式就可以写为:
H ( K ) = X ~ W T H^{(K)}=\tilde XW^T H(K)=X~WT
这个形式就是相当于矩阵 X ~ \tilde X X~的线性变换!对于每个节点的embedding而言:
h v ( K ) = W X ~ v h_v^{(K)}=W\tilde X_v hv(K)=WX~v
X ~ v \tilde X_v X~v是矩阵 X ~ \tilde X X~中的节点 v v v对应的预先计算的特征,就是矩阵中的某一行。整个计算不涉及其他节点,因此,计算出矩阵后 X ~ \tilde X X~,我们可以并行的计算 M M M个节点 { v 1 , v 2 , ⋯   , v M } \{v_1,v_2,\cdots,v_M\} {v1,v2,,vM}的embedding:
h v 1 ( K ) = W X ~ v 1 , h v 2 ( K ) = W X ~ v 2 , ⋯ h v M ( K ) = W X ~ v M . (2) h_{v_1}^{(K)}=W\tilde X_{v_1},\\ h_{v_2}^{(K)}=W\tilde X_{v_2},\\ \cdots\\ h_{v_M}^{(K)}=W\tilde X_{v_M}.\tag2 hv1(K)=WX~v1,hv2(K)=WX~v2,hvM(K)=WX~vM.(2)

小结

simplified GCN模型可以分两步:
1.Pre-processing step:先算矩阵 X ~ \tilde X X~
2.Mini-batch training step:
2.1对每个mini-batch,随机采样 M M M个节点
2.2按公式2分别计算每个节点的embedding
3.利用embedding进行预测或者计算Loss
4.使用SGD更新参数

与前面两种思路的比较

相比neighbor sampling:Simplified GCN不用构造计算图,因此生成节点embedding更高效。
相对于Cluster-GCN:Simplified GCN的Mini-batch中的节点是从整个图中进行采样的(各个节点之间的计算没有相互依赖),不需要从子图中进行采样,因此其SGD的方差在训练过程中较小。

存在问题

由于Simplified GCN简化了非线性部分,因此它的表达能力相对于原始GCN是变弱了的。但是在模型的文章中Simplified GCN的表现虽然差,但是并没有差很多,但是效率确实很好。
究其原因,因为图的同质性(Graph homophily),相邻节点(有边连接)通常会趋于相同标签,例如:
在引文网络,存在引用关系的文章一般都是相同领域的文章;
在电影推荐系统,两个好基友通常会喜欢同类型的电影。
Simplified GCN的preprocessing step中,计算的 A ~ K X \tilde A^KX A~KX实际上是不断将其 K K K跳邻居特征进行平均后迭代到当前节点上,因此这个也暗自符合了图的同质性,因此Simplified GCN在有同质性的图上效果非常棒,对于那些同质性较差的图,Simplified GCN效果就很扑街。


  1. Inductive Representation learning on Large Graphs ↩︎

  2. 深度之眼Paper带读笔记GNN.07.GraphSAGE ↩︎

  3. CS224W摘要13.Community Detection in Networks ↩︎

  4. Simplified GCN ↩︎

  5. CS224W摘要02.Traditional Methods for Machine Learning in Graphs ↩︎

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

oldmao_2000

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值