【图神经网络基础】理解GCN的对称归一化操作-图的拉普拉斯归一化

1 对称归一化的意义

  对图卷积网络的公式,已经非常熟悉了,并且对公式表示的意思也能理解即:实现图中节点之间的消息传递或者称做特征传递。但是在dgl框架的学习过程中,对于单向二部图的图卷积操作的使用过程中,需要深入的理解图邻接矩阵的对称归一化操作也即图的拉普拉斯正则。
H ( l + 1 ) = σ ( D ~ − 1 / 2 A ~ D ~ − 1 / 2 H l W l ) H^{(l+1)}=\sigma\left(\tilde{D}^{-1 / 2} \tilde{A} \tilde{D}^{-1 / 2} H^{l} W^{l}\right) H(l+1)=σ(D~1/2A~D~1/2HlWl)
其中 D ~ = D + I , A ~ = A + I \tilde{D}=D+I, \tilde{A}=A+I D~=D+I,A~=A+I
  通过查询各个博主的观点,图卷积的对称归一化主要有以下意义:

  1. 是为了信息传递的过程中保持特征矩阵 H H H的原有分布,防止一些度数高的顶点和度数低的顶点在特征分布上产生较大的差异[1]。
  2. 采用加法规则进行聚合时,度大的节点的特征会越来越大,度小的节点的特征会越来越小,所以需要归一化[2]。
  3. 归一化 D − 1 D^{-1} D1即可以实现采用 D − 1 / 2 A D − 1 / 2 D^{-1/2}AD^{-1/2} D1/2AD1/2是为了保证图的对称性并且特征归一化有利于神经网络的学习[3]。关于为什么归一化或者标准化对神经网络学习的影响可以见[5][6]。

2 例子解释

(图来自参考文献[7])
在这里插入图片描述
A = { 0 1 0 0 1 0 1 0 1 0 1 0 0 1 0 1 0 0 0 0 1 0 1 1 1 1 0 1 0 0 0 0 0 1 0 0 } , D = { 2 0 0 0 0 0 0 3 0 0 0 0 0 0 2 0 0 0 0 0 0 3 0 0 0 0 0 0 3 0 0 0 0 0 0 1 } A=\left\{\begin{array}{llllll} 0 & 1 & 0 & 0 & 1 & 0 \\ 1 & 0 & 1 & 0 & 1 & 0 \\ 0 & 1 & 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 & 1 & 1 \\ 1 & 1 & 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 & 0 & 0 \end{array}\right\}, D=\left\{\begin{array}{llllll} 2 & 0 & 0 & 0 & 0 & 0 \\ 0 & 3 & 0 & 0 & 0 & 0 \\ 0 & 0 & 2 & 0 & 0 & 0 \\ 0 & 0 & 0 & 3 & 0 & 0 \\ 0 & 0 & 0 & 0 & 3 & 0 \\ 0 & 0 & 0 & 0 & 0 & 1 \end{array}\right\} A= 010010101010010100001011110100000100 ,D= 200000030000002000000300000030000001
A ~ = A + I N = { 1 1 0 0 1 0 1 1 1 0 1 0 0 1 1 1 0 0 0 0 1 1 1 1 1 1 0 1 1 0 0 0 0 1 0 1 } , D ~ = ∑ j A ~ i j = D + I N = { 3 0 0 0 0 0 0 4 0 0 0 0 0 0 3 0 0 0 0 0 0 4 0 0 0 0 0 0 4 0 0 0 0 0 0 2 } \tilde{A}=A+I_{N}=\left\{\begin{array}{llllll} 1 & 1 & 0 & 0 & 1 & 0 \\ 1 & 1 & 1 & 0 & 1 & 0 \\ 0 & 1 & 1 & 1 & 0 & 0 \\ 0 & 0 & 1 & 1 & 1 & 1 \\ 1 & 1 & 0 & 1 & 1 & 0 \\ 0 & 0 & 0 & 1 & 0 & 1 \end{array}\right\}, \tilde{D}=\sum_{j} \tilde{A}_{i j}=D+I_{N}=\left\{\begin{array}{cccccc} 3 & 0 & 0 & 0 & 0 & 0 \\ 0 & 4 & 0 & 0 & 0 & 0 \\ 0 & 0 & 3 & 0 & 0 & 0 \\ 0 & 0 & 0 & 4 & 0 & 0 \\ 0 & 0 & 0 & 0 & 4 & 0 \\ 0 & 0 & 0 & 0 & 0 & 2 \end{array}\right\} A~=A+IN= 110010111010011100001111110110000101 ,D~=jA~ij=D+IN= 300000040000003000000400000040000002

