GCN网路详解

GCN原理

1 邻接矩阵: A是图的邻接矩阵

2 特征矩阵 设 A 是n阶方阵,如果存在数m和非零n维列向量x,使得 Ax=mx 成立,则称 m 是矩阵A的一个特征值(characteristic value)或本征值(eigenvalue)。
3 度矩阵 D 是顶点的度矩阵(对角矩阵),对角线上元素依次为各个顶点的度,

4 拉普拉斯矩阵

对于图[G=(V,E)其Laplacian 矩阵的定义为L=D-A 其中L是Laplacian矩阵,D是顶点的度矩阵(对角矩阵),对角线上元素依次为各个顶点的度,A是图的邻接矩阵。看图5的示例,就能很快知道Laplacian 矩阵的计算方法。

img

图5 Laplacian 矩阵的计算方法
在这里插入图片描述

为什么GCN要用拉普拉斯矩阵?

拉普拉斯矩阵矩阵有很多良好的性质,这里写三点我感触到的和GCN有关之处

  • 拉普拉斯矩阵是对称矩阵,可以进行特征分解(谱分解),这就和GCN的spectral domain对应上了
  • 拉普拉斯矩阵只在中心顶点和一阶相连(就是直接相连)的顶点上(1-hop neighbor)有非0元素,其余之处均为0
  • 通过拉普拉斯算子与拉普拉斯矩阵进行类比(详见第6节)

superbrother 拉普拉斯矩阵与拉普拉斯算子的关系

GCN的核心基于拉普拉斯矩阵的谱分解。

矩阵的谱分解,特征分解,对角化都是同一个概念
不是所有的矩阵都可以特征分解,其充要条件为n阶方阵存在n个线性无关的特征向量]

但是拉普拉斯矩阵都是半正定对称矩阵(半正定矩阵本身就是对称矩阵,此处这样写为了和下面的性质对应,避免混淆),有如下三个性质:

  • 对称矩阵一定有n个线性无关的特征向量
  • 半正定矩阵的特征值一定非负
  • 对称矩阵的特征向量相互正交,即所有特征向量构成的矩阵为正交矩阵

在这里插入图片描述

5.图卷积神经网络网络 GCN
图卷积神经网络网络 Graph Convolutional Network (GCN) 最早是在 2016 年提
出,2017 年发表在 ICLR 上。GCN 主要是将卷积操作应用到图结构上,如下图所示,
GCN 输入的 chanel 为 C (即节点 Xi 特征向量的维度),GCN 输出的 chanel 为 F,
即每个节点 (Zi) 的特征向量维度为 F,最后用节点的特征对节点进行分类预测等:
在这里插入图片描述
GCN 卷积示意图

GCN 和 CNN 类似,具有强大的特征学习能力,它们的实质也是类似的,某个点的卷
积可以看成对该点邻居的加权求和。下图为传统的图像 (image) 卷积操作,每个点表
示一个像素,图像的像素也可以看成是一种图 (graph) 结构,相邻的像素之间有边连
接,而卷积是对像素邻居进行加权平均得到的。
在这里插入图片描述

图像 (image) 的二维卷积
而对于图 (graph) 结构,也可以采取类似的方法进行卷积。例如对下图中红色的节点
卷积就等于取其邻居节点进行加权平均。
在这里插入图片描述图 (graph) 结构卷积

GCN 中给出了图卷积的计算公式,如下所示,其中 H(l) 表示节点在第 l 层的特征向
量,H(l+1) 表示经过卷积后节点在第 l+1 层的特征向量,W(l) 表示第 l 层卷积的参
数,σ 表示激活函数。而由矩阵 A、D 组成的部分是一种拉普拉斯矩阵 (Laplacian
matrix),A+I 中的 I 为单位矩阵,即对角线为 1,其他为 0 的矩阵:
在这里插入图片描述

GCN 卷积公式

GCN卷积公式的理解:

对图像 (image) 中某一个像素进行卷积实际上是对该像素及相邻像素进行加权求和,
那么在图 (graph) 结构中对某一个节点卷积就应该是对该节点和其邻居节点进行加权
求和。
我们首先考虑最简单的图卷积操作,如下公式:
在这里插入图片描述

简单的图卷积公式
上面的公式中 W 为卷积变换的参数,可以训练优化。A 矩阵为邻接矩阵,Aij 不为 0 则
表示节点 i,j 为邻居。H 为所有节点的特征向量矩阵,每一行是一个节点的特征向量,
H(0) 就是 X 矩阵。A 和 H 的乘积其实就是把所有的邻居节点向量进行相加,如下所
示。
在这里插入图片描述

矩阵 A 和 H 相乘

上式的邻接矩阵中,节点 1 和节点 2、3 为邻居,则 A 乘上 H 后节点 1 的特征向量
就用节点 2、3 特征向量加和得到,即 [2,2,2,2,2]+[3,3,3,3,3]=[5,5,5,5,5]。得到 AH 之
后再和 W 相乘,最后经过激活函数 σ 就得到下一层节点的特征向量了。
但是上面的公式存在一些问题,AH 只获得了某个节点的邻居信息,而忽略了节点本身
信息。为了解决这个问题,我们可以将矩阵 A 中对角线的值设为 1,即每个节点会指
向自身,新的卷积公式如下:
在这里插入图片描述

I 为单位矩阵,即对角线为 1,其余为 0。使用上面的卷积公式即可把节点自身的信息
也考虑进去,但是这个公式仍然存在问题:矩阵 A 没有归一化,AH 会把节点所有邻
居的向量都相加,这样经过多层卷积后向量的值会很大。
因此需要对矩阵 A 进行归一化,归一化要用到图的度矩阵 D,可以直接使用矩阵 D 的
逆和 A 相乘,如下:
在这里插入图片描述

邻接矩阵归一化
但是上面的归一化公式得到的 A 不是对称矩阵,通常使用对称归一化的方法:
邻接矩阵对称归一化
把上面的优化方法结合在一起,就是 GCN 的卷积公式了:
在这里插入图片描述

6.GCN 预测
GCN 可以用最后一层卷积层得到的节点特征向量进行预测,假设 GCN 只有两层,则
预测的公式如下:
在这里插入图片描述
分类的损失函数如下:
在这里插入图片描述

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
GCN(Graph Convolutional Networks,图卷积网络)是一种用于图像分类、节点分类等图像处理任务的深度学习模型。下面我将介绍如何使用PyTorch实现GCN。 首先,我们需要安装PyTorch和其它必要的库。可以使用以下命令安装: ``` pip install torch torchvision pip install numpy scipy scikit-learn ``` 接下来,我们需要定义一个GCN模型。以下是一个简单的实现: ```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.fc1 = nn.Linear(input_dim, hidden_dim) self.fc2 = nn.Linear(hidden_dim, output_dim) def forward(self, x, adj): x = F.relu(self.fc1(torch.mm(adj, x))) x = self.fc2(torch.mm(adj, x)) return F.log_softmax(x, dim=1) ``` 在上面的代码中,我们定义了一个三层的GCN模型。`input_dim`是输入特征的维度,`hidden_dim`是隐藏层的维度,`output_dim`是输出层的维度。`nn.Linear`是一个线性层,`F.relu`是一个激活函数,`F.log_softmax`是一个softmax函数。 接下来,我们需要定义一个训练函数。以下是一个简单的实现: ```python def train(model, optimizer, criterion, features, adj, labels, idx_train): model.train() optimizer.zero_grad() output = model(features, adj) loss = criterion(output[idx_train], labels[idx_train]) loss.backward() optimizer.step() return model, optimizer, loss.item() ``` 在上面的代码中,我们定义了一个训练函数。`features`是输入特征,`adj`是邻接矩阵,`labels`是标签,`idx_train`是训练样本的索引。我们使用`model.train()`将模型切换到训练模式,然后使用`optimizer.zero_grad()`将梯度清零,使用`model(features, adj)`计算输出,使用`criterion(output[idx_train], labels[idx_train])`计算损失,使用`loss.backward()`计算梯度,使用`optimizer.step()`更新参数。 接下来,我们需要定义一个测试函数。以下是一个简单的实现: ```python def test(model, features, adj, labels, idx_test): model.eval() output = model(features, adj) _, preds = torch.max(output, dim=1) correct = torch.sum(preds[idx_test] == labels[idx_test]) acc = correct.item() / len(idx_test) return acc ``` 在上面的代码中,我们定义了一个测试函数。`features`是输入特征,`adj`是邻接矩阵,`labels`是标签,`idx_test`是测试样本的索引。我们使用`model.eval()`将模型切换到测试模式,然后使用`model(features, adj)`计算输出,使用`torch.max`计算最大值,使用`torch.sum`计算正确的预测数量,使用`acc = correct.item() / len(idx_test)`计算准确率。 以下是一个完整的GCN模型的实现: ```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.fc1 = nn.Linear(input_dim, hidden_dim) self.fc2 = nn.Linear(hidden_dim, output_dim) def forward(self, x, adj): x = F.relu(self.fc1(torch.mm(adj, x))) x = self.fc2(torch.mm(adj, x)) return F.log_softmax(x, dim=1) def train(model, optimizer, criterion, features, adj, labels, idx_train): model.train() optimizer.zero_grad() output = model(features, adj) loss = criterion(output[idx_train], labels[idx_train]) loss.backward() optimizer.step() return model, optimizer, loss.item() def test(model, features, adj, labels, idx_test): model.eval() output = model(features, adj) _, preds = torch.max(output, dim=1) correct = torch.sum(preds[idx_test] == labels[idx_test]) acc = correct.item() / len(idx_test) return acc ``` 接下来,我们需要加载数据。以下是一个简单的实现: ```python import numpy as np def load_data(): adj = np.array([[0, 1, 1, 0], [1, 0, 1, 0], [1, 1, 0, 1], [0, 0, 1, 0]]) features = np.array([[0, 1, 0], [1, 0, 0], [0, 0, 1], [1, 0, 0]]) labels = np.array([0, 1, 2, 0]) idx_train = np.array([0, 1, 2]) idx_test = np.array([3]) return adj, features, labels, idx_train, idx_test ``` 在上面的代码中,我们定义了一个简单的图。`adj`是邻接矩阵,`features`是输入特征,`labels`是标签,`idx_train`是训练样本的索引,`idx_test`是测试样本的索引。 接下来,我们需要训练模型。以下是一个简单的实现: ```python import torch.optim as optim adj, features, labels, idx_train, idx_test = load_data() model = GCN(input_dim=features.shape[1], hidden_dim=16, output_dim=labels.max()+1) optimizer = optim.Adam(model.parameters(), lr=0.01) criterion = nn.CrossEntropyLoss() for epoch in range(100): model, optimizer, loss = train(model, optimizer, criterion, features, adj, labels, idx_train) acc = test(model, features, adj, labels, idx_test) print('Epoch: {:03d}, Loss: {:.4f}, Acc: {:.4f}'.format(epoch, loss, acc)) ``` 在上面的代码中,我们定义了一个优化器和一个损失函数。然后,我们使用一个循环来训练模型,并使用`test`函数测试模型。我们使用`print`函数打印训练和测试的损失和准确率。 以上就是使用PyTorch实现GCN的一些基本步骤。当然,这只是一个简单的实现,实际中还有很多需要改进的地方。希望能对你有所帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

perfect Yang

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

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

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

打赏作者

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

抵扣说明:

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

余额充值