dgl-02 gcn


GCN

为什么需要gcn

  1. 之前的cnn无法处理非欧式距离的数据
  2. 而非欧式距离的数据(比如拓扑结构,网络结构)在现实中是一种广泛存在的数据结构

GCN原理

比较多的是从谱域来解释,关于怎么从二维卷积到图卷积,参考这个:从二维卷积到图卷积

  1. 定义谱域的卷积操作,其中有用到拉普拉斯矩阵
  2. 完整的卷积公式很复杂,通过切比雪夫近似得到gcn的迭代公式:
    在这里插入图片描述

说明:

  1. A和D是基于图结构得到的,固定参数
  2. H是输入,节点的特征矩阵,输入一次H0,迭代得到中间层
  3. W是要学习的参数

理解:

  1. A 和 H 的乘积其实就是把所有的邻居节点向量进行相加
    在这里插入图片描述
  2. A+I是把自身节点加上【Q1】
  3. DAD是对A做归一化,防止某些度比较大的节点影响模型训练【Q2】
  4. DADH就是利用邻接矩阵对H根据邻居信息进行聚合,最后乘以W类似于全连接矩阵。

代码实现

dgl官网代码:gcn

dgl里面图卷积用的公式为:
在这里插入图片描述
这是原论文里面公式12,论文
原理和上面的公式是一样的,主要是对邻居借点做归一化。
补充一个讲解:GCN

卷积部分: GraphConv

# 这个模块就是最基础的图卷积,也就是走 DADHW 这个公式

# __ini__() 定义里面主要是定义W和激活函数
self._in_feats = in_feats
self._out_feats = out_feats
self._norm = norm
self._allow_zero_in_degree = allow_zero_in_degree

if weight:
    self.weight = nn.Parameter(th.Tensor(in_feats, out_feats))
else:
    self.register_parameter('weight', None)

if bias:
    self.bias = nn.Parameter(th.Tensor(out_feats))
else:
    self.register_parameter('bias', None)

self.reset_parameters()

self._activation = activation


# forward(), 主要做归一化,然后全连接,核心代码如下:

# 做归一化
degs = graph.out_degrees().float().clamp(min=1)  
norm = th.pow(degs, -0.5)  

# 全联接
feat_src = feat_src * norm
feat_src = th.matmul(feat_src, weight)
rst = rst + self.bias

# 激活
rst = self._activation(rst)


GCN模型

# 卷积层定义好后,这里就是定义2层卷积就行了,
class GCN(nn.Module):
   def __init__(self, in_size, hid_size, out_size):
       super().__init__()
       self.layers = nn.ModuleList()
       # two-layer GCN
       self.layers.append(dglnn.GraphConv(in_size, hid_size, activation=F.relu))
       self.layers.append(dglnn.GraphConv(hid_size, out_size))
       self.dropout = nn.Dropout(0.5)

   def forward(self, g, features):
       h = features
       for i, layer in enumerate(self.layers):
           if i != 0:
               h = self.dropout(h)
           h = layer(g, h)
       return h

训练代码:

for epoch in range(200):
     model.train()
     logits = model(g, features)
     loss = loss_fcn(logits[train_mask], labels[train_mask])
     optimizer.zero_grad()
     loss.backward()
     optimizer.step()
  • 这里可以看出模型的输入是整个graph和所有特征节点向量。计算loss的时候用train_mask来筛选训练数据计算loss。因此gcn的方法对于动态图就不适应了。比如定义好graph后,训练完了,有新的节点加入,那么需要重新训练模型

cora数据结果

Epoch 00197 | Loss 0.3549 | Accuracy 0.7860 
Epoch 00198 | Loss 0.3656 | Accuracy 0.7880 
Epoch 00199 | Loss 0.3818 | Accuracy 0.7900 
Testing...
Test accuracy 0.8090

  • paper里面是0.815
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 PyTorch 中搭建一个基于 DGL 的 GCN 模型,需要以下步骤: 1. 安装 DGL 库: `pip install dgl` 2. 导入 DGL 中 GCN 模型所需的库: ```python import dgl import dgl.function as fn import torch import torch.nn as nn ``` 3. 定义 GCNLayer 类继承自 nn.Module,并实现 forward() 函数: ```python class GCNLayer(nn.Module): def __init__(self, in_feats, out_feats): super(GCNLayer, self).__init__() self.linear = nn.Linear(in_feats, out_feats) def forward(self, g, inputs): # g is the graph and the inputs is the input node features # first set the node features g.ndata['h'] = inputs # then send the node features to its neighbors g.update_all(fn.copy_src('h', 'm'), fn.sum('m', 'h')) # apply linear transformation h = self.linear(g.ndata['h']) return h ``` 4. 构建 GCN 模型,并定义损失函数和优化器: ```python class GCN(nn.Module): def __init__(self, in_feats, hidden_size, num_classes): super(GCN, self).__init__() self.layer1 = GCNLayer(in_feats, hidden_size) self.layer2 = GCNLayer(hidden_size, num_classes) def forward(self, g, inputs): h = self.layer1(g, inputs) h = torch.relu(h) h = self.layer2(g, h) return h # define loss function and optimizer criterion = nn.CrossEntropyLoss() optimizer = torch.optim.Adam(model.parameters(), lr=0.01) ``` 5. 加载数据并训练模型: ```python # load your data g, inputs, labels = ... # training loop for epoch in range(100): logits = model(g, inputs) loss = criterion(logits, labels) optimizer.zero_grad() loss.backward() optimizer.step() ``` 以上是一个简单的 GCN 模型的实现,你可以根据你的数据和需求来修改

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值