GNN动手实践(三):适用于同配图和异配图的高效图神经网络——H2GCN

一.前言

H 2 GCN \text{H}_{2}\text{GCN} H2GCN是NeurIPS 2020上发表的论文《Beyond Homophily in Graph Neural Networks: Current Limitations and Effective Designs》所提出来的一个同时适用于同配图和异配图的GNN模型。该模型官方也开源了相应的源码(Github),但是作者是基于Tensorflow实现的,为此,本文基于Pytorch+PyG来对该模型进行复现。

论文解读可以参考:《Beyond Homophily in Graph Neural Networks: Current Limitations and Effective Designs》阅读笔记

二.H2GCN理论基础

2.1 i − i- ihop邻居

在该论文中作者提出了 i − i- ihop邻居的概念,即 N ‾ i ( v ) \overline{N}_{i}(v) Ni(v),其指的是到节点 v v v最短路径为 i i i的节点的集合。例如便展示了 N ‾ i ( v ) \overline{N}_{i}(v) Ni(v)(黄色节点)和 N ‾ 2 ( v ) \overline{N}_{2}(v) N2(v)(紫色节点)。

neighborhoods

那么如何计算图中所有节点的 2 − 2- 2hop邻居呢?作者在论文中也给出了计算公式:
A 0 ← I n / ∗ I n  is the  n × n  identity matrix  ∗ / A ‾ 1 ← I [ A − I n > 0 ] / ∗ I  is a element-wise indicator function for matrix  ∗ / A ‾ 2 ← I [ A 2 − A − I n > 0 ] ; \begin{aligned} &\mathbf{A}_{0} \leftarrow \mathbf{I}_{n} \quad / * \mathbf{I}_{n} \text { is the } n \times n \text { identity matrix } * / \\ &\overline{\mathbf{A}}_{1} \leftarrow \mathbb{I}\left[\mathbf{A}-\mathbf{I}_{n}>0\right] \quad / * \mathbb{I} \text { is a element-wise indicator function for matrix } * / \\ &\overline{\mathbf{A}}_{2} \leftarrow \mathbb{I}\left[\mathbf{A}^{2}-\mathbf{A}-\mathbf{I}_{n}>0\right] ; \end{aligned} A0In/In is the n×n identity matrix /A1I[AIn>0]/I is a element-wise indicator function for matrix /A2I[A2AIn>0];
对于大图来说,如果是密集(dense)邻接矩阵,那 A 2 \mathbf{A}^2 A2的计算代价的非常高的。为此,本文采用稀疏矩阵乘法的形式来计算 A 2 \mathbf{A}^2 A2,而PyG中的SparseTensor刚好支持稀疏矩阵间的乘法。给定graph如下:

org_graph

下面是对其求图的2hop矩阵的示例代码:

import torch
from torch_sparse import SparseTensor
from torch_geometric.utils import to_undirected
import scipy.sparse as sp


def toCSR(spt):
    rowptr, col, value = spt.csr()
    mat = sp.csr_matrix((value, col, rowptr)).tolil()
    mat.setdiag(0)
    return mat.tocsr()


edge_index = torch.LongTensor([[0, 0, 0, 1, 1, 1, 2, 3],
                               [1, 2, 3, 2, 3, 5, 6, 4]])
edge_index = to_undirected(edge_index)
adj = SparseTensor(row=edge_index[0], col=edge_index[1],
                   sparse_sizes=(7, 7)).fill_value(1.0)
adj2 = adj.matmul(adj).fill_value(1.0)
adj_2hop = (toCSR(adj2) - toCSR(adj)) > 0
adj_2hop = SparseTensor.from_scipy(adj_2hop).fill_value(1.0)
print(adj_2hop.to_dense())
"""
tensor([[0., 0., 0., 0., 1., 1., 1.],
        [0., 0., 0., 0., 1., 0., 1.],
        [0., 0., 0., 1., 0., 1., 0.],
        [0., 0., 1., 0., 0., 1., 0.],
        [1., 1., 0., 0., 0., 0., 0.],
        [1., 0., 1., 1., 0., 0., 0.],
        [1., 1., 0., 0., 0., 0., 0.]])
"""

从最后输出的密集邻接矩阵可以验证上述求解的正确性,例如对于节点0,其2-hop邻居包括节点4、5、6。

2.2 框架详解

H 2 GCN \text{H}_{2}\text{GCN} H2GCN框架分为三个阶段:

  • 阶段一:特征编码(feature embedding)。
  • 阶段二:领域聚合,主要是聚合图节点的1-hop邻居和2-hop邻居特征(采用拼接效果最好),该阶段重复两轮。
  • 阶段三:将第一阶段以及第二阶段的几轮得到的特征进行拼接,得到最终的节点特征,然后进行下游的分类任务。

framework

三.复现与实验

3.1 实验环境

本实验的环境如下所示:

Python: 3.7
Pytorch: 1.10.1
torch_geometric: 2.0.4
scipy: 1.7.3

3.2 模型复现

根据2.1节,下面给出的是根据图的邻接矩阵计算 A 2 − A − I n > 0 \mathbf{A}^{2}-\mathbf{A}-\mathbf{I}_{n}>0 A2AIn>0的源码,以及对邻接矩阵进行正则化,即 D − 1 / 2 A D − 1 / 2 \mathbf{D}^{-1/2}\mathbf{A}\mathbf{D}^{-1/2} D1/2AD1/2的源码,注意操作的邻接矩阵数据存储都为SparseTensor格式:

from torch_sparse import SparseTensor, fill_diag, mul
from torch_sparse import sum as sparsesum
import scipy.sparse as sp


