【源码复现】图神经网络之SGC

一、论文简介

二、论文核心概述

 本篇论文是针对GCN论文的改进。
 GCN采用分层的结构进行信息传播(Propagation)和线性变变换(Transformation),并在每层之后采用ReLU非线性激活函数,最后一层采用Softmax激活函数来进行预测。本文作者认为受深度学习方法启发的GCN模型,存在固有的复杂度和冗余的计算,这些是由于非线性激活函数引起的,而且降低了模型的可解释性。从这个角度出发,作者重复地移除GCN每层地非线性激活函数并保留最终的Softmax激活函数进行预测,对于重复的矩阵乘积形式,采用矩阵幂的形式来表示,用一个统一的可学习矩阵 W W W来进行线性变换。

GCN模型
第 K 层定义的传播规则为: H k ← R e L U ( S H ( K − 1 ) W ( K ) ) ;        H ( 0 ) = X ; K 层 G C N 的模型预测为: Y ^ G C N = S o f t m a x ( S H ( k − 1 ) W ( K ) ) 第K层定义的传播规则为:H^{k} \gets ReLU(SH^{(K-1)}W^{(K)}) ; \;\;\;H^{(0)}=X; \\ K层GCN的模型预测为:\hat Y_{GCN} = Softmax(SH^{(k-1)}W^{(K)}) K层定义的传播规则为:HkReLU(SH(K1)W(K));H(0)=X;KGCN的模型预测为:Y^GCN=Softmax(SH(k1)W(K))
重复地移除非线性激活函数后,结果如下:
Y ^ = S o f t m a x ( S . . . S X W ( 1 ) W ( 2 ) . . . W ( K ) ) \hat Y = Softmax(S...SXW^{(1)}W^{(2)}...W^{(K)}) Y^=Softmax(S...SXW(1)W(2)...W(K))
将重复地 S S S采用矩阵乘积地形式表示,并将每层地线性变换矩阵用一个统一的矩阵 W W W来表示,得到的结果为:
Y ^ S G C = S o f t m a x ( S K X W ) \hat Y_{SGC} = Softmax(S^KXW) Y^SGC=Softmax(SKXW)
这就是SGC最终地模型,作者通过大量的实验分析,与GCN模型在分类准确性上势均力敌,但在代码执行速度上比GCN快了几个数量级。SGC模型看似非常简单,但思想的创新实则不易。下图就是SGC与GCN模型的比较。


 同时,本文作者也从谱域对SGC进行分析,表明重整归一化的传播矩阵 S = D − 1 2 ( A + I ) D − 1 2 S=D^{-\frac{1}{2}}(A+I)D^{-\frac{1}{2}} S=D21(A+I)D21是一种低通滤波器,S的最大值从原来的2近似为原来的1.5左右,并且消除了负数系数的影响,而且,这种低通滤波器能够产生局部平滑的效果。

三、Pyorch源码

模型核心代码
可以理解为一种简单的线性回归问题(完整代码详见文章末尾)。

注释部分是另外一种写法,等价于Linear方法

import torch
from torch.nn import Module,Linear
from torch.nn import functional as F
from torch.nn import Parameter

class SGC(Module):
    def __init__(self,input_dim,output_dim):
        super(SGC, self).__init__()
        self.input_feature = input_dim
        # 输出特征
        self.output_feature = output_dim
        self.layer = Linear(input_dim,output_dim,bias=False)

        # self.weight = Parameter(torch.FloatTensor(input_dim,output_dim))
        # torch.nn.init.xavier_uniform_(self.weight.data,gain=1)

    def forward(self,x):
        #x = S^k * H
        #output = torch.mm(x,self.weight)
        return F.log_softmax(self.layer(x),dim=1)
        #return F.log_softmax(output,dim=1)

SGC模型输入的 X = S k X X= S^kX X=SkX,其计算方法如下:

#对邻接矩阵进行预处理:S^k
def sgc_precompute(features,adj,k):
    for i in range(k):
        features = torch.mm(adj,features)
    return features

链接:https://pan.baidu.com/s/1EzhVCVKWzI3hRjuPpPeZGA
提取码:6666

四、DGL复现SGC模型

import os

os.environ["DGLBACKEND"] = "pytorch"

import dgl
import dgl.function as fn
import torch 
import torch.nn as nn
import torch.nn.functional as F
from dgl.nn.pytorch.conv import SGConv,GraphConv

class SGCLayer(nn.Module):
    def __init__(self,infeat,outfeat,k) -> None:
        super(SGCLayer,self).__init__()
        self.fn = nn.Linear(infeat,outfeat,bias=False)
        self.fn.reset_parameters()
        self.weight = nn.Parameter(torch.Tensor(infeat, outfeat))
        nn.init.xavier_uniform_(self.weight.data,gain=1.414)
        self.k = k
    def forward(self,g,feat):
        with g.local_scope():
            g = dgl.add_self_loop(g)
            # degs = g.in_degrees().to(feat).clamp(min=1)
            # norm = torch.pow(degs,-0.5)
            # norm = norm.to(feat.device).unsqueeze(1)
            degs = g.out_degrees().to(feat).clamp(min=1)
            norm = torch.pow(degs,-0.5)
            shp = norm.shape + (1,) * (feat.dim() -1 )
            norm = torch.reshape(norm,shp)
            for _ in range(self.k):
                feat = feat * norm
                g.ndata['h'] = feat 
                g.update_all(fn.copy_u('h','m'),fn.sum(msg='m',out ='h'))
                feat = g.ndata.pop('h')
                feat = feat * norm
            #return torch.matmul(feat,self.weight)
            return self.fn(feat)

class SGC(nn.Module):
    def __init__(self,infeat,outfeat ,dropout,k) -> None:
        super(SGC,self).__init__()
        self.dropout = dropout
        self.layer = SGCLayer(infeat,outfeat,k)
    def forward(self,g,features):
        x = F.dropout(features,self.dropout,training=self.training)
        x = self.layer(g,x)
        return F.log_softmax(x,dim=1)
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

鲸可落

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

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

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

打赏作者

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

抵扣说明:

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

余额充值