网站建设的解决办法,网站外链优化,wordpress 函数api文件,网易企业邮箱怎么撤回邮件Pytorch自带一个PyG的图神经网络库#xff0c;和构建卷积神经网络类似。不同于卷积神经网络仅需重构__init__( )和forward( )两个函数#xff0c;PyTorch必须额外重构propagate( )和message( )函数。
一、环境构建 ①安装torch_geometric包。
pip install torch_geometric …Pytorch自带一个PyG的图神经网络库和构建卷积神经网络类似。不同于卷积神经网络仅需重构__init__( )和forward( )两个函数PyTorch必须额外重构propagate( )和message( )函数。
一、环境构建 ①安装torch_geometric包。
pip install torch_geometric ②导入相关库
import torch
import torch.nn.functional as F
import torch.nn as nn
import torch_geometric.nn as pyg_nn
from torch_geometric.datasets import Planetoid二、PyG图学习架构 构建方法首先继承MessagePassing类接下来重写构造函数和以下三个方法
message() #构建消息传递
aggregate() #将消息聚合到目标节点
update() #更新消息节点 1.构造函数
def __init__(self, aggr: Optional[str] add,flow: str source_to_target, node_dim: int -2,decomposed_layers: int 1):参数内容aggr消息聚合的方式常见的方法add、mean、min、maxflow 消息传播的方向source_to_target--从源节点到目标节点 target_to_source--从目标节点到源节点 node_dim传播的维度2.propagate函数 该函数为消息传播的启动函数调用此函数后会依次执行message、aggregate、update来完成消息的传递、聚合、更新。 该函数声明如下
propagate(self, edge_index: Adj, size: Size None, **kwargs)
参数说明edge_index边索引size邻接矩阵的尺寸若为None则表示方阵**kwargs额外参数3.message函数 用于构建节点消息传递给propagate的tensor可以映射到中心节点和邻居节点仅需在相应的变量名后加上_i中心节点或_j邻居节点即可。
self.propagate(edge_index, xx):passdef message(self, x_i, x_j, edge_index_i):pass
x_i中心节点构成的特征向量组成的矩阵x_j邻居节点构成的特征向量组成的矩阵edge_index_i中心节点的索引4.aggregate函数 消息聚合函数用以聚合来自邻居的消息常见的方法有add、sum、mean、max可以通过super().__init__()中的参数aggr来设定 5.update函数 用于更新节点的消息
三、GCN图卷积网络 GCN网络的原理可见图卷积神经网络--GCN 需要注意 torch_scatter无法使用pip install加载可以参见 torch_scatter安装 1.加载数据集
from torch_geometric.datasets import Planetoiddataset Planetoid(rootCora, nameCora) Cora数据集是一个根据科学论文之间相互引用关系构建的图(Graph)数据集合论文合计7类共2708篇论文2708个节点10556条边。 2.定义GCN层
class GCNConv(MessagePassing):def __init__(self, in_channels, out_channels, add_self_loopsTrue, biasTrue):super(GCNConv, self).__init__()self.add_self_loops add_self_loopsself.edge_index Noneself.linear pyg_nn.dense.linear.Linear(in_channels, out_channels, weight_initializerglorot)if bias:self.bias nn.Parameter(torch.Tensor(out_channels, 1))self.bias pyg_nn.inits.glorot(self.bias)else:self.register_parameter(bias, None)# 1.消息传递def message(self, x, edge_index):# 1.对所有节点进行新的空间映射x self.linear(x) # [num_nodes, feature_size]# 2.添加偏置if self.bias ! None:x self.bias.flatten()# 3.返回source、target信息对应边的起点和终点row, col edge_index # [E]# 4.获得度矩阵deg degree(col, x.shape[0], x.dtype) # [num_nodes]# 5.度矩阵归一化deg_inv_sqrt deg.pow(-0.5) # [num_nodes]# 6.计算sqrt(deg(i)) * sqrt(deg(j))norm deg_inv_sqrt[row] * deg_inv_sqrt[col] # [num_nodes]# 7.返回所有边的映射x_j x[row] # [E, feature_size]# 8.计算归一化后的节点特征x_j norm.view(-1, 1) * x_j # [E, feature_size]return x_j# 2.消息聚合def aggregate(self, x_j, edge_index):# 1.返回source、target信息对应边的起点和终点row, col edge_index # [E]# 2.聚合邻居特征aggr_out scatter(x_j, row, dim0, reducesum) # [num_nodes, feature_size]return aggr_out# 3.节点更新def update(self, aggr_out):# 对于GCN没有这个阶段所以直接返回return aggr_outdef forward(self, x, edge_index):# 2.添加自环信息考虑自身信息if self.add_self_loops:edge_index, _ add_self_loops(edge_index, num_nodesx.shape[0]) # [2, E]return self.propagate(edge_index, xx) 3.定义GCN网络
class GCN(nn.Module):def __init__(self, num_node_features, num_classes):super(GCN, self).__init__()self.conv1 GCNConv(num_node_features, 16)self.conv2 GCNConv(16, num_classes)def forward(self, data):x, edge_index data.x, data.edge_indexx self.conv1(x, edge_index)x F.relu(x)x F.dropout(x, trainingself.training)x self.conv2(x, edge_index)return F.log_softmax(x, dim1) 4.模型调用
device torch.device(cuda if torch.cuda.is_available() else cpu) # 设备
epochs 200 # 学习轮数
lr 0.0003 # 学习率
num_node_features dataset.num_node_features # 每个节点的特征数
num_classes dataset.num_classes # 每个节点的类别数
data dataset[0].to(device) # Cora的一张图# 4.定义模型
model GCN(num_node_features, num_classes).to(device)
optimizer torch.optim.Adam(model.parameters(), lrlr) # 优化器
loss_function nn.NLLLoss() # 损失函数# 训练模式
model.train()for epoch in range(epochs):optimizer.zero_grad()pred model(data)loss loss_function(pred[data.train_mask], data.y[data.train_mask]) # 损失correct_count_train pred.argmax(axis1)[data.train_mask].eq(data.y[data.train_mask]).sum().item() # epoch正确分类数目acc_train correct_count_train / data.train_mask.sum().item() # epoch训练精度loss.backward()optimizer.step()if epoch % 20 0:print(【EPOCH: 】%s % str(epoch 1))print(训练损失为{:.4f}.format(loss.item()), 训练精度为{:.4f}.format(acc_train))print(【Finished Training】)# 模型验证
model.eval()
pred model(data)# 训练集使用了掩码
correct_count_train pred.argmax(axis1)[data.train_mask].eq(data.y[data.train_mask]).sum().item()
acc_train correct_count_train / data.train_mask.sum().item()
loss_train loss_function(pred[data.train_mask], data.y[data.train_mask]).item()# 测试集
correct_count_test pred.argmax(axis1)[data.test_mask].eq(data.y[data.test_mask]).sum().item()
acc_test correct_count_test / data.test_mask.sum().item()
loss_test loss_function(pred[data.test_mask], data.y[data.test_mask]).item()print(Train Accuracy: {:.4f}.format(acc_train), Train Loss: {:.4f}.format(loss_train))
print(Test Accuracy: {:.4f}.format(acc_test), Test Loss: {:.4f}.format(loss_test))