3 代码

import numpy as np

A = np.array([[0, 1, 0, 0, 1, 0],
              [1, 0, 1, 0, 1, 0],
              [0, 1, 0, 1, 0, 0],
              [0, 0, 1, 0, 1, 1],
              [1, 1, 0, 1, 0, 0],
              [0, 0, 0, 1, 0, 0]])

A_ = A + np.eye(A.shape[0])
print(A_)

print(A_.sum(axis=1))
# print(A_.sum(axis=0))
# D = np.diag(1/np.sqrt(A_.sum(axis=1)))
# print("D", D)
# print(A_ / np.sqrt(A_.sum(axis=1)))
C = A_ / A_.sum(axis=1)
print("---")
print("C", C)
print(C.T / np.sqrt(A_.sum(axis=0)))

# R = D @ A_ @ D
# print(R)

从文献【4】的角度,对称归一化可以从行的标准化合列的标准化两个方面理解。
(1)首先是横向标准化,这一步的意义从深度学习的角度来说是很容易理解的,因为graph中,不同节点之间的edge的weight差异可能很大,比如节点0和其他节点的edge的weights范围在0~1之间,而节点1和其他节点的weights范围在100~1000之间,对于金融中通过user之间的交易关系来构建的图尤其如此,交易的金额作为weights则不同用户之间的交易金额(即edge)权重差异可能非常大。这对于nn的训练来说问题比较大,比如GCN处理有权图问题,不对邻接矩阵进行横向标准化,则sum之后,不同节点的领域的sum结果量纲差异可能会很大,比如节点A和领域的edge weights范围在0~1,sum的结果可能也就是10以内,节点B和领域的edge weights范围在1000~10000,sum的结果就非常大了,这样gnn中做节点非线性变换的dense层会很头疼,难收敛啊。
  那么显然,我们做个横向标准化就可以解决这样的问题了,因为对于GNN来说,我们无非是想学习到所有节点和领域的某种隐藏的关联模式,而对于不同用户来说,edge weights的绝对大小不重要,相对大小才重要。这和时间序列预测中的多序列预测问题是一样的,不同商品的销量的绝对值差异很大,但是我们要学习到的是相对的模式而不是绝对的模式,因此在多序列的时间序列预测问题中也常常会做横向标准化,即将所有商品的销量放缩到大致相同的区间。
(2)列的标准化,这里也非常有意思,我们做纵向标准化实际上是希望将节点的领节点对其的“贡献”进行标准化。比如说脉脉上的用户之间的关注关系就是天然的同构图,假设我们要做节点分类判定某个用户A是不是算法工程师,并且假设A用户仅仅和另一个算法工程师B以及10个猎头有关注的关系,直观上,猎头对用户A的节点类别的判定的贡献应该是很小的,因为猎头往往会和算法,开发,测试,产品等不同类型的用户有关联关系,他们对于用户A的“忠诚关联度”是很低的,而对于算法工程师B而言,假设他仅仅和A有关联, 那么明显,B对A的“忠诚关联度”是很高的,B的node features以及B和A的关联关系在对A进行节点分类的时候应该是更重要的。
  那么,纵向标准化就较好的考虑到了上面的问题,思想很简单,假设节点1和节点2有一个权重为1的edge相连,节点2和其他1000个节点也有关联,那么节点2对于节点1的贡献度为1/1000,即用edge weights除以节点2的度(有权图上用加权度)。
  而对称归一化拉普拉斯矩阵,实际上是横纵向标准化之后又开了根号,开根号不影响计算结果的相对大小,不改变实际的物理意义。
  因此,对称归一化拉普拉斯矩阵可以看作是对原始的邻接矩阵的一种横纵向标准化。(注:上述的计算是包括了自环的,不影响理解)
但是按照文献【4】给出的计算的例子从矩阵计算的角度,还是不理解行列的标准化,有理解的朋友评论区留言。

