# Data类的构造函数
class Data(object):
def __init__(self, x=None, edge_index=None, edge_attr=None, y=None, **kwargs):
pass
从上面代码可以看到 :
edge_index的每一列定义一条边,其中第一行为边起始节点的索引,第二行为边结 束节点的索引。这种表示方法被称为COO格式(coordinate format),通常用于表示稀疏矩阵。PyG不是用稠密矩阵 来持有邻接矩阵的信息,而是用仅存储邻接矩阵 中非 元素的稀疏矩阵来表示图
通常,一个图至少包含x, edge_index, edge_attr, y, num_nodes5个属性,当图包含其他属性时,我们可以通过指定额外的参数使Data对象包含其他的属性:
graph = Data(x=x, edge_index=edge_index, edge_attr=edge_attr, y=y, num_nodes=num_nodes, other_attr=other_attr)
import numpy as np
from numpy.random import randn
from torch_geometric.data import Data
# 定义节点相关数据
num_nodes = 2000
num_node_features = 4000
num_edges = 100
# 定义字典对象
graph_dict = {
'x': randn(num_nodes, num_node_features),
'edge_index': randn(2, num_edges),
'edge_attr': randn(num_edges, num_node_features),
'y': randn(num_edges),
'num_nodes': num_nodes
}
graph_data = Data.from_dict(graph_dict)
print(graph_data)
Data(x=[2000, 4000], edge_index=[2, 100], edge_attr=[100, 4000], y=[100], num_nodes=2000)
data_dict = Data.to_dict(graph_data)
print(data_dict)
# 获取Data的属性
x = graph_data['x']
print(x.shape)
# 获取Data属性包含的关键字
print(graph_data.keys)
# 导入已有的数据集
from torch_geometric.datasets import KarateClub
datasets = KarateClub()
print("查看图的个数 : {}".format(len(datasets)))
# 获取第一张图
data = datasets[0]
print(data)
# 获取图的相关信息
print("图的节点数量 : {}".format(data.num_nodes))
print("图的节点属性的维度 : {}".format(data.num_node_features))
print("同样是节点属性的维度 : {}".format(data.num_features))
print("图的边的数量 : {}".format(data.num_edges))
print("边属性的维度 : {}".format(data.num_edge_features))
print("平均节点度 : {}".format(data.num_edges / data.num_nodes))
print("用作训练集的节点数 {}".format(data.train_mask.sum()))
print("用作训练集的节点数占比 {}".format(int(data.train_mask.sum()) / data.num_nodes))
print("此图是否包含孤立的节点 {}".format(data.contains_isolated_nodes()))
print("此图是否包含自环的边 {}".format(data.contains_self_loops()))
print("此图是否是无向图 {}".format(data.is_undirected()))
Data(x=[34, 34], edge_index=[2, 156], y=[34], train_mask=[34])
图的节点数量 : 34
图的节点属性的维度 : 34
同样是节点属性的维度 : 34
图的边的数量 : 156
边属性的维度 : 0
平均节点度 : 4.588235294117647
用作训练集的节点数 4
用作训练集的节点数占比 0.11764705882352941
此图是否包含孤立的节点 False
此图是否包含自环的边 False
此图是否是无向图 True
Planetoid 数据集类的官方文档为torch_geometric.datasets.Planetoid
from torch_geometric.datasets import Planetoid
datasets = Planetoid(root="../../datasets/Cora", name="Cora")
print("数据集图的个数 : {}".format(len(datasets)))
print("数据集分类 : {}".format(datasets.num_classes)) # 7
print("数据集特征 : {}".format(datasets.num_features)) # 1433
如上面代码 可以看到该数据集只有一个图,包含7个分类任务,节点的属性为1433维度
data = datasets[0]
# 查看图的相关信息
print(data)
print("是否是无向图 : {} ".format(data.is_undirected()))
print("可以用作训练集的节点个数 : {} ".format(data.train_mask.sum().item()))
print("可以用作验证集的节点个数 : {} ".format(data.val_mask.sum().item()))
print("可以用作测试集的节点个数 : {} ".format(data.test_mask.sum().item()))
现在我们看到该数据集包含的唯一的图,有2708个节点,节点特征为1433维,有
10556条边,有140个用作训练集的节点,有500个用作验证集的节点,有1000个用 作测试集的节点
假设我们定义好了一个图神经网络模型,其名为Net。在下方的代码中,我们展示了节点分类图数据集在训练过程中的使用。
import torch
import torch.nn as nn
import torch.nn as nn
class Net(nn.Module):
def __init__(self):
pass
def forward(self, x):
pass
def train(self):
pass
使用定义好的模型加载数据
device = "cuda" if torch.cuda.is_available() else "cpu"
# 定义模型, 这个模型仅仅是简单定义, 并不能使用
model = Net().to(device)
# 定义优化函数
optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)
model.train()
for epoch in range(200):
# 重置梯度
optimizer.zero_grad()
# 获取模型输出
out = model(data)
loss = F.nll_loss(out[data.train_mask], data.y[data.train_mask])
loss.backward()
optimizer.step()