赣县企业网站建设,网站开发如何入门,稳定一天赚200块游戏,搭建一个微信小程序要多少钱目录 1、论文简介2、论文核心介绍2.1、研究动机2.2、创新点2.3、具体实现2.3.1、初始残差链接2.3.2、恒等映射2.3.3、模型 3、源码复现3.1、Torch复现3.2、DGL复现 1、论文简介
论文题目——《Simple and Deep Graph Convolutional Networks》论文作者——Ming Chen#xff0… 目录 1、论文简介2、论文核心介绍2.1、研究动机2.2、创新点2.3、具体实现2.3.1、初始残差链接2.3.2、恒等映射2.3.3、模型 3、源码复现3.1、Torch复现3.2、DGL复现 1、论文简介
论文题目——《Simple and Deep Graph Convolutional Networks》论文作者——Ming ChenZhewei Wei Zengfeng HuangBolin DingYaliang Li论文地址——Simple and Deep Graph Convolutional Networks》源码———论文源码链接
2、论文核心介绍
2.1、研究动机 图神经网络是一种强大的处理图结构数据的有效学习方法。图神经网络及其变体在真实数据集上显示出了优异的性能。但目前的大多数GCN模型都很浅GCN和GAT都是在两层的模型上实现最佳性能。浅层的网络结构限制了他们从高阶邻居中提取信息的能力。 然而堆叠多层和添加非线性往往会降低模型的性能出现过平滑的现象原因是随着堆叠层数的增加GCN中节点的表示会收敛到某个值因此变得无法区分。 那么那图神经网络真的可以达到深层吗答案是肯定的
2.2、创新点 在传统GCN的基础上引入两个简单的技术初始剩余连接和恒等映射来真正实现深层的图卷积神经网络。
初始残差连接是将 H ( l ) H^{(l)} H(l)与第一层 H ( 0 ) H^{(0)} H(0)的初始残差连接相结合增加了一个恒等式映射 I n I_n In到第 l l l层权重矩阵 W ( ℓ ) W^{(ℓ)} W(ℓ)中。
2.3、具体实现 GCNII模型灵感来自于2016年计算机视觉领域解决相似问题的ResNet模型ResNet模型采用残差连接使模型可以训练更深层的网络。同样采用初始残差的APPNP模型采用线性聚合方式很难达到深层说明仅仅在图神经网络模型中添加残差连接是不充分的并不能使图神经网络引向更深的模型。为此GCNII模型采用初始残差连接和恒等映射两个技巧可以达到深层的模型而不会导致过平滑的现象。
2.3.1、初始残差链接 为了模拟ResNet中的残差连接GCN提出了将平滑表示 P H ( ℓ ) \mathrm{PH^{(ℓ)}} PH(ℓ)与 H ( ℓ ) \mathrm{H^{(ℓ)}} H(ℓ)相结合的残差连接但是这种残差连接并没有实质上解决过平滑的问题随着网络层数的增多模型的性能仍会降低。 因此GCNII模型中没有使用上一层的残差连接而是初始表 H ( 0 ) \mathrm{H^{(0)}} H(0)称为初始残差连接。这样即使堆叠了很多层初始剩余连接确保每个节点的最终表示都至少保留输入层的一小部分信息作者简单将 α l \alpha_{l} αl设置为0.1或0.2以便每个节点的最终表示都至少包含输入特征的一小部分信息。 值得注意的是 H ( 0 ) \mathrm{H^{(0)}} H(0)不一定是特征矩阵 X \mathrm{X} X。如果特征维数 d \mathrm{d} d比较大可以在 X \mathrm{X} X上应用全连接神经网络以在前向传播之前获得较低维的初始表示 H ( 0 ) \mathrm{H^{(0)}} H(0)。
2.3.2、恒等映射 恒等映射确保深层GCNII模型至少实现与其浅层版本相同的性能。通过将 β l \beta_{l} βl设置得足够小深度的GCNII会忽略权重矩阵 W ( ℓ ) W^{(ℓ)} W(ℓ)。 已经观察到特征矩阵在不同维度之间的频繁交互降低了模型在半监督任务中的性能。然而将平滑表示 P H ( ℓ ) \mathrm{PH^{(ℓ)}} PH(ℓ)直接映射到输出则会减少了这种交互。 恒等映射被证明在半监督任务中特别有用。HardtMa2017证明了形式为 H ( l 1 ) H ( l ) ( W ( l ) I n ) \mathrm{H^{(l1)}H^{(l)}(W^{(l)}I_n)} H(l1)H(l)(W(l)In)满足以下性质 最优权矩阵 W ( ℓ ) W^{(ℓ)} W(ℓ)具有小范数 这个性质允许我们强正则化 W ( ℓ ) W^{(ℓ)} W(ℓ)避免过度拟合唯一的临界点是全局极小值。 在训练数据有限的半监督任务中是可取的 OonoSuzuki从理论上证明了K层GCNS的节点特征会收敛到一个子空间从而导致信息丢失。特别地收敛速度依赖于 S K S^K SKS是权重矩阵 W ( ℓ ) W^{(ℓ)} W(ℓ)ℓ0…K−1的最大奇异值。通过将 W ( ℓ ) W^{(ℓ)} W(ℓ)替换为 ( 1 − β l ) I n β l W ( l ) (1-\beta_l)\mathrm{I_n}\beta_lW^{(l)} (1−βl)InβlW(l)并对 W ( ℓ ) W^{(ℓ)} W(ℓ)施加正则化强制 W ( ℓ ) W^{(ℓ)} W(ℓ)的范数小。因此上式的奇异值将接近1。因此最大奇异值s也将接近1这意味着 S K S^K SK过大信息损失得到缓解。设置 β l \beta_l βl的原则是确保权重矩阵的衰减随着层数的增加而自适应地增加。
2.3.3、模型
GCNII模型分层结构可以被描述为 H ( l 1 ) σ ( ( ( 1 − α l ) A ^ H ( l ) α l H ( 0 ) ) ( ( 1 − β l ) I n β l W ( l ) ) ) H^{(l1)} \sigma(((1-\alpha_l)\hat{A}H^{(l)}\alpha_lH^{(0)})((1-\beta_l)I_n\beta_lW^{(l)})) H(l1)σ(((1−αl)A^H(l)αlH(0))((1−βl)InβlW(l))) 初始残差连接确保每个结点堆叠多层的最终表征至少包含来自输入的部分表征。 为了弥补APPNP的缺陷GCNII借鉴ResNet模型中恒等映射的思想。恒等映射可以使深层GCNII模型实现与浅层GCNII模型达到相同的性能同时使模型能够关注局部的邻域信息最后还可以防止过拟合。 从谱域的角度来看一个k层的GCNII可以模型任意的系数的k阶多项式谱图滤波器感兴趣的读者可以去读这篇论文。
参考连接
3、源码复现
详细源码请参考百度网盘连接 链接https://pan.baidu.com/s/1IV9Kdg9TyWSWxMC9qZsIiA 提取码6666 3.1、Torch复现
import torch
from torch import nn
from torch.nn import functional as F
from torch.nn import Module
from torch.nn import Linear
from torch.nn.parameter import Parameter
from torch.nn import functional as F
import torch
import mathclass GraphConvLayer(Module):def __init__(self, unit_num,alpha,beta,device) - None:super(GraphConvLayer,self).__init__()self.alpha alphaself.beta betaself.device deviceself.W Parameter(torch.empty(size(unit_num,unit_num)))self.init_param()passdef init_param(self):torch.nn.init.xavier_uniform_(self.W.data,gain1.414)def forward(self,P,H,H0):#P : N*N#H : N*C#H0 : N *F#W : C*Cinitial_res_connect (1-self.alpha)*torch.mm(P,H)self.alpha * H0I torch.eye(self.W.shape[0]).to(self.device)identity_map (1-self.beta) * I self.beta * self.Woutput torch.mm(initial_res_connect,identity_map)return F.relu(output)class GCNII(Module):def __init__(self, input_dim,hidden_dim,output_dim,k,alpha,lamda,dropout,device):super(GCNII,self).__init__()self.layer1 Linear(input_dim,hidden_dim)self.layer2 Linear(hidden_dim,output_dim)self.convs nn.ModuleList()self.convs.append(self.layer1)self.k kself.dropout dropout#self.layers []for i in range(k):beta math.log(lamda / (i1) 1)self.convs.append(GraphConvLayer(hidden_dim,alpha,beta,device))self.convs.append(self.layer2)self.reg_param list(self.convs[1:-1].parameters())self.non_linear_param list(self.convs[0:1].parameters())list(self.convs[-1:].parameters())#直接在低维变换效果不好高维变换再映射到低维空间#self.layers.append(GraphConvLayer(output_dim,alpha,beta,device))# for i,layer in enumerate(self.layers):# self.add_module(f{i},layer)def forward(self,features,adj):#H0 self.layer1(features)H0 F.dropout(features,self.dropout,training self.training)H0 F.relu(self.convs[0](H0))H H0#for layer in self.layers:for layer in self.convs[1:-1]:H F.dropout(H,self.dropout,training self.training)H layer(adj,H,H0)H F.dropout(H,self.dropout,training self.training)output self.convs[-1](H)#output self.layer2(H)return F.log_softmax(output,dim1)
class GCNII_START(Module):def __init__(self, input_dim,hidden_dim,output_dim,k,alpha,lamda,dropout,device) :super(GCNII_START,self).__init__()self.layer1 Linear(input_dim,hidden_dim)self.layer2 Linear(hidden_dim,output_dim)self.dropout dropoutself.layers []for i in range(k):beta lamda /(i1)self.layers.append(GraphConvLayer_START(hidden_dim,alpha,beta,device))for i,layer in enumerate(self.layers):self.add_module(f{i},layer)def forward(self,features,adj):H0 F.dropout(features,self.dropout,training self.training)H0 F.relu(self.layer1(H0))H H0for layer in self.layers:H F.dropout(H,self.dropout,trainingself.training)H layer(adj,H,H0)H F.dropout(H,self.dropout,training self.training)output self.layer2(H)return F.log_softmax(output,dim1)pass
class GraphConvLayer_START(Module):def __init__(self, unit_num,alpha,beta,device):super(GraphConvLayer_START,self).__init__()self.alpha alphaself.beta betaself.device deviceself.W1 Parameter(torch.empty(size(unit_num,unit_num)))self.W2 Parameter(torch.empty(size(unit_num,unit_num)))self.init_param()def init_param(self):nn.init.xavier_uniform_(self.W1.data,gain1.414)nn.init.xavier_uniform_(self.W2.data,gain1.414)def forward(self,P,H,H0):I torch.eye(self.W1.shape[0]).to(self.device)propagation torch.mm(P,H)initial_res H0identity_map1 (1-self.beta)*Iself.beta*self.W1identity_map2 (1-self.beta)*Iself.beta*self.W2output (1-self.alpha)*torch.mm(propagation,identity_map1) self.alpha * torch.mm(initial_res,identity_map2)return F.relu(output)3.2、DGL复现
DGL复现精度可达0.8510仅在cpu上
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
import mathclass GraphConvLayer(nn.Module):def __init__(self,infeat,alpha,beta) - None:super(GraphConvLayer,self).__init__()self.alpha alphaself.beta betaself.W nn.Parameter(torch.empty(size(infeat,infeat)))nn.init.xavier_uniform_(self.W.data,gain1.414)def forward(self,x,g):with g.local_scope():h0 g.ndata[init_feat]#添加自环g dgl.add_self_loop(g)#计算正则degs g.in_degrees().to(x).clamp(min1)norm torch.pow(degs,-0.5)norm norm.to(x.device).unsqueeze(1)x x * normg.ndata[h] xg.update_all(fn.copy_u(h,m),fn.sum(m,h))h g.ndata[h].to(x)h h * normr (1-self.alpha) * h self.alpha * h0out (1-self.beta) * r self.beta * torch.mm(r,self.W)return out
class GCNII(nn.Module):def __init__(self,infeat,hidfeat,outfeat,alpha,lamda,dropout,k) - None:super(GCNII,self).__init__()self.dropout dropoutself.convs nn.ModuleList()for i in range(k):#theta lamda /(i1)beta math.log(lamda/(i1)1)self.convs.append(GraphConvLayer(hidfeat,alpha,beta))self.fcs nn.ModuleList()self.fcs.append(nn.Linear(infeat,hidfeat))self.fcs.append(nn.Linear(hidfeat,outfeat))self.params1 list(self.convs.parameters())self.params2 list(self.fcs.parameters())self.act_fn nn.ReLU()self.sg nn.Sigmoid()self.init_param()def init_param(self):self.fcs[0].reset_parameters()self.fcs[1].reset_parameters()def forward(self,x,g):x F.dropout(x,self.dropout,trainingself.training)x self.act_fn(self.fcs[0](x))print(x.device())g.ndata[init_feat] xh xfor conv in self.convs:h self.act_fn(conv(h,g))h F.dropout(h,self.dropout,trainingself.training)h self.fcs[-1](h)return F.log_softmax(h,dim1)