pyg安装配置,以及简单的使用测试

最近开始学习图神经网络,发现pyg框架不仅好用,官方文档中的教程也很详细。

今天就分享一下pyg的安装和环境配置,记录自己的踩坑过程,顺便展示一些基本的使用。

一、创建虚拟环境

打开Anaconda Prompt,使用如下命令创建虚拟环境:

conda create -n pyg
conda activate pyg

默认使用的python的就是最新版,我这里是python3.12.4,如果你想用稳定一点的配置,可以选择更低版本(例如3.8)

二、安装pytorch

进入我们创建的虚拟环境后,首先要安装pytorch。

通过pytorch官网(PyTorch),查找我们对应要下载的pytorch版本:

如图,复制对应版本的下载命令,粘贴到Anaconda Prompt命令行。

conda install pytorch torchvision torchaudio pytorch-cuda=11.8 -c pytorch -c nvidia

这里我们选用conda命令进行安装, pip安装其实也行,不过据说conda安装会更好一点。

三、安装pyg和扩展包:

这是pyg的官方文档地址:

(Installation — pytorch_geometric documentation (pytorch-geometric.readthedocs.io)

在其中找到自己环境对应的pyg版本,根据你的pytorch和cuda进行选择,比如我安装的pytorch版本是2.4.0,cuda版本是11.8,那么我就选择如下命令:

pip install torch_geometric

为什么这里没选conda呢?因为我发现conda下载的时候会出现一些问题,比如明明下载好了文件却找不到依赖,官方文档也写了问题的原因:

当然,你要是在linux系统上进行配置,那么直接用conda命令就好了,conda安装命令如下:

conda install pyg -c pyg

如果你和我一样,是用pip安装的pyg,那么可能你还需要下载安装额外的一些拓展库。

拓展库包括了:

pyg-lib:异构 GNN 算子和图采样例程

torch-scatter:加速且高效的稀疏减少

torch-sparse: 支持,详见 hereSparseTensor

torch-cluster:图形聚类例程

torch-spline-conv: SplineConv 支持

官方文档中也给出了一次性全部下载的安装命令:

# Optional dependencies:
pip install pyg_lib torch_scatter torch_sparse torch_cluster torch_spline_conv -f https://data.pyg.org/whl/torch-2.4.0+cu118.html

 如果你不想安装全部拓展库,而是想针对自己的任务去安装其中特定的几个,那么也可以对每个拓展进行单独的安装。

具体方式是,进入pyg提供的whl链接:data.pyg.org/whl/

其中内容如下:

在其中找到自己torch对应的版本和cuda版本。

以我自己为例,我要下载torch2.4.0+cuda11.8的对应版本,于是找到torch-2.4.0+cu118,点进去跳转到另一个链接:data.pyg.org/whl/torch-2.4.0%2Bcu118.html

接下来,我们再去看看自己要下载的哪个拓展包,比如我想下载pyg-lib,那么命令就是:

pip install pyg-lib -f https://data.pyg.org/whl/torch-2.4.0%2Bcu118.html

同理,只需要对其中的包的名字,以及后面的链接做替换,就能在对应版本下安装自己想要的包了 。

四、pyg入门

现在,我们基本配置好了环境,来尝试一下使用pyg吧。

首先我们要知道,pyg是一个用于图类型数据处理和图机器学习的框架,其中内置了很多常见的模型、算子、算法,能让我们像使用pytorch一样创建图神经网络。

参考官方教程,我们先在环境下创建一个pyg_test.py文件,然后声明一下需要的包:

import torch
from torch_geometric.data import Data

 

先来学习如何创建一个图类型的数据,以这张图为例:

 很明显,这是一张无向图,它有三个节点和两条边,其中每个节点的特征向量长度都只有1,在pyg中是这样创建这张图的:

edge_index = torch.tensor([[0, 1, 1, 2],
                           [1, 0, 2, 1]], dtype=torch.long)
x = torch.tensor([[-1], [0], [1]], dtype=torch.float)

data = Data(x=x, edge_index=edge_index)
>>> Data(edge_index=[2, 4], x=[3, 1])

其中edge_index是边索引信息,用的是coo格式的矩阵,注意这里的数据类型是tensor.long;

x是每个节点的特征向量信息;

data是我们最终得到的图数据,在pyg中,它的数据类型是:

<class 'torch_geometric.data.data.Data'>

现在,我们可以对这张图的形状进行一些查看之类的操作。

print(data.keys()) #查看data的参数
>>> ['x', 'edge_index']

print(data['x']) #查看data的特征矩阵
>>> tensor([[-1.0],
            [0.0],
            [1.0]])

for key, item in data: #查看data各个参数的信息
    print(f'{key} found in data')
>>> x found in data
>>> edge_index found in data

'edge_attr' in data #查看参数在data中是否存在
>>> False

data.num_nodes #查看图节点数量
>>> 3

data.num_edges 

#查看data边数量,注意这里之所以是4,是因为这张图是无向图,一条无向边是一条入边和一条出边的组合
>>> 4

data.num_node_features #查看图节点特征的维度
>>> 1

data.has_isolated_nodes() #查看图中是否存在孤立节点
>>> False

data.has_self_loops() #查看图中是否存在自环
>>> False

data.is_directed() #查看图是否是有向图
>>> False

#将数据对象传输到 GPU。
device = torch.device('cuda')
data = data.to(device)

我们可能注意到,上文是用coo格式的边索引矩阵去进行的图创建,实际问题中,我们可能更常用的是图的邻接矩阵格式,那么这二者该如何进行转化呢?

下面是一个将邻接矩阵转化为coo格式的例子:

import torch
import numpy as np
import scipy.sparse as sp
from torch_geometric.data import Data


# 边的连接信息
# 注意,无向图的边要定义两次

A = np.array([[0, 0, 0, 1, 0, 0],
              [0, 0, 1, 1, 0, 1],
              [0, 1, 0, 1, 1, 0],
              [1, 1, 1, 0, 0, 0],
              [0, 0, 1, 0, 0, 1],
              [0, 1, 0, 0, 1, 0],])

edge_index_temp = sp.coo_matrix(A)
print(edge_index_temp)

#将邻接矩阵转化为coo形式
values = edge_index_temp.data  # 边上对应权重值weight
indices = np.vstack((edge_index_temp.row, edge_index_temp.col))#这个结果是一个数组
edge_index_A = torch.LongTensor(indices)  # 将数组转化为tensor.long的形式,这就是我们真正需要的coo形式

print(edge_index_A)
<COOrdinate sparse matrix of dtype 'int32'
	with 14 stored elements and shape (6, 6)>
  Coords	Values
  (0, 3)	1
  (1, 2)	1
  (1, 3)	1
  (1, 5)	1
  (2, 1)	1
  (2, 3)	1
  (2, 4)	1
  (3, 0)	1
  (3, 1)	1
  (3, 2)	1
  (4, 2)	1
  (4, 5)	1
  (5, 1)	1
  (5, 4)	1
tensor([[0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5],
        [3, 2, 3, 5, 1, 3, 4, 0, 1, 2, 2, 5, 1, 4]])

将邻接矩阵转化为coo矩阵,并以tensor.long的格式进行保存,这样我们就可以将其用于创建data对象了。

再来学习一下如何导入内置的数据集: 

pyg中内置了很多图数据集,可以用一行命令直接下载、清洗、导入。

这里,我们选用 ENZYMES 数据集(包含600个图,以及6种分类)作为演示:

from torch_geometric.datasets import TUDataset

dataset = TUDataset(root='/tmp/ENZYMES', name='ENZYMES')

其中,root是数据保存的目录,name是数据集的名字,更详细的信息请移步官方文档,在此只做粗略的介绍。

想要查看数据集相关的信息,做法和前文是一样的。

len(dataset)
>>> 600

dataset.num_classes
>>> 6

dataset.num_node_features
>>> 3

如果我们需要划分数据集,可以直接用分割的方法:

train_dataset = dataset[:540]
>>> ENZYMES(540)

test_dataset = dataset[540:]
>>> ENZYMES(60)

和我们处理别的序列类型数据是一样的。

当然,机器学习过程中肯定是需要随机划分数据集的,一种办法是直接用torch里的方法,torch.randperm()来进行对数据集进行打乱,例如:

perm = torch.randperm(len(dataset))
dataset = dataset[perm]

此外,pyg还内置了一个方法,用于打乱数据集:

dataset = dataset.shuffle()

图数据可视化:

懒得长篇大论了,直接上代码。

import networkx as nx
import matplotlib.pyplot as plt
from torch_geometric.utils import to_networkx
import matplotlib
matplotlib.use('TkAgg')

#用于可视化图数据(二维)
def visualize_graph(data, color):
    G = to_networkx(data, to_undirected=True)
    plt.figure(figsize=(7,7))
    plt.xticks([])
    plt.yticks([])
    nx.draw_networkx(G, pos=nx.spring_layout(G, seed=42), with_labels=False,
                     node_color=color, cmap="Set2")
    plt.show()

把这个函数保存到另一个文件vis.py里,以后要用导入一下就行了。

用这个函数可视化一下我们前面创建的图:

 最后是我自己学习过程中的全部代码:

import torch
import numpy as np
import scipy.sparse as sp
from torch_geometric.data import Data

from vis import visualize_graph
from torch_geometric.datasets import KarateClub


# 边的连接信息
# 注意,无向图的边要定义两次

#print("----------------------")
A = np.array([[0, 0, 0, 1, 0, 0],
              [0, 0, 1, 1, 0, 1],
              [0, 1, 0, 1, 1, 0],
              [1, 1, 1, 0, 0, 0],
              [0, 0, 1, 0, 0, 1],
              [0, 1, 0, 0, 1, 0],])

edge_index_temp = sp.coo_matrix(A)
print(edge_index_temp)

#将邻接矩阵转化为coo形式
values = edge_index_temp.data  # 边上对应权重值weight
indices = np.vstack((edge_index_temp.row, edge_index_temp.col))#这个结果是一个数组
edge_index_A = torch.LongTensor(indices)  # 将数组转化为tensor.long的形式,这就是我们真正需要的coo形式
print(edge_index_A)

#以下的结果不能输入Data,纯粹用于观察图的性质
i = torch.LongTensor(indices)  # 转tensor
v = torch.FloatTensor(values)  # 转tensor
edge_index = torch.sparse_coo_tensor(i, v, edge_index_temp.shape)
print(edge_index)
print("----------------------")

# 节点的属性信息
x = torch.tensor(
    [
        # 每个节点的属性向量维度为1
        [0],
        [1],
        [2],
        [3],
        [4],
        [5],
    ]
)
# 节点的标签信息
y = torch.tensor(
    [
        # 每个节点的标签向量维度为1
        [0],
        [1],
        [1],
        [0],
        [1],
        [0],
    ]
)


# 实例化为一个图结构的数据
data1 = Data(x=x, y=y,edge_index=edge_index_A)
print("type:",type(data1))


#从内置数据集导入
dataset = KarateClub()
data2 = dataset[0]

def show(data):
    # 查看图数据
    print(data)
    # 图数据中包含什么信息
    print(data.keys)
    # 查看节点的属性信息
    print(data['x'])
    # 节点数
    print(data.num_nodes)
    # 边数
    print(data.num_edges)
    # 节点属性向量的维度
    print(data.num_node_features)
    # 图中是否有孤立节点
    print(data.has_isolated_nodes())
    # 图中是否有环
    print(data.has_self_loops())
    # 是否是有向图
    print(data.is_directed())

print("data1:",show(data1))
visualize_graph(data1,data1.y)
#print("data2:",show(data2))
#visualize_graph(data2,data2.y)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值