def toCSR(spt):
    if not spt.has_value():
        spt = spt.fill_value(1.)
    rowptr, col, value = spt.csr()
    mat = sp.csr_matrix((value, col, rowptr)).tolil()
    # remove self-loops
    mat.setdiag(0)
    return mat.tocsr()


def hopNeighborhood(adj):
    adj2 = adj.matmul(adj).fill_value(1.0)
    adj_2hop = (toCSR(adj2) - toCSR(adj)) > 0
    adj_2hop = SparseTensor.from_scipy(adj_2hop).fill_value(1.0)
    return adj2


def norm_adj(adj_t, add_self_loops=True):
    """
    normalization adj
    """
    if add_self_loops:
        adj_t = fill_diag(adj_t, 1.)
    deg = sparsesum(adj_t, dim=1)
    deg_inv_sqrt = deg.pow_(-0.5)
    deg_inv_sqrt.masked_fill_(deg_inv_sqrt == float('inf'), 0.)
    adj_t = mul(adj_t, deg_inv_sqrt.view(-1, 1))
    adj_t = mul(adj_t, deg_inv_sqrt.view(1, -1))
    return adj_t


if __name__ == "__main__":
    pass

根据第2.2节中的介绍,下面是 H 2 GCN \text{H}_{2}\text{GCN} H2GCN完整模型的源码:

import torch
import torch.nn as nn
import torch.nn.functional as F


class H2GCN(nn.Module):
    def __init__(self, in_channels, hidden_channels, out_channels, drop_prob,
                 round):
        super().__init__()
        self.round = round
        self.embed = nn.Sequential(nn.Linear(in_channels, hidden_channels),
                                   nn.ReLU())

        self.dropout = nn.Dropout(drop_prob)
        self.classification = nn.Linear(hidden_channels * (2**(round + 1) - 1),
                                        out_channels)

    def forward(self, x, adj, adj_2hop):
        hidden_reps = []
        x = self.embed(x)
        hidden_reps.append(x)
        for _ in range(self.round):
            r1 = adj.matmul(x)
            r2 = adj_2hop.matmul(x)
            x = torch.cat([r1, r2], dim=-1)
            hidden_reps.append(x)
        hf = self.dropout(torch.cat(hidden_reps, dim=-1))
        return F.log_softmax(self.classification(hf), dim=1)


if __name__ == "__main__":
    pass

3.2 实验及结果展示

本实验选取了原文中的三个同配率较高数据集CiteseerCoraPubMed和一个同配率较低的异配数据集Texas进行训练与测评。几个图数据集的统计特征如下所示:

数据集名称节点数边数节点特征数类别数train/val/test划分
Cora2,70810,5561,4337140/500/1000
Citeseer3,3279,1043,7036120/500/1000
PubMed19,71788,648500360/500/1000
Texas1833091703587/59/37

作者在论文中将上述benchmarks中进行了10次随机划分,对于每个类别选取48%/32%/20%的节点分别作为训练集、验证集和测试集。限于时间原因,就直接按数据集默认的划分方式进行实验了,另外Texas数据集包含10组划分方式,本实验只取了第0组的划分结果进行实验。因此,实验结果应该会和作者配置的方式有出入。

在本实验中,选取了GCN作为baseline,实验中在训练集上进行模型的参数更新,然后用验证集来筛选最佳模型,最后在最佳模型上对测试集进行测评,实验过程中进行了小范围内的网格搜索调参,然后选取最佳的结果:

epochs: 2000
lr: 0.01, 0.001, 0.0001
drop_prob: 0, 0.6

# 对应的运行命令示例
python main.py --dataset cora --lr 0.001 --drop_prob 0.6 --model gcn
python main.py --dataset texas --lr 0.001 --drop_prob 0.6 --model h2gcn

实验结果总结如下表所示:

数据集名称H2GCNGCN
Cora0.81600.7720
Citeseer0.68900.6820
PubMed0.78600.7410
Texas0.83780.6757

结论:从结果可以看出,作者设计的 H 2 GCN \text{H}_{2}\text{GCN} H2GCN是有效的,它能同时在同配图和异配图上都取得不错的性能。

四.结语

以上便是本文的全部内容,要是觉得不错的话就点个赞或关注一下博主吧,你们的支持是博主继续创作的不解动力,当然若是有任何问题也敬请批评指正!!!

想获取完整项目源码的可以私聊我。

  • 8
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
人工智能(AI)最近经历了复兴,在视觉,语言,控制和决策等关键领域取得了重大进展。 部分原因在于廉价数据和廉价计算资源,这些资源符合深度学习的自然优势。 然而,在不同的压力下发展的人类智能的许多定义特征仍然是当前方法无法实现的。 特别是,超越一个人的经验 - 从婴儿期开始人类智能的标志 - 仍然是现代人工智能的一项艰巨挑战。 以下是部分立场文件,部分审查和部分统一。我们认为组合概括必须是AI实现类似人类能力的首要任务,结构化表示和计算是实现这一目标的关键。就像生物学利用自然和培养合作一样,我们拒绝“手工工程”和“端到端”学习之间的错误选择,而是倡导一种从其互补优势中获益的方法。我们探索如何在深度学习架构中使用关系归纳偏差来促进对实体,关系和组成它们的规则的学习。我们为AI工具包提供了一个新的构建模块,具有强大的关系归纳偏差 - 形网络 - 它概括和扩展了在形上运行的神经网络的各种方法,并为操纵结构化知识和生成结构化行为提供了直接的界面。我们讨论网络如何支持关系推理和组合泛化,为更复杂,可解释和灵活的推理模式奠定基础。作为本文的配套文件,我们还发布了一个用于构建形网络的开源软件库,并演示了如何在实践中使用它们。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

斯曦巍峨

码文不易,有条件的可以支持一下

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

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

打赏作者

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

抵扣说明:

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

余额充值