深度讲解PyG实现自定义layer的GCN
目前的代码讲解基本都是直接使用PyG内置的包实现固定结构的网络层。虽然我们可以通过每层使用不同的传递方式来建立不同的网络,但是却不能自定义网络层的传递方式,对于做创新性的研究工作而言是一个不足。
本篇在 GCN学习:Pytorch-Geometric教程(二)的基础上,自定义了GCN的层传递方式(仍然是按照论文中的传递方式建立,但是我们以后也可以建立其他传递方式),其他代码与系列(二)的代码相同。
完整代码
import torch
from torch_geometric.nn import MessagePassing
from torch_geometric.utils import add_self_loops,degree
from torch_geometric.datasets import Planetoid
import ssl
import torch.nn.functional as F
class GCNConv(MessagePassing):
def __init__(self,in_channels,out_channels):
super(GCNConv,self).__init__(aggr='add')
self.lin=torch.nn.Linear(in_channels,out_channels)
def forward(self,x,edge_index):
edge_index, _ = add_self_loops(edge_index,num_nodes=x.size(0))
x=self.lin(x)
row,col=edge_index
#计算度矩阵
deg=degree(col,x.size(0),dtype=x.dtype)
#度矩阵的-1/2次方
deg_inv_sqrt=deg.pow(-0.5)
norm=deg_inv_sqrt[row]*deg_inv_sqrt[col]
return self.propagate(edge_index,x=x,norm=norm)
def message(self,x_j,norm):
return norm.view(-1,1)*x_j
ssl._create_default_https_context = ssl._create_unverified_context
dataset = Planetoid(root='Cora', name='Cora')
print(dataset)
print(dataset.num_node_features)
print(dataset.num_classes)
class Net(torch.nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = GCNConv(dataset.num_node_features, 16)
self.conv2 = GCNConv(16, dataset.num_classes)
def forward(self, data):
x, edge_index = data.x, data.edge_index
x = self.conv1(x, edge_index)
x = F.relu(x)
x = F.dropout(x, training=self.training)
x = self.conv2(x, edge_index)
return F.log_softmax(x, dim=1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = Net().to(device)
data = dataset[0].to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)
model.train()
for epoch in range(200):
optimizer