图谱卷积之ChebNet推导_易懂

        目前流行的是以切比雪夫多项式为核的图卷积公式,所以我们来推导一下如何从图卷积的原理到具体的网络中进行实现。(流程中免不了有错漏之处,请大家辩证地看待)

        首先,我们要知道执行这些操作为了达到的目的:非欧空间的数据无法像欧式空间那样直接执行卷积等操作,于是我们考虑将非欧空间的数据投影到一个便于进行类似卷积操作的谱空间,对投影后的数据进行卷积,再将卷积得到的结果还原为原来的空间即可。

        其次,我们需要对上面的目的进行理解,将图转换到谱域,有点类似于将时域信号转换到频域。而将时域转换到频域会使用傅里叶变换,使用的基底是三角函数。对应到图中,他的傅里叶变换是拉普拉斯矩阵L特征向量组成的基底。为什么在这里使用拉普拉斯矩阵L呢?因为在图结构中,我们常用拉普拉斯矩阵来对图的性质进行描述。(如果在数学概念上有点不理解,可以先承认这个设定往后看,然后再去补充相关的知识)我们使用U表示拉普拉斯矩阵特征向量也就是基底,那么将图信号X投影到谱域空间的得到的谱域表达\widehat{X}表达式就会是:

\widehat{X}=U^{T}X (1)

         同样的,将谱域得到的表达\widehat{X}再转回原先的图域,也就是逆变换,就可以被表达为:

\overline{X}=U\widehat{X} (2)

        现在我们来定义这里的图卷积,我们取g为卷积核x为输入,那么卷积核对输入进行卷积的表达式可以被写为:

g*x=傅里叶逆变换(傅里叶变换(g*x))(3)

        那么对于这里的傅里叶变换(g*x),有一个这样的定理:两个信号的卷积的傅里叶变换是他们的傅里叶变换的点积,为什么不直接计算g*x呢?还是因为“非欧空间的数据无法像欧式空间那样直接执行卷积”。结合我们刚说的,使用U作为基底,上面的式子可以被表示为:

g*x=U((U^{T}g)*(U^{T}x)) (4)

        这里U^{T}就是U的逆,(如果在数学概念上有点不理解,可以先承认这个设定往后看,然后再去补充相关的知识)。因为U是拉普拉斯矩阵的特征向量组成的矩阵,也就是说U和拉普拉斯矩阵L之间的关系为:

L=U\Lambda U^{T} (5)

        所以有:

U^{T}L=\Lambda U^{T} (6)

        也就是说,如果我们对卷积核g使用U^{T}进行图域到谱域的转换,这里g是一个可以学习的参数,这里的UT是拉普拉斯矩阵的特征向量,那么得到的结果会得到关于拉普拉斯特征向量的多项式。因为g可以看成是常数,就是常数核特征向量的线性组合。而特征向量与特征值\Lambda有关,所以我们可以进一步将U^{T}g写为:

U^{T}g = g_{\theta }(\Lambda ) (7)

        这里\theta表示参数。

        那么现在回到公式(4),对于公式(4)中对输入X进行谱域变换的部分我们可以先不看,留着后面有用。我们是不是可以直接把(7)带回呢?当然可以,但是在实际计算中,根据输入的拉普拉斯矩阵L求其特征值是一项复杂而庞大的工程。那么(7)表示的这个多项式可以怎么进行表示呢?切比雪夫多项式就提供了一个很好的多项式逼近方法。从而公式(7)可以被切比雪夫多项式表示为:

g_{\theta }(\Lambda )=\sum_{k=0}^{K}\theta _{k}\cdot T_{k}(\widetilde{\Lambda }) (8)

        这里T_{k}是切比雪夫多项式中一项的表达方式,\widetilde{\Lambda }是归一化之后的特征值,要进行归一化是为了符合切比雪夫多项式自变量范围的要求[-1,1]。(归一化并不会影响结果,因为我们把这个视为向量的组合,归一化并不改变向量的方向,至于向量大小的缩短完全可以通过参数\theta _{k}来弥补。个人理解,可能不对。)

        好了,现在我们得到了简便好算的卷积核的谱域表达式(8),我们将其代回(4),并且接下来(4)中对输入X进行谱域变换的部分也会被用上了。

        g*x=U((U^{T}g)*(U^{T}x))\\=U(g_{\theta }(\Lambda )*(U^{T}x))\\=U(\sum_{k=0}^{K}\theta _{k}\cdot T_{k}(\widetilde{\Lambda })*U^{T}x)\\=\sum_{k=0}^{K}\theta _{k}\cdot T_{k}(U\widetilde{\Lambda }U^{T})x (9)

        第一个等号是将(7)代回(4),第二个等号是(8)。由公式(5)我们可以知道:

