-->

signed

QiShunwang

“诚信为本、客户至上”

PyTorch Geometric (PyG) 入门教程

2021/6/3 18:41:19   来源:

诸神缄默不语-个人CSDN博文目录

PyTorch Geometric是PyTorch1的几何图形学深度学习扩展库。本文旨在通过介绍PyTorch Geometric(PyG)中常用的方法等内容,为新手提供一个PyG的入门教程。
官方文档地址

文章目录

  • 1. 可视化
  • 2. 数据集:以KarateClub为例
  • 3. Data
    • 3.1 Data的重要属性和方法
  • 4. 应用GNN
  • 5. 除文中已列出的PyG官方文档外,其他使用到的参考资料

1. 可视化

一个教程中提供的可视化函数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()

2. 数据集:以KarateClub为例

torch_geometric.datasets官方文档

举例:class KarateClub(transform=None)
维基百科:Zachary’s karate club
原论文:Semi-Supervised Classification with Graph Convolutional Networks

数据集中只有一张图。该图描述了一个空手道俱乐部会员的社交关系,以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类的实例

3. 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)2,形状为 [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,是一个元素为布尔值的向量。3描述我们已知哪些节点的真实社区(在本示例中有4个节点)。
x是一个有34个观测的34维特征向量矩阵,y是有34个观测的一维目标向量矩阵。

3.1 Data的重要属性和方法

  1. num_nodes 图中的节点数
  2. num_edges 图中的边数(无向图会返回两个方向的边数,即唯一边数的两倍)
  3. contains_isolated_nodes() 图中是否含有孤立点
  4. contains_self_loops() 图中是否含有自环
  5. is_undirected() 图是不是无向的

示例代码(仍以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

  1. 转换为NetworkX的Graph或DiGraph格式4:torch_grometric.utils.to_networkx(data,to_undirected=False)
    data是Data格式数据。
    如果to_undirected置True就返回Graph,反之返回DiGraph。

示例代码:

from torch_geometric.utils import to_networkx
G = to_networkx(data, to_undirected=True)

对其进行可视化visualize(G, color=data.y)在这里插入图片描述

4. 应用GNN

举例: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构成的神经网络模型可以比较好地将四类节点区分开来):在这里插入图片描述

5. 除文中已列出的PyG官方文档外,其他使用到的参考资料

  1. cs224w课程的colab0
    1. 原始文件下载地址
    2. 我上传到GitHub的文件网址,已添加过部分私人注释

  1. PyTorch包入门可见我之前写的博文:60分钟闪击速成PyTorch(Deep Learning with PyTorch: A 60 Minute Blitz)学习笔记 ↩︎

  2. COO format是对于稀疏矩阵的一种常用储存格式。在PyG中edge_index就是将Data的邻接矩阵(常常是一个稀疏矩阵)表示为COO format。
    参考资料:稀疏矩阵的主要存储格式 ↩︎

  3. 关于mask是什么,我上网查了一下,好像是一个用于NLP、RNN、Bert这些领域的专业术语?我还看到了一个论文:Node Masking。
    没看懂。 ↩︎

  4. NetworkX是另一个在Python图挖掘领域常用的包,入门可见我之前写的博文:NetworkX入门教程 ↩︎