4 从信息聚合的角度理解GCN的归一化

  采用加法规则时,对于度大的节点特征越来越大,而对于度小的节点却相反,这可能导致网络训练过程中梯度爆炸或者消失的问题。(PageRank的迭代优化过程)。在不考虑对称归一化时, D − 1 A ^ \hat{D^{-1}A} D1A^是最简单的归一化方式。但是这样得到的矩阵是非对称阵, 所以出现了如下的对称归一化的形式。
L ^ s y m = D ^ − 1 / 2 A ^ D ^ − 1 / 2 A ^ = A + I D ^ = D + I \begin{array}{l} \hat{L}_{s y m}=\hat{D}^{-1 / 2} \hat{A} \hat{D}^{-1 / 2} \\ \hat{A}=A+I \\ \hat{D}=D+I \end{array} L^sym=D^1/2A^D^1/2A^=A+ID^=D+I
我们先不考虑,对称归一化,先看一下在传统归一化下,矩阵乘法到底做了什么。
( D ~ − 1 A ~ H ) i = ( D ~ − 1 A ~ ) i H = ( ∑ k D ~ i k − 1 A ~ i ) H = ( D ~ i i − 1 A ~ i ) H = D ~ i i − 1 ∑ j A ~ i j H j = ∑ j 1 D ~ i i A ~ i j H j \begin{aligned} \left(\tilde{D}^{-1} \tilde{A} H\right)_{i} &=\left(\tilde{D}^{-1} \tilde{A}\right)_{i} H \\ &=\left(\sum_{k} \tilde{D}_{i k}^{-1} \tilde{A}_{i}\right) H \\ &=\left(\tilde{D}_{i i}^{-1} \tilde{A}_{i}\right) H \\ &=\tilde{D}_{i i}^{-1} \sum_{j} \tilde{A}_{i j} H_{j} \\ &=\sum_{j} \frac{1}{\tilde{D}_{i i}} \tilde{A}_{i j} H_{j} \end{aligned} (D~1A~H)i=(D~1A~)iH=(kD~ik1A~i)H=(D~ii1A~i)H=D~ii1jA~ijHj=jD~ii1A~ijHj
上式中, i i i是行 k k k是列,由于 D D D是对角矩阵只有对角线才有值所以直接取 i i i这种聚合方式实际上就是在对邻居求和取平均。从近似归一化的角度理解 D ^ − 1 / 2 A ^ D ^ − 1 / 2 \hat{D}^{-1 / 2} \hat{A} \hat{D}^{-1 / 2} D^1/2A^D^1/2,这种归一化方式,将不再单单地对领域节特征点取平均,它不仅考虑了节点i对度,也考虑了邻接节点j的度,当邻居节点j度数较大时,它在聚合时贡献地会更少。这也比较好理解,存在B->A<-C<-[D,E,F] 这么一个图,当使用这种归一化矩阵,在对A这个节点的特征进行更新时,B占的权重会更大,C占的权重会更小。因为B对A产生影响,与A对B产生对影响是一样的(无向图),由于B只有A这个邻居,所以A对B影响很大;同样地,C对A产生影响,与A对C产生对影响是一样的,因为C有很多节点,所以A对C节点对影响没那么大,即C对A节点对影响没那么大。【参考文献8
( D ~ − 0.5 A ~ D ~ − 0.5 H ) i = ( D ~ − 0.5 A ~ ) i D ~ − 0.5 H = ( ∑ k D ~ i k − 0.5 A ~ i ) D ~ − 0.5 H = D ~ i i − 0.5 ∑ j A ~ i j ∑ k D ~ j k − 0.5 H j = D ~ i i − 0.5 ∑ j A ~ i j D ~ j j − 0.5 H j = ∑ j 1 D ~ i i D ~ j j A ~ i j H j \begin{aligned} \left(\tilde{D}^{-0.5} \tilde{A} \tilde{D}^{-0.5} H\right)_{i} &=\left(\tilde{D}^{-0.5} \tilde{A}\right)_{i} \tilde{D}^{-0.5} H \\ &=\left(\sum_{k} \tilde{D}_{i k}^{-0.5} \tilde{A}_{i}\right) \tilde{D}^{-0.5} H \\ &=\tilde{D}_{i i}^{-0.5} \sum_{j} \tilde{A}_{i j} \sum_{k} \tilde{D}_{j k}^{-0.5} H_{j} \\ &=\tilde{D}_{i i}^{-0.5} \sum_{j} \tilde{A}_{i j} \tilde{D}_{j j}^{-0.5} H_{j} \\ &=\sum_{j} \frac{1}{\sqrt{\tilde{D}_{i i} \tilde{D}_{j j}}} \tilde{A}_{i j} H_{j} \end{aligned} (D~0.5A~D~0.5H)i=(D~0.5A~)iD~0.5H=(kD~ik0.5A~i)D~0.5H=D~ii0.5jA~ijkD~jk0.5Hj=D~ii0.5jA~ijD~jj0.5Hj=jD~iiD~jj 1A~ijHj