\widetilde{L}=U^{T}\widetilde{\Lambda } U (10)

        所以我们将(9)写为:

g*x=\sum_{k=0}^{K}\theta _{k}\cdot T_{k}(\widetilde{L })x (11)

        为了简化计算并将其应用到图卷积网络中,取切比雪夫多项式的K为1,这样上面的式子可以被写为:

g*x=\theta _{0}x+\theta _{1}\widetilde{L }x  (12)

        意味着图卷积可以分解为两部分:一部分是节点自身的特征乘以一个权重\theta _{0}x,另一部分是节点特征的邻域聚合乘以另一个权重\theta _{1}\widetilde{L }x。但是我们一般不使用两个权重,我们希望可以使用一个权重W,因此我们使用归一化的邻接矩阵加上自连接的形式来代替直接处理归一化的图拉普拉斯矩阵\widetilde{L },也即:

\widetilde{L }=\widetilde{D}^{-\frac{1}{2}}\widetilde{A }\widetilde{D}^{-\frac{1}{2}}  (13)

        其中,\widetilde{A }=A+I,A表示邻接矩阵,I表示单位阵用来实现自连接。\widetilde{D}是对应于\widetilde{A }的度矩阵。如果我们将权重W\widetilde{L }重新对(12)进行表达,那么卷积会被表述为:

g*x=W\widetilde{D}^{-\frac{1}{2}}\widetilde{A }\widetilde{D}^{-\frac{1}{2}}x (14)

        应用到图卷积网络中时,我们再对其添加一个激活函数\sigma,就可以得到第l层的输出被表示为:

H^{l}=\sigma (W^{l-1}\widetilde{D}^{-\frac{1}{2}}\widetilde{A }\widetilde{D}^{-\frac{1}{2}}H^{l-1})

        在第1层时,输入X就是H。在GCN网络的搭建中,一般提供特征矩阵X和邻接矩阵A就足够了。

        到这里就推导结束了^-^

参考链接:

谱卷积的GNN原理解释(Spectral Network),附代码-CSDN博客
图卷积神经网络系列:4. | 图谱卷积之ChebNet/PyTorch实现 - 知乎 (zhihu.com)
GCN:基于切比雪夫多项式(chebyshev ploynomials)为核的图卷积推导与pytorch实现_切比雪夫图卷积-CSDN博客
傅里叶变换(Fourier Transform)——附详细推导傅里叶变换和傅里叶级数关系和区别 - 知乎 (zhihu.com)
傅里叶变换公式推导 - 知乎 (zhihu.com)

  • 20
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在Pytorch中实现基于GCN/GAT/Chebnet的交通流预测,可以参考以下步骤: 1. 数据预处理:读入交通流数据,构建交通网络,将节点和边转换为矩阵表示。 2. 模型定义:定义GCN/GAT/Chebnet神经网络模型,包括输入层、隐藏层、输出层等。 3. 模型训练:使用交通流数据进行模型训练,通过计算损失函数来优化模型参数。 4. 模型测试:使用测试集数据进行模型测试,预测交通流情况,计算预测值与实际值之间的误差。 下面是一个基于GCN的交通流预测模型的Pytorch代码示例: ```python import torch import torch.nn as nn import torch.nn.functional as F class GCN(nn.Module): def __init__(self, input_dim, hidden_dim, output_dim): super(GCN, self).__init__() self.linear1 = nn.Linear(input_dim, hidden_dim) self.linear2 = nn.Linear(hidden_dim, output_dim) def forward(self, x, adj): x = F.relu(self.linear1(torch.matmul(adj, x))) x = self.linear2(torch.matmul(adj, x)) return x ``` 该模型包括两个线性层,其中第一个线性层将输入节点特征乘以邻接矩阵,然后通过ReLU激活函数得到隐藏层的输出,第二个线性层将隐藏层的输出再次乘以邻接矩阵得到最终的输出。 在训练过程中,需要定义损失函数和优化器,如下所示: ```python criterion = nn.MSELoss() optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate) ``` 然后,使用交通流数据进行模型训练,如下所示: ```python for epoch in range(num_epochs): outputs = model(features, adj) loss = criterion(outputs, labels) optimizer.zero_grad() loss.backward() optimizer.step() print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, num_epochs, loss.item())) ``` 在模型测试阶段,可以直接使用模型进行预测,如下所示: ```python with torch.no_grad(): test_outputs = model(test_features, adj) test_loss = criterion(test_outputs, test_labels) print('Test Loss: {:.4f}'.format(test_loss.item())) ``` 以上是基于GCN的交通流预测模型的Pytorch代码示例,类似的代码可以用于实现基于GAT/Chebnet的交通流预测模型。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值