诸神缄默不语-个人CSDN博文目录
PyTorch Geometric是PyTorch1的几何图形学深度学习扩展库。本文旨在通过介绍PyTorch Geometric(PyG)中常用的方法等内容,为新手提供一个PyG的入门教程。
官方文档地址
一个教程中提供的可视化函数visualize()
%matplotlib inline
import torch
import networkx as nx
import matplotlib.pyplot as plt
# Visualization function for NX graph or PyTorch tensor
def visualize(h, color, epoch=None, loss=None):
plt.figure(figsize=(7,7))
plt.xticks([])
plt.yticks([])
if torch.is_tensor(h): #可视化神经网络运行中间结果
h = h.detach().cpu().numpy()
plt.scatter(h[:, 0], h[:, 1], s=140, c=color, cmap="Set2")
if epoch is not None and loss is not None:
plt.xlabel(f'Epoch: {
epoch}, Loss: {
loss.item():.4f}', fontsize=16)
else: #可视化图
nx.draw_networkx(G, pos=nx.spring_layout(G, seed=42), with_labels=False,
node_color=color, cmap="Set2")
plt.show()
torch_geometric.datasets官方文档
(官方文档中说是154条边(指无向图边×2的数目),应该是写错了,我已经在GitHub项目的论坛里面提问了,等解答ing)
举例:class KarateClub(transform=None)
2
维基百科:Zachary’s karate club
原论文:
An Information Flow Model for Conflict and Fission in Small Groups 34个节点,78条无向无权边
Semi-Supervised Classification with Graph Convolutional Networks 基于modularity-based clustering将节点聚合为4类,聚合基于每一类的一个有标签节点(也就是一共有4个真实值节点)
数据集中只有一张图。该图描述了一个空手道俱乐部会员的社交关系,以34名会员作为节点,如果两位会员在俱乐部之外仍保持社交关系,则在节点间增加一条边。
每个节点具有一个34维的特征向量。节点类型class共有4类,分别代表会员所属的社区community。
获取数据示例代码:
from torch_geometric.datasets import KarateClub
dataset = KarateClub()
print(f'Dataset: {
dataset}:')
print('======================')
print(f'Number of graphs: {
len(dataset)}')
print(f'Number of features: {
dataset.num_features}')
print(f'Number of classes: {
dataset.num_classes}')
输出结果:
Dataset: KarateClub():
======================
Number of graphs: 1
Number of features: 34
Number of classes: 4
可以通过索引的方式获取Dataset中的图,示例:data=dataset[0]
返回值是torch_geometric.data.data.Data
类的实例
Data类的文档:torch_geometric.data.Data
是PyG中表示图的Python object,可含多种属性,包括但不限于:
x (Tensor) - 节点特征矩阵,形状为: [num_nodes, num_node_features]
edge_index (LongTensor) - Graph connectivity in COO format (coordinate format)3,形状为 [2, num_edges]
举例来说,可以是一个由两个元素组成的tuple,第一个元素是由边起点组成的list,第二个元素是由边终点组成的list(如果是无向图,两种方向都会出现)
y (Tensor) - 图或节点的目标矩阵
以KarateClub图为例,将其打印出来为:Data(edge_index=[2, 156], train_mask=[34], x=[34, 34], y=[34])
train_mask是训练集的mask,是一个元素为布尔值的向量。4描述我们已知哪些节点的真实社区(在本示例中有4个节点)。
x是一个有34个观测的34维特征向量矩阵,y是有34个观测的一维目标向量矩阵。
示例代码(仍以KarateClub的data举例):
print(f'Number of nodes: {
data.num_nodes}')
print(f'Number of edges: {
int(data.num_edges/2)}')
print(f'Average node degree: {
data.num_edges / data.num_nodes:.2f}') #2E/N
print(f'Number of training nodes: {
data.train_mask.sum()}')
print(f'Training node label rate: {
int(data.train_mask.sum()) / data.num_nodes:.2f}')
print(f'Contains isolated nodes: {
data.contains_isolated_nodes()}')
print(f'Contains self-loops: {
data.contains_self_loops()}')
print(f'Is undirected: {
data.is_undirected()}')
输出结果:
Number of nodes: 34
Number of edges: 78
Average node degree: 4.59
Number of training nodes: 4
Training node label rate: 0.12
Contains isolated nodes: False
Contains self-loops: False
Is undirected: True
示例代码:
from torch_geometric.utils import to_networkx
G = to_networkx(data, to_undirected=True)
对其进行可视化visualize(G, color=data.y)
:
举例:GCN
文档地址:torch_geometric.nn.GCNConv(in_channels,out_channels)
forward(x: torch.Tensor, edge_index: Union[torch.Tensor, torch_sparse.tensor.SparseTensor], edge_weight: Optional[torch.Tensor] = None)
原论文:Semi-Supervised Classification with Graph Convolutional Networks
示例代码——建立模型:
import torch
from torch.nn import Linear
from torch_geometric.nn import GCNConv
class GCN(torch.nn.Module):
def __init__(self):
super(GCN, self).__init__()
torch.manual_seed(12345)
self.conv1 = GCNConv(dataset.num_features, 4)
self.conv2 = GCNConv(4, 4)
self.conv3 = GCNConv(4, 2)
self.classifier = Linear(2, dataset.num_classes)
def forward(self, x, edge_index):
h = self.conv1(x, edge_index)
h = h.tanh()
h = self.conv2(h, edge_index)
h = h.tanh()
h = self.conv3(h, edge_index)
h = h.tanh() # Final GNN embedding space.
# Apply a final (linear) classifier.
out = self.classifier(h)
return out, h
model = GCN()
print(model)
这个模型可以聚合节点的3-hop邻居信息。
模型作为表示学习输出h,降维过程为34→4→4→2
半监督学习训练:
import time
model = GCN()
criterion = torch.nn.CrossEntropyLoss() # Define loss criterion.
optimizer = torch.optim.Adam(model.parameters(), lr=0.01) # Define optimizer.
def train(data):
optimizer.zero_grad() # Clear gradients.
out, h = model(data.x, data.edge_index) # Perform a single forward pass.
loss = criterion(out[data.train_mask], data.y[data.train_mask]) # Compute the loss solely based on the training nodes.
loss.backward() # Derive gradients.
optimizer.step() # Update parameters based on gradients.
return loss, h
for epoch in range(401):
loss, h = train(data)
# Visualize the node embeddings every 10 epochs
if epoch % 10 == 0:
visualize(h, color=data.y, epoch=epoch, loss=loss)
time.sleep(0.3)
每次可视化都有输出结果。最后一次输出结果(从图中可以看出,3层GCNConv构成的神经网络模型可以比较好地将四类节点区分开来):
PyTorch包入门可见我之前写的博文:60分钟闪击速成PyTorch(Deep Learning with PyTorch: A 60 Minute Blitz)学习笔记 ↩︎
该数据集详解可见我写的博文:图数据集Zachary‘s karate club network详解,包括其在NetworkX、PyG上的获取和应用方式 ↩︎
COO format是对于稀疏矩阵的一种常用储存格式。在PyG中edge_index就是将Data的邻接矩阵(常常是一个稀疏矩阵)表示为COO format。
参考资料:稀疏矩阵的主要存储格式 ↩︎
关于mask是什么,我上网查了一下,好像是一个用于NLP、RNN、Bert这些领域的专业术语?我还看到了一个论文:Node Masking。
没看懂。 ↩︎
NetworkX是另一个在Python图挖掘领域常用的包,入门可见我之前写的博文:NetworkX入门教程 ↩︎