5 矩阵计算角度(更好理解)

   来自参考文献【9】
  任何一个图卷积层都可以写成一个非线性函数:
H l + 1 = f ( H l , A ) H^{l+1}=f\left(H^{l}, A\right) Hl+1=f(Hl,A)
H 0 = X H^{0}=X H0=X 为第一层的输入, X ∈ R N × D X\in R^{N\times D} XRN×D N N N为图中的节点个数, D D D为每个节点特征向量的维度, A A A为邻接矩阵。不同模型的差异点在于函数 f f f的实现不同。下面是几种图卷积的实现形式,但是每一种实现都统称拉普拉斯矩阵。

5.1 图卷积实现一

5.2 图卷积实现二

5.3 图卷积实现三

6 参考文献

[1]【Graph Neural Network】GCN: 算法原理,实现和应用
[2]GCN实现及其中的归一化
[3]关于GCN对称归一化的手动推导
[4]对称归一化拉普拉斯矩阵的意义
[5]神经网络为什么要归一化
[6]神经网络输入数据预处理——数据标准化(归一化)——python
[7]最全面的图卷积网络GCN的理解和详细推导,都在这里了!
[8]GCN中的拉普拉斯矩阵如何归一化?
[9]一文读懂图卷积GCN

  • 15
    点赞
  • 71
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对称归一化是一种常用的邻接矩阵归一化方法,它可以用于卷积网络(GCN)等神经网络模型中。下面是对称归一化的解释、代码和实现方法: 1. 对称归一化的意义: 对称归一化的目的是将邻接矩阵中的每个元素除以其所在行和列的度数之和的平方根。这样做的好处是可以保持特征向量的单位长度,避免在卷积操作中引入不必要的缩放。 2. 代码实现: 假设邻接矩阵为A,对称归一化后的邻接矩阵为D^(-1/2) * A * D^(-1/2),其中D是对角矩阵,其对角线元素为每个节点的度数。 ```python import numpy as np def symmetric_normalize_adjacency(adjacency_matrix): # 计算每个节点的度数 degrees = np.sum(adjacency_matrix, axis=1) # 计算度数的平方根的倒数 degrees_sqrt_inv = np.power(degrees, -0.5) degrees_sqrt_inv[np.isinf(degrees_sqrt_inv)] = 0.0 # 构建对角矩阵 D_sqrt_inv = np.diag(degrees_sqrt_inv) # 对称归一化邻接矩阵 normalized_adjacency_matrix = np.dot(np.dot(D_sqrt_inv, adjacency_matrix), D_sqrt_inv) return normalized_adjacency_matrix ``` 3. 从信息聚合的角度理解GCN归一化对称归一化可以理解为在信息聚合过程中,将每个节点的特征向量与其邻居节点的特征向量进行加权平均,权重由归一化后的邻接矩阵决定。这样可以保持特征向量的单位长度,并且更好地保留了节点之间的关系。 4. 矩阵计算角度(更好理解): 对称归一化可以通过以下三种方式实现: - 卷积实现一: ```python normalized_adjacency_matrix = np.dot(np.dot(D_sqrt_inv, adjacency_matrix), D_sqrt_inv) ``` - 卷积实现二: ```python normalized_adjacency_matrix = np.dot(np.dot(D_sqrt_inv, adjacency_matrix), D_sqrt_inv.T) ``` - 卷积实现三: ```python normalized_adjacency_matrix = np.dot(np.dot(D_sqrt_inv.T, adjacency_matrix), D_sqrt_inv) ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值