Re0:读论文 PPNP/APPNP Predict then Propagate: Graph Neural Networks meet Personalized PageRank

诸神缄默不语-个人CSDN博文目录

论文全名:Predict then Propagate: Graph Neural Networks meet Personalized PageRank
模型简称:APPNP
(其实第一个提出的模型应该是PPNP,但是没人用PPNP,都用的是APPNP)
论文ArXiv地址:https://arxiv.org/abs/1810.05997

APPNP是2019年ICLR论文,做节点表征,大概逻辑就是直接做GCN节点传播相当于做随机游走,这会导致所有节点的表征最后趋于相同,即所谓over-smoothing问题,因此传统GNN不能卷太多层。因为本文提出PPNP模型,先对节点表征进行线性转换(predict),然后用PPR来进行信息传播(propagate),这样就能保留节点本身的特征了。但是PPNP的计算代价太高,因为本文又提出了APPNP模型,用多次迭代RWR来模拟PPR(RWR的极限状态)。
别的都忘了,我现在自己看下面的内容都已经快要看不懂了……我理论一直都不太好,太久没看更是忘得一干二净。

1. 模型构造思路

整体思路:
message passing系模型都很难将聚集的邻居扩大,也就是多卷几层扩大感受野。一是因为聚合求平均太多层会平滑,即over-smoothing问题,本文主要关注这一问题;二是因为层数增多也会增多参数,但是这一问题可以用共享参数解决,本文重点不在此,但本文提出的方法也成功减少了参数。
message passing本质是Laplacian smoothing,message passing系GNN(如GCN等)会出现over-smoothing问题,即如果网络层数增多,各节点的嵌入都会趋于相近,就无法反映各节点的自有特征。
因此这些模型无法加深层数,只能在较近的邻居之间传播信息,限制其表示能力。但是在需要更多信息,尤其是对于边缘节点(实证结果见Appendix I)和有标签节点较少(实证结果见Figure 3和Appendix H)时,就是需要远程传播信息,所以本文提出了能够更远、更深传播信息而不over-smooth的 PPNP / APPNP 模型。
原始GCN节点之间的影响程度与随机游走分布成比例,随机游走最终会趋于稳定,所以GCN节点影响程度也会趋于相同。PageRank得分即随机游走稳定分布,会得到全图的结构信息。而使用以根节点为teleport set 的 Personalized PageRank(PPR)方法能得到各节点独有的局部结构信息,这样就能保存住各节点的独有信息。
本文提出的PPNP将predict和propagate阶段拆开,在predict阶段仅用节点特征来进行预测,在propagate阶段用PPR对预测值进行信息传递,这样能在远程传播中仍然保留节点局部信息,而且不需要过多的参数。
PPNP使PPR收敛至稳定状态。由于PPNP计算代价过高,在此基础上提出了代价较小的近似模型APPNP,只迭代有限次PPR。

PPR引入的思路:
根据[JK]1,GNN中节点 x x x y y y 的influence score: I ( x , y ) = ∑ i ∑ j ∂ Z y i ∂ X x j I(x,y)=\sum_i\sum_j\frac{\partial\mathbf{Z}_{yi}}{\partial\mathbf{X}_{xj}} I(x,y)=ijXxjZyi x x x 特征各项元素对 y y y 嵌入各项元素的影响程度的加总,感觉很有点经济学弹性概念内味2。在k层GCN中, I ( x , y ) ∝ P r w ′ ( x → y , k ) I(x,y)∝P_{rw'}(x\rightarrow y,k) I(x,y)Prw(xy,k)(一个经微调的(没说咋调的,看意思应该是把转移矩阵换成 A ~ ^ \hat{\tilde{A}} A~^)从 x x x 开始的random walk distribution)
k → ∞ k\rightarrow\infty k 且图 irreducible and aperiodic 时,该值会趋于一个与 x x x 无关的稳定分布( P l i m ( → y ) P_{lim}(\rightarrow y) Plim(y)),这个分布可通过 π l i m = A ~ ^   π l i m \pi_{lim}=\hat{\tilde{\mathbf{A}}}\ \pi_{lim} πlim=A~^ πlim 计算得到。也就是说任何节点对该节点的影响程度最后会是一个相同的值,这样跟节点的局部信息就无关了。
这样证明了GCN和RW的关系(我没仔细看JK文章,反正APPNP逻辑应该是这样),此外根据[BP]3 我们知道原始PageRank就是随机游走的稳定分布( π p r = A r w   π p r \pi_{pr}=\mathbf{A}_{rw}\ \pi_{pr} πpr=Arw πpr),体现整个图的全局结构。PPR的结果则会考虑到我们感兴趣的节点集,而APPNP本文对根节点感兴趣,也就相当于跑了个RWR(Random Walk with Restart)( π p p r ( i x ) = ( 1 − α ) A ~ ^ π p p r ( i x ) + α   i x \pi_{ppr}(\mathbf{i}_x)=(1-\alpha)\hat{\tilde{\mathbf{A}}}\pi_{ppr}(\mathbf{i}_x)+\alpha\ \mathbf{i}_x πppr(ix)=(1α)A~^πppr(ix)+α ix)。
这样从每个节点开始随机游走直至稳定最后得到的PPR就能保存根节点局部结构信息。 I ( x , y ) I(x,y) I(x,y) ∝ PPR π p p r ( i x ) y \pi_{ppr}(\mathbf{i}_x)_y πppr(ix)y 与根节点有关。

2. Notation和模型介绍

2.1 notation

图  G = ( V , E ) n = ∣ V ∣ m = ∣ E ∣ 节点特征  X ∈ R n × f 节点标签(独热编码) Y ∈ R n × c 邻接矩阵  A A ~ = A + I n D ~ i i = ∑ j A ~ i j A r w = A D − 1 A ~ ^ = D ~ − 1 2 A ~ D ~ − 1 2 influence score  I ( x , y ) = ∑ i ∑ j ∂ Z y i ∂ X x j 随机游走分布  P 随机游走稳定分布/PageRank/PPR  π \begin{aligned} 图\ &G=(V,E) \\ &n=|V| \\ &m=|E| \\ 节点特征\ &\mathbf{X}\in\mathbb{R}^{n\times f} \\ 节点标签(独热编码)&\mathbf{Y}\in\mathbb{R}^{n\times c} \\ 邻接矩阵\ &\mathbf{A} \\ &\tilde{\mathbf{A}}=\mathbf{A}+\mathbf{I}_n \\ &\tilde{\mathbf{D}}_{ii}=\sum_j\tilde{\mathbf{A}}_{ij} \\ &\mathbf{A}_{rw}=\mathbf{A}\mathbf{D}^{-1} \\ &\hat{\tilde{\mathbf{A}}}=\tilde{\mathbf{D}}^{-\frac{1}{2}}\tilde{\mathbf{A}}\tilde{\mathbf{D}}^{-\frac{1}{2}} \\ \text{influence score}\ &I(x,y)=\sum_i\sum_j\frac{\partial\mathbf{Z}_{yi}}{\partial\mathbf{X}_{xj}} \\ 随机游走分布\ &P \\ \text{随机游走稳定分布/PageRank/PPR}\ &\pi \end{aligned}  节点特征 节点标签(独热编码)邻接矩阵 influence score 随机游走分布 随机游走稳定分布/PageRank/PPR G=(V,E)n=Vm=EXRn×fYRn×cAA~=A+InD~ii=jA~ijArw=AD1A~^=D~21A~D~21I(x,y)=ijXxjZyiPπ
(那个 D ~ \tilde{\mathbf{D}} D~我用的是GCN的写法,就是度矩阵。因为我没看懂PPNP本文的写法里面那个 δ \delta δ是啥东西?但是它说用的是GCN里面的表示法,所以我就去GCN那边抄公式了)

2.2 PPNP公式

predict: H i , : = f θ ( X i , : ) \mathbf{H}_{i,:}=f_\theta(\mathbf{X}_{i,:}) Hi,:=fθ(Xi,:)
f f f:仅使用每个节点的特征建立神经网络模型,神经网络参数为 θ \theta θ,得到预测结果 H ∈ R n × c \mathbf{H}\in\mathbb{R}^{n\times c} HRn×c

propagate: Z PPNP = softmax ( α ( I n − ( 1 − α ) A ~ ^ ) − 1 H ) \mathbf{Z}_{\text{PPNP}}=\text{softmax}\Big(\alpha\big(\mathbf{I}_n-(1-\alpha)\hat{\tilde{\mathbf{A}}}\big)^{-1}\mathbf{H}\Big) ZPPNP=softmax(α(In(1α)A~^)1H)
这里的 A ~ ^ \hat{\tilde{\mathbf{A}}} A~^ 可以替换成任何propagation matrix(例如 A r w \mathbf{A}_{rw} Arw(我的理解是可以换成任何一个可作为状态转移矩阵的stochastic matrix)

2.3 APPNP公式

PPR矩阵 Π ppr = α ( I n − ( 1 − α ) A ~ ^ ) − 1 \Pi_{\text{ppr}}=\alpha\big(\mathbf{I}_n-(1-\alpha)\hat{\tilde{\mathbf{A}}}\big)^{-1} Πppr=α(In(1α)A~^)1 是个稠密矩阵,PPNP的复杂度达 O ( n 2 ) \mathcal{O}(n^2) O(n2)
(其实矩阵稀疏和稠密这块我也还不了解,就大概看起来是这么一回事吧)

(就我感觉这个简化写法就类似于PageRank的power iteration不迭代到收敛,但是在论文中提到了topic-sensitive PageRank,我没看那个论文,所以不理解这部分含义。总之逻辑大概就是模拟RWR)

Z ( 0 ) = H = f θ ( X ) \mathbf{Z}^{(0)}=\mathbf{H}=f_\theta(\mathbf{X}) Z(0)=H=fθ(X)
Z ( k + 1 ) = ( 1 − α ) A ~ ^ Z ( k ) + α H \mathbf{Z}^{(k+1)}=(1-\alpha)\hat{\tilde{\mathbf{A}}}\mathbf{Z}^{(k)}+\alpha\mathbf{H} Z(k+1)=(1α)A~^Z(k)+αH
Z ( K ) = softmax ( ( 1 − α ) A ~ ^ Z ( K − 1 ) + α H ) \mathbf{Z}^{(K)}=\text{softmax}\big((1-\alpha)\hat{\tilde{\mathbf{A}}}\mathbf{Z}^{(K-1)}+\alpha\mathbf{H}\big) Z(K)=softmax((1α)A~^Z(K1)+αH)

其中 k ∈ [ 0 , K − 2 ] k\in[0,K-2] k[0,K2]
prediction matrix H \mathbf{H} H 同时作为 starting vector 和 teleport set
保持矩阵稀疏度,而且不会构建出 n × n n\times n n×n 的大方阵。

APPNP只有线性复杂度。

迭代收敛证明见Appendix B。

3. 详细的数学推导和证明

3.1 message passing系GNN的over-smoothing问题

就我之前对此问题的理解就很直觉,就是感受野越广,各节点邻居重叠越大,所以得到的结果就越像(就,一样的邻居嘛……)。(来自cs224w,可参考我之前撰写的笔记:cs224w(图机器学习)2021冬季课程学习笔记9 Graph Neural Networks 2: Design Space

在本文中提到GCN本质上是Laplacian smoothing,给了两篇参考文献:
Qimai Li, Zhichao Han, and Xiao-Ming Wu. Deeper Insights Into Graph Convolutional Networks for Semi-Supervised Learning. In AAAI, 2018.
Keyulu Xu, Chengtao Li, Yonglong Tian, Tomohiro Sonobe, Ken-ichi Kawarabayashi, and Stefanie Jegelka. Representation Learning on Graphs with Jumping Knowledge Networks. In ICML, 2018.
就我简单看了一下第一篇作者自己写的介绍:Laplacian Smoothing and Graph Convolutional Networks – Qimai’s Home实话实说,没有看懂。就我委实没有搞懂拉普拉斯矩阵那一堆是在搞什么

然后第二篇也是提出influence score I ( x , y ) I(x,y) I(x,y) 的那篇论文。论文里与之相关的内容我在第一部分和3.2部分写了。

3.2 GCN收敛,RW极限,PageRank和PPR,influence score

PageRank的矩阵表达式、power iteration等可参考我之前写的博文:cs224w(图机器学习)2021冬季课程学习笔记4 Link Analysis: PageRank (Graph as Matrix)

随着GCN层数增加,influence score I ( x , y ) I(x,y) I(x,y) 与RW的分布成正比,这个分布随着迭代数(层数)增加,最后会收敛到与起始节点无关的稳定状态。
RW的极限分布 π \pi π 与起始节点(根节点)无关,这个极限分布也是PageRank的结果 π \pi π


原始PageRank迭代式: π = A r w ⋅ π \pi=\mathbf{A}_{rw}\cdot \pi π=Arwπ
A r w = A D − 1 \mathbf{A}_{rw}=\mathbf{A}\mathbf{D}^{-1} Arw=AD1

带自环 + teleport set(图中任一节点)的PageRank迭代式: π = ( 1 − α ) A ~ r w ⋅ π + α [ 1 N ] N \pi=(1-\alpha)\tilde{\mathbf{A}}_{rw}\cdot \pi+\alpha\left[\dfrac{1}{N}\right]_{N} π=(1α)A~rwπ+α[N1]N
A ~ r w = A ~ D ~ − 1 \tilde{\mathbf{A}}_{rw}=\tilde{\mathbf{A}}\tilde{\mathbf{D}}^{-1} A~rw=A~D~1 [ 1 N ] N \left[\dfrac{1}{N}\right]_{N} [N1]N 是每个元素都是 1 N \dfrac{1}{N} N1 的向量)


本文使用的PPR的teleport就是根节点: π p p r ( i x ) = ( 1 − α ) A ~ ^ π p p r ( i x ) + α   i x \pi_{ppr}(\mathbf{i}_x)=(1-\alpha)\hat{\tilde{\mathbf{A}}}\pi_{ppr}(\mathbf{i}_x)+\alpha\ \mathbf{i}_x πppr(ix)=(1α)A~^πppr(ix)+α ix ①
A ~ ^ = D ~ − 1 2 A ~ D ~ − 1 2 \hat{\tilde{\mathbf{A}}}=\tilde{\mathbf{D}}^{-\frac{1}{2}}\tilde{\mathbf{A}}\tilde{\mathbf{D}}^{-\frac{1}{2}} A~^=D~21A~D~21
我就是看不懂为什么能这样换转移矩阵!

PPR能够保留初始节点的信息,这事在直觉上还挺明显的,就你一直在试图往回跳嘛,那最后的稳定状态肯定是跟teleport set有关的。
严谨证明不知道有没有,我还没看PageRank和主题PageRank的论文。

上式做线性转换易得: π p p r ( i x ) = α [ I n − ( 1 − α ) A ~ ^ ] − 1 i x \pi_{ppr}(\mathbf{i}_x)=\alpha\big[\mathbf{I}_n-(1-\alpha)\hat{\tilde{\mathbf{A}}}\big]^{-1}\mathbf{i}_x πppr(ix)=α[In(1α)A~^]1ix

用单位阵 I I I 代替指示向量 i x \mathbf{i}_x ix
PPR矩阵: Π p p r ( i x ) = α [ I n − ( 1 − α ) A ~ ^ ] − 1 \Pi_{ppr}(\mathbf{i}_x)=\alpha\big[\mathbf{I}_n-(1-\alpha)\hat{\tilde{\mathbf{A}}}\big]^{-1} Πppr(ix)=α[In(1α)A~^]1
逆必存在,证明见Appendix A。
PPR矩阵对应行列的元素就是对应节点之间的influence score。

PPNP公式就是直接用PPR矩阵左乘 H \mathbf{H} H(predict输出)。
就相当于直接求以 H \mathbf{H} H 为starting vector的RWR(以根节点为teleport set的PPR)的最终稳定分布。

APPNP公式就是用①式进行跑RWR,以 H \mathbf{H} H 作为teleport set和初始starting vector。
直觉大概可以理解为通过RWR把信息传播到K(迭代数)层邻居上。
通过Appendix B证明APPNP迭代最终收敛到PPNP公式上。

3.3 A r w \mathbf{A}_{rw} Arw A ~ ^ \hat{\tilde{\mathbf{A}}} A~^

反正都能拿来当RW的转移矩阵,而且公式里写明了可以互换。但是具体咋回事我还妹整明白。

A r w \mathbf{A}_{rw} Arw 的话我能理解,因为PageRank的公式就是这么写的,就是 r j = ∑ i → j 1 d i ⋅ r i r_j=\sum\limits_{i\rightarrow j}\dfrac{1}{d_i}\cdot r_i rj=ijdi1ri嘛。
带上自环就是带上自环了嘛。

A ~ ^ \hat{\tilde{\mathbf{A}}} A~^ 是咋回事?GCN那块数学我就没看懂,难道我还要再磨一趟GCN吗……
这玩意它满足stochastic matrix的要求不我都妹整明白。
如果用 A ~ ^ \hat{\tilde{\mathbf{A}}} A~^ 的话,我把三部分拆开(没管自环)做了一下矩阵乘法,迭代式就变成了(我没考虑有向边的情况,所以ij顺序可能是写反的): r j = ∑ i 1 d i ( ∑ j 1 d j ⋅ A j i ) ⋅ r i r_j=\sum_i\dfrac{1}{\sqrt{d_i}}(\sum_j\dfrac{1}{\sqrt{d_j}}\cdot A_{ji})\cdot r_i rj=idi 1(jdj 1Aji)ri
……虽然看上去还挺规整的,但这是个什么玩意啊?


(补一个来自学长的指导: A ~ ^ \hat{\tilde{\mathbf{A}}} A~^ 可视为 A r w \mathbf{A}_{rw} Arw 的一个变体)
X ′ = D ^ − 1 / 2 A ^ D ^ − 1 / 2 X Θ x i ′ = Θ ∑ j ∈ N ( v ) ∪ { i } e j , i d ^ j d ^ i x j (公式源自PyG的GCNConv文档) \mathbf{X}^{\prime} = \mathbf{\hat{D}}^{-1/2} \mathbf{\hat{A}} \mathbf{\hat{D}}^{-1/2} \mathbf{X} \mathbf{\Theta} \\ \mathbf{x}^{\prime}_i = \mathbf{\Theta} \sum_{j \in \mathcal{N}(v) \cup \{ i \}} \frac{e_{j,i}}{\sqrt{\hat{d}_j \hat{d}_i}} \mathbf{x}_j \\ \text{(公式源自PyG的GCNConv文档)} X=D^1/2A^D^1/2xi=ΘjN(v){i}d^jd^i ej,ixj(公式源自PyGGCNConv文档)
就,be like:在这里插入图片描述

顺带一提:
PageRank用的是 A D − 1 AD^{-1} AD1,所以上图是按发出信息方的度数算;如果用 D − 1 A D^{-1}A D1A就应该是按接收信息方的度数算了。
马尔科夫假设那块我还没搞懂,但是我看说 D − 1 A D^{-1}A D1A是row-stachastic matrix, A D − 1 AD^{-1} AD1是column-stochastic matrix(如果我没搞错的话),所以应该都能拿来作为转移矩阵,都能收敛?
然后 D − 1 2 A D − 1 2 D^{-\frac{1}{2}}AD^{-\frac{1}{2}} D21AD21是对称归一化,也能收敛。
大概就这样理解吧,我搞够了。

3.4 附录A:证明 Π ppr \Pi_{\text{ppr}} Πppr 存在

即证明 I n − ( 1 − α ) A ~ ^ \mathbf{I}_n-(1-\alpha)\hat{\tilde{\mathbf{A}}} In(1α)A~^ 存在逆矩阵。
即证明 det ⁡ ( I n − ( 1 − α ) A ~ ^ ) ≠ 0 \det\Big(\mathbf{I}_n-(1-\alpha)\hat{\tilde{\mathbf{A}}}\Big)\neq0 det(In(1α)A~^)=0
即证明 det ⁡ ( 1 1 − α I n − A ~ ^ ) ≠ 0 \det\Big(\dfrac{1}{1-\alpha}\mathbf{I}_n-\hat{\tilde{\mathbf{A}}}\Big)\neq0 det(1α1InA~^)=0
如果 1 1 − α \dfrac{1}{1-\alpha} 1α1 不是 A ~ ^ \hat{\tilde{\mathbf{A}}} A~^ 的特征值,上式就恒成立。
α < 1 \alpha<1 α<1 恒成立
1 1 − α > 1 \dfrac{1}{1-\alpha}>1 1α1>1 恒成立

证明一下 A ~ ^ \hat{\tilde{\mathbf{A}}} A~^ 和 row-stachastic matrix A r w \mathbf{A}_{rw} Arw 特征值相同:
在这里插入图片描述
因为 row-stachastic matrix 的最大特征值为1(根据Gershgorin circle theorem可证,我也不知道这个是啥),所以 1 1 − α > 1 \dfrac{1}{1-\alpha}>1 1α1>1 不可能是 A ~ ^ \hat{\tilde{\mathbf{A}}} A~^ 的特征值,所以原式可证。

3.5 附录B:证明APPNP收敛于PPNP

还没看,待补。

4. 实验结果

还没写,待补。

5. 代码实现和复现

5.1 论文官方实现

klicperajo/ppnp: PPNP & APPNP models from “Predict then Propagate: Graph Neural Networks meet Personalized PageRank” (ICLR 2019)
还没看,待补。

5.2 PyG官方实现

APPNP类,官方文档:torch_geometric.nn — pytorch_geometric 1.7.2 documentation

源代码:torch_geometric.nn.conv.appnp — pytorch_geometric 1.7.2 documentation
他这个用MessagePassing实现的基类我就没太看懂……就是,唉,当年GCN那个怎么从矩阵拆成向量形式的我就没搞懂,这个我就更没搞懂了!
我看这个实现逻辑里面用到了 gcn_norm() 这个函数,这个我查了一下是GCNConv类里面用到的函数。GCNConv源代码在这里:torch_geometric.nn.conv.gcn_conv — pytorch_geometric 1.7.2 documentation
然后呢我也没咋看懂这个的实现逻辑。就……意思应该是计算 A ~ ^ \hat{\tilde{\mathbf{A}}} A~^,但是,妈的,他到底是咋搞的啊!

我寻摸着,这个类的实现逻辑大概是:用 gcn_norm() 计算出 A ~ ^ \hat{\tilde{\mathbf{A}}} A~^,然后用MessagePassing基类的 propage() 方法来计算公式,叠个dropout,以上过程实现K次(顺序我也没搞懂,因为我没看懂)。

5.3 我自己写的复现

还没加dropout。
还没优化。

5.3.1 APPNP:dense Tensor

class APPNP_self1(torch.nn.Module):
    #参考PyG设置的参数什么的
    #就PyG设置的就是没有predict部分,所以我也把predict部分放在GNNStack里面了
    #就我想了一下,我觉得用MessagePassing类不方便,就还是用torch的Module类了
    
    def __init__(self,K,alpha):
        #别的参数暂时省略
        super(APPNP_self1,self).__init__()
        self.K=K
        self.alpha=alpha

    def forward(self, x, edge_index):
        #首先尝试使用dense_tensor,如果不行再转sparse_tensor
        (row, col)= edge_index
        node_num=max(row.max(),col.max())+1
        adj = torch.zeros((node_num,node_num))
        adj=adj.to(hp['device'])
        adj[row, col] = torch.ones(row.numel()).to(hp['device'])
        
        self_loop=torch.eye(adj.size()[0]).to(hp['device'])  #自环
        adj=adj+self_loop  #\slide{A}
        degree_vector=torch.sum(adj,dim=1).cpu()  #度矩阵
        degree_vector=1/np.sqrt(degree_vector)  #D-1/2
        degree_matrix=torch.diag(degree_vector).to(hp['device'])
        adj=torch.mm(degree_matrix,adj)
        adj=torch.mm(adj,degree_matrix)  #\hat{\slide{A}}
        
        H=x.clone()
        Z=x.clone()
        
        for k in range(self.K-1):
            Z=torch.mm(adj,Z)
            Z=Z*(1-self.alpha)
            Z=Z+self.alpha*H
        
        Z=torch.mm(adj,Z)
        Z=Z*(1-self.alpha)
        Z=Z+self.alpha*H
        Z=F.log_softmax(Z, dim=1)
        
        return Z

在CPU上跑得贼慢,在GPU上OOM了……

5.3.1 APPNP:稀疏矩阵

我用的是PyTorch的稀疏矩阵(torch.sparse),文档:torch.sparse — PyTorch 1.9.0 documentation
我参考了一下PyG和论文官方实现,PyG用的是torch_sparse,这个库他妈的没有文档就算了,GitHub项目里面代码连个注释都没有。大佬是真的牛逼,他怎么做到自己写的代码自己看得懂的?……
论文官方用的是scipy的稀疏矩阵,这个我还没有了解过。

def edge_index2sparse_tensor(edge_index,node_num):
    sizes=(node_num,node_num)
    v=torch.ones(edge_index[0].numel()).to(hp['device'])  #边数
    return torch.sparse_coo_tensor(edge_index, v, sizes)

class APPNP_self2(torch.nn.Module):    
    def __init__(self,K,alpha):
        #别的参数暂时省略
        super(APPNP_self2,self).__init__()
        self.K=K
        self.alpha=alpha

    def forward(self, x, edge_index):
        node_num=x.size()[0]
        edge_index, _ = pyg_utils.add_self_loops(edge_index,num_nodes=node_num)  #添加自环(\slide{A})
        adj=edge_index2sparse_tensor(edge_index,node_num)  #将\slide{A}转换为稀疏矩阵
        degree_vector=torch.sparse.sum(adj,0)  #度数向量
        degree_vector=degree_vector.to_dense().cpu()
        degree_vector=1/np.sqrt(degree_vector)
        degree_matrix=torch.diag(degree_vector).to(hp['device'])
        adj=torch.sparse.mm(adj.t(),degree_matrix.t())
        adj=adj.t()
        adj=torch.mm(adj,degree_matrix)
        adj=adj.to_sparse()
        
        H=x.clone()
        
        for k in range(self.K-1):
            x=torch.mm(adj,x)
            x=x*(1-self.alpha)
            x=x+self.alpha*H
        
        x=torch.mm(adj,x)
        x=x*(1-self.alpha)
        x=x+self.alpha*H
        x=F.log_softmax(x, dim=1)
        
        return x

5.3.3 PPNP

还没写,待补。

5.4 复现实验结果对比

APPNP和C&S复现
未完待续。

6. 参考资料

  1. 我参考了这两篇讲解同一论文的博文:
    1. APPNP_fnoi2014xtx的博客-CSDN博客
    2. APPNP:一个更强大的用于半监督分类的图卷积网络模型 - 知乎
  2. 关于拉普拉斯矩阵平滑这一概念(没看懂……不是,主要是没搞懂拉普拉斯平滑跟message passing的关系,拉普拉斯平滑本身感觉就是一种正则化方式了):
    1. 神奇的拉普拉斯平滑(Laplacian Smoothing)及其在正则化上的应用~_love模式识别-CSDN博客_拉普拉斯平滑
    2. 谈谈自己对正则化的一些理解~_love模式识别-CSDN博客_对正则化的理解
    3. 拉普拉斯平滑(Laplacian smoothing)_潜心学习的渣渣的博客-CSDN博客_拉普拉斯平滑
  3. JK 《Representation Learning on Graphs with Jumping Knowledge Networks》 的一些讲解博文。不过都没讲解在APPNP论文中强调的influence score问题,我简单浏览了一下原文,好像influence score和RW相关的问题还要见《Random Walks on Graphs》一文,我一看,妈耶,一篇40多页的综述……
    1. 读书笔记3:Representation Learning on Graphs with Jumping Knowledge Networks_b224618的博客-CSDN博客
    2. 论文分享 |Jumping Knowledge Networks_geek_wh2016的博客-CSDN博客
  4. BP 《The PageRank Citation Ranking: Bringing Order to the Web》
  5. Random Walks on Graphs: A Survey, Combinatorics, Paul Erdos is Eighty
    40多页的综述,搞我呢,以后有缘了再看吧。

  1. JK 《Representation Learning on Graphs with Jumping Knowledge Networks》 ↩︎

  2. 要说为什么我现在看到偏导就会想到弹性……那只能回忆起一个夏天,我一开始学微积分就被灌输了弹性概念,从此经济学的弹性永远与数学的导数与偏导概念如影相随,萦绕我心。
    第一印象害死人。 ↩︎

  3. BP 《The PageRank Citation Ranking: Bringing Order to the Web》 ↩︎

  • 7
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
本文首发于DF创客社区,作者:云天 原文链接:http://mc.dfrobot.com.cn/thread-296401-1-1.html 【设计背景】 当在公园、郊区等偏僻区域或黑夜无人情景,发生突发事件,手机等通讯设备被抢、丢失或未携带等,需报警求救。在这种孤立无援情况下,我们急需报警求救设施。 根据以上需求,相关部分可在以上这种环境下设置智能报警路灯。 【设计思路】 1、路灯配置智能终端(手机),利用人脸识别技术,采集人脸信息,后台记录(减少谎报),采集成功后,开启报警页面。 2、利用超声波检测到报警人,点亮路灯,并利用路灯发出求救信号,扩大求救范围。 【设计草】 设计草 【演示视频】 报警端演示 后台显示报警人 【材料准备】首先根据设计思路,准备好制作智能报警路灯所需的材料,清单和说明如下表和下所示。 【电路设计】 为了方便编写程序,先设计智能报警路灯的电路连接关系,电路原理如下所示。 【程序设计】# 程序流程设计 在写程序之前,先梳理一下思路,设计程序流程,如下所示。 ##硬件程序流程 ##APP程序流程 【ArduinoLeonardo硬件代码】#include #include double mind_n_bs; char mind_s_str; const byte LedArray_BBlG[] = {//"S"字模 B00111000, B01100100, B01100000, B00110000, B00011000, B00001100, B00100110, B00011100, }; const byte LedArray_pFgv[] = {//"O"字模 B00011000, B00100100, B01000010, B01000010, B01000010, B01000010, B00100100, B00011000}; const byte LedArray_42Se[] ={//“S”字模 B00111000, B01100100, B01100000, B00110000, B00011000, B00001100, B00100110, B00011100, }; const byte LedArray_PPNP[] = {B01100110,B11111111,B10011001,B10000001,B11000011,B01100110,B00111100,B00011000};//“心型”案 DFRobot_LedControl max7219(5, 3, 4);//LED点阵(MAX7219),初始化DIN引脚为5,CS管脚为4,CLK管脚为3 DFRobot_Ultrasonic ultraA0;//模拟超声波 void SOS(); void XianShi(); void SOS()//12引脚上接电磁继电器,控制灯的开关,发出“SOS”莫尔代码 { digitalWrite(12, HIGH); delay(500); digitalWrite(12, LOW); delay(100); digitalWrite(12, HIGH); delay(500); digitalWrite(12, LOW); delay(100); digitalWrite(12, HIGH); delay(500); digitalWrite(12, LOW); delay(100); digitalWrite(12, HIGH); delay(1500); digitalWrite(12, LOW); delay(100); digitalWrite(12, HIGH); delay(1500); digitalWrite(12, LOW); delay(100); digitalWrite(12, HIGH); delay(1500); digitalWrite(12, LOW); delay(100); digitalWrite(12, HIGH); delay(500); digitalWrite(12, LOW); delay(100); digitalWrite(12, HIGH); delay(500); digitalWrite(12, LOW); delay(100); digitalWrite(12, HIGH); delay(500); digitalWrite(12, LOW); delay(100); } void XianShi()//LED点阵显示内容 { max7219.show(LedArray_BBlG); delay(200)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

诸神缄默不语

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

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

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

打赏作者

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

抵扣说明:

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

余额充值