【Code】关于 GCN,我有三种写法

本篇文章主要基于 DGL 框架用三种不同的方式来实现图卷积神经网络。

1. DGL

DGL(Deep Graph Library)框架是由纽约大学和 AWS 工程师共同开发的开源框架,旨在为大家提供一个在图上进行深度学习的工具,帮助大家更高效的实现算法。

用现有的一些框架比如 TensorFlow、Pytorch、MXNet 等实现图神经网络模型都不太方便,同样现有框架实现图神经网络模型的速度不够快。

DGL 框架设计理念主要在于将图神经网络看作是消息传递的过程,每一个节点会发出它自己的消息,也会接收来自其它节点的消息。然后在得到所有信息之后做聚合,计算出节点新的表示。原有的深度学习框架都是进行张量运算,但是图很多时候并不能直接表示成一个完整的张量,需要手动补零,这其实很麻烦,不高效。

DGL 是基于现有框架,帮助用户更容易实现图神经网络模型。DGL 现在主要是以消息传递的接口作为核心,同时提供图采样以及批量处理图的接口。

关于 DGL 就不再进行过多介绍,感兴趣的同学可以去官网(http://dgl.ai/)了解。

2. Prepare

import torch
import time
import math
import dgl
import numpy as np
import torch.nn as nn
from dgl.data import citation_graph as citegrh
from dgl import DGLGraph
import dgl.function as fn
import networkx as nx
import torch.nn.functional as F

# 疑问 1: 为什么可以直接从 pytorch 中导入 GraphConv,这个不应该是 conv 文件中的吗
from dgl.nn import GraphConv
# from dgl.nn.pytorch import GraphConv
# from dgl.nn.pytorch.conv import GraphConv

这里有三种导入方法,建议用第一种,因为 DGL 的开发同学设计了一个机制,会自动 detect 用了什么 beckend,从而适配对应的 backend 的 api。

print(torch.__version__)
print(dgl.__version__)
print(nx.__version__)
1.4.0
0.4.3
2.3

3. GCN

3.1 First version

DGL 的第一种写法是利用 DGL 预定义的图卷积模块 GraphConv 来实现的。

GCN 的数学公式如下:
h i ( l + 1 ) = σ ( b ( l ) + ∑ j ∈ N ( i ) 1 c i j h j ( l ) W ( l ) ) h_i^{(l+1)} = \sigma(b^{(l)} + \sum_{j\in\mathcal{N}(i)}\frac{1}{c_{ij}}h_j^{(l)}W^{(l)}) hi(l+1)=σ(b(l)+jN(i)cij1hj(l)W(l))

其中, N ( i ) \mathcal{N}(i) N(i) 为节点的邻居集合, c i j = ∣ N ( i ) ∣ ∣ N ( j ) ∣ c_{ij}=\sqrt{|\mathcal{N}(i)|}\sqrt{|\mathcal{N}(j)|} cij=N(i) N(j) 表示节点度的平方根的乘积,用于归一化数据, s i g m a sigma sigma 为激活函数

GraphConv 模型参数初始化参考 tkipf 大佬的原始实现,其中 W ( l ) W^{(l)} W(l) 使用 Glorot uniform 统一初始化,并将偏差初始化为零。

简单介绍下 Glorot 均匀分布(uniform)

Glorot 均匀分布,也叫 Xavier 均匀分布,该方法源于 2010 年的一篇论文《Understanding the difficulty of training deep feedforward neural networks》。其核心思想在于:为了使得网络中信息更好的流动,每一层输出的方差应该尽量相等。基于这个目标,权重 W 的方差需要满足 ∀ i    V a r [ W i ] = 2 n i + n i + 1 \forall i \; Var[W^i] = \frac{2}{n_{i}+n_{i+1}} iVar[Wi]=n

  • 5
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是使用GCN实现聚类的代码示例,代码使用Python和PyTorch实现: ``` import torch import torch.nn.functional as F from torch_geometric.nn import GCNConv # 定义GCN模型 class GCN(torch.nn.Module): def __init__(self, input_dim, hidden_dim, output_dim): super(GCN, self).__init__() self.conv1 = GCNConv(input_dim, hidden_dim) self.conv2 = GCNConv(hidden_dim, output_dim) def forward(self, x, edge_index): x = F.relu(self.conv1(x, edge_index)) x = self.conv2(x, edge_index) return x # 定义聚类函数 def k_means(x, k): centroids = x[:k, :].clone() while True: distances = torch.cdist(x, centroids) _, cluster = distances.min(dim=1) new_centroids = torch.stack([x[cluster == i, :].mean(dim=0) for i in range(k)]) if torch.equal(new_centroids, centroids): break centroids = new_centroids return cluster # 加载数据 data = ... # 从文件或数据库中读取 # 初始化GCN模型 model = GCN(input_dim=data.num_features, hidden_dim=16, output_dim=8) # 训练模型 optimizer = torch.optim.Adam(model.parameters(), lr=0.01) for epoch in range(100): model.train() optimizer.zero_grad() x = model(data.x, data.edge_index) loss = F.mse_loss(x, data.y) loss.backward() optimizer.step() # 聚类节点 with torch.no_grad(): model.eval() x = model(data.x, data.edge_index) clusters = k_means(x, k=4) # 输出结果 print(clusters) ``` 上述代码中,我们首先定义了一个GCN模型,并使用PyTorch中的GCNConv层实现了卷积操作。然后,我们定义了一个聚类函数k_means,该函数使用k-means算法对节点进行聚类。在模型训练完成后,我们使用训练好的GCN模型对节点进行特征提取,并使用k-means算法对节点进行聚类。最后,我们输出了聚类结果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值