图卷积神经网络笔记——第五章:(1)基于PyG库的图卷积的节点分类实战

前面讲解了图卷积的基本理论知识( 链接.),接下来讲解基于PyG库的图卷积的节点分类。
需要说明的是,我是用的是win10系统。

目录

  • 一、环境搭建
      • 1、PyG库简介
      • 2、安装Anaconda并配置虚拟环境
      • 3、安装PyTorch和PyG
          • (1)安装PyTorch
          • (2)安装PyGeometric
  • 二、节点分类实战
      • 1、GCN模型: Y = A ^ W X Y=\hat AWX Y=A^WX
      • 2、GAT模型

一、环境搭建

1、PyG库简介

PyG的全称是 PyTorch Geometric,是一款基于 PyTorch 的几何深度学习框架,可以简单方便的实现图神经网络,也就是说,PyG里面封装了各种方法,比如常见的各种图卷积,直接调用即可。当然在学习PyG之前,要对PyTorch有一定的了解。
PyG官方文档: https://pytorch-geometric.readthedocs.io/en/latest/notes/installation.html.
项目链接: https://github.com/rusty1s/pytorch_geometric.

2、安装Anaconda并配置虚拟环境

官网下载Anaconda: https://www.anaconda.com/products/individual.
然后根据教程: https://zhuanlan.zhihu.com/p/61639212.安装即可。

注意,需要添加环境变量,下面的这两点是Linxu上的添加环境变量

export PATH=/home/你的用户名/anaconda3/bin:$PATH

再更新一下环境变量:

source ~/.bashrc

安装完Anaconda之后,我们添加一些设置,为以后安装别的包方便。
首先打开Anaconda Prompt。

(1)添加清华镜像包管理:

conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/

conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/

添加之后,在安装包的时候将地址展示出来,方便我们查看:

conda config --set show_channel_urls yes

如果不想用添加的源,使用下面的命令删除就行了。

conda config --remove-key channels

(2)conda配置虚拟环境

我们为每个项目创建一个虚拟环境,虽然麻烦,但是这样比较清晰,也方便管理,会减少一些不必要的问题。

创建环境:(这个项目使用的是python3.6)

conda create -n env_name python=3.x

删除环境:

conda remove -n env_name --all

激活环境:

activate env_name # 这个是windows下的
source activate env_name # 这个是linux下的

退出环境:

deactivate env_name # 这个是windows下的
source deactivate env_name # 这个是linux下的

3、安装PyTorch和PyG

(1)安装PyTorch

在安装之前,需要看看对应的版本(去前面给的项目链接看)。

PyTorch 1.5.0对应如下:
图卷积神经网络笔记——第五章:(1)基于PyG库的图卷积的节点分类实战_第1张图片
PyTorch 1.4.0对应如下:
图卷积神经网络笔记——第五章:(1)基于PyG库的图卷积的节点分类实战_第2张图片
这个项目使用如下版本:

PyTorch=1.4.0、torchvision=0.5.0、cudatoolkit=10.1、cudnn=7.6.3
(cudnn基于GPU的加速库,也就是有了它才能在GPU上加速)

然后去PyTorch官网,复制安装命令,如下所示:

图卷积神经网络笔记——第五章:(1)基于PyG库的图卷积的节点分类实战_第3张图片
需要说明的是 -c pytorch 的意思就是说不用我们设置的清华镜像,而是去pytorch官网下载。

由于要指定版本,所以最终使用的命令如下,需要说明的是需要进入前面创建的虚拟环境安装。

conda install pytorch=1.4 torchvision=0.5 cudatoolkit=10.1

然后测试是否安装成功:
输入 python
输入 import torch,没有报错说明安装成功
输入 print(torch.version),查看pytorch的版本。

到这里,pytorch和 torchvision,以及要使用显卡的包cudatoolkit,就安装成功了。
注意:如果不用显卡,用cpu跑则不用安装cudatoolkit。

(2)安装PyGeometric

图卷积神经网络笔记——第五章:(1)基于PyG库的图卷积的节点分类实战_第4张图片
首先去PyGeometric的官网: https://pytorch-geometric.readthedocs.io/en/latest/notes/installation.html.

1、确保至少安装了PyTorch 1.4.0:

python -c "import torch; print(torch.__version__)"
>>> 1.4.0

2、PyTorch安装的CUDA版本:

python -c "import torch; print(torch.version.cuda)"
>>> 10.1

3、安装相关软件包:

pip install torch-scatter==latest+cu101 -f https://pytorch-geometric.com/whl/torch-1.4.0.html
pip install torch-sparse==latest+cu101 -f https://pytorch-geometric.com/whl/torch-1.4.0.html
pip install torch-cluster==latest+cu101 -f https://pytorch-geometric.com/whl/torch-1.4.0.html
pip install torch-spline-conv==latest+cu101 -f https://pytorch-geometric.com/whl/torch-1.4.0.html
pip install torch-geometric

如果是AMD的显卡,显然不能使用cuda,那么只能使用cpu跑了,用CPU时,要注意:pytorch,还有上面的这几个相关依赖包都要是CPU版本的。

4、测试是否安装成功:

输入 python
输入 import torch
输入 import torch_geometric

如果都没有报错,那就是成功了。

我安装完遇到了错误:import torch_geometric,然后报错:OSError: [WinError 127] 找不到指定的模块,我把错误写下来, 链接.

二、节点分类实战

最好先把PyG的官方文档看一遍, PyG官方文档.
还要基本会用PyTorch, PyTorch官方文档.

解释在代码的注释中。

注意,总体要按四步来看:
第一步:准备数据
第二步:定义模型(网络的定义,以及输入、隐藏、输出层数)
第三步:定义损失函数和优化器
第四步:训练+测试(把数据灌入里面)
下面就使用最简单的GCN模型。

1、GCN模型: Y = A ^ W X Y=\hat AWX Y=A^WX

import os
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch_geometric.datasets import Planetoid # PyG处理好的一些数据,如"Cora", "CiteSeer" and "PubMed" ,用Planetoid这个类调用即可
import torch_geometric.nn as pyg_nn


# 第一步:准备数据,load Cora dataset
def get_data(folder="node_classify/cora", data_name="cora"):
    """
    :param folder:保存数据集的根目录。
    :param data_name:数据集的名称
    :return:返回的是一个对象,就是PyG文档里的Data对象,它有一些属性,如 data.x、data.edge_index等
    """
    dataset = Planetoid(root=folder, name=data_name)
    return dataset

# 第二步:定义模型,create the graph cnn model
class GraphCNN(nn.Module):
    def __init__(self, in_c, hid_c, out_c):
        super(GraphCNN, self).__init__()  # 表示子类GraphCNN继承了父类nn.Module的所有属性和方法.
        # 下面这个就是前面讲的GCN,参数只有输入和输出,定义了两层的GCN.
        self.conv1 = pyg_nn.GCNConv(in_channels=in_c, out_channels=hid_c)
        self.conv2 = pyg_nn.GCNConv(in_channels=hid_c, out_channels=out_c)

    def forward(self, data):
        # data.x  data.edge_index
        x = data.x  # [N, C], C为特征的维度
        edge_index = data.edge_index  # [2, E], E为边的数量
        hid = self.conv1(x=x, edge_index=edge_index)  # [N, D], N是节点数量,D是第一层输出的隐藏层的维度
        hid = F.relu(hid)

        out = self.conv2(x=hid, edge_index=edge_index)  # [N, out_c], out_c就是定义的输出,比如分成几类就是几,这里是7

        out = F.log_softmax(out, dim=1)  # [N, out_c],表示输出

        return out


# todo list
class YouOwnGCN(nn.Module):  # 这个不用理会,如果之后想用别的图卷积实现,可以自己在这里写,然后调用
    pass
def main():
    os.environ["CUDA_VISIBLE_DEVICES"] = "0"  # 配置GPU
    cora_dataset = get_data()

    # todo list
    # 这个是自己写的网络的实例化
    my_net = GraphCNN(in_c=cora_dataset.num_node_features, hid_c=13, out_c=cora_dataset.num_classes)
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")   # 检查设备

    my_net = my_net.to(device)  # 模型送入设备
    data = cora_dataset[0].to(device)  # 数据送入设备,也就是一张图
    
    # 第三步:定义损失函数和优化器
    optimizer = torch.optim.Adam(my_net.parameters(), lr=1e-3)  # 优化器
    
    # 第四步:训练+测试
    # model train,这个train就是说归一化等可以重复使用,而设置成eval则就不行了,表示测试
    my_net.train()
    for epoch in range(200):
        optimizer.zero_grad()  # 每次缓存之后清零,不然梯度会累加

        output = my_net(data)  # 预测结果

        loss = F.nll_loss(output[data.train_mask], data.y[data.train_mask])  # 意思就是只取训练集
        loss.backward()

        print("epoch:", epoch + 1, loss.item())
        optimizer.step()  # 优化器

    # model test
    my_net.eval()
    _, prediction = my_net(data).max(dim=1)

    target = data.y

    test_correct = prediction[data.test_mask].eq(target[data.test_mask]).sum().item()
    test_number = data.test_mask.sum().item()

    print("Accuracy of Test Samples:{}%".format(100*test_correct/test_number))

if __name__ == "__main__":
    main()

2、GAT模型

这个和上面的大部分代码都是一样的,不一样的只是定义模型使用的是GAT。

import os
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch_geometric.datasets import Planetoid
import torch_geometric.transforms as T
import torch_geometric.nn as pyg_nn


# load Cora dataset
def get_data(folder="node_classify/cora", data_name="cora"):
    dataset = Planetoid(root=folder, name=data_name, pre_transform=T.KNNGraph(k=6), transform=T.NormalizeFeatures())
    return dataset

# create the graph cnn model
class GraphCNN(nn.Module):
    def __init__(self, in_c, hid_c, out_c):
        super(GraphCNN, self).__init__()  # 表示子类GraphCNN继承了父类nn.Module的所有属性和方法
        self.conv1 = pyg_nn.GATConv(in_channels=in_c, out_channels=hid_c, dropout=0.6)
        self.conv2 = pyg_nn.GATConv(in_channels=hid_c, out_channels=out_c, dropout=0.6, heads=1, concat=True)

    def forward(self, data):
        # data.x  data.edge_index
        x = data.x  # [N, C], C为特征的维度
        edge_index = data.edge_index  # [2, E], E为边的数量
        x = F.dropout(x, p=0.6, training=self.training)
        hid = self.conv1(x=x, edge_index=edge_index)  # [N, D], N是节点数量,D是第一层输出的隐藏层的维度
        hid = F.relu(hid)

        out = self.conv2(x=hid, edge_index=edge_index)  # [N, out_c], out_c就是定义的输出,比如分成几类就是几,这里是7

        out = F.log_softmax(out, dim=1)  # [N, out_c],表示输出

        return out

def main():
    os.environ["CUDA_VISIBLE_DEVICES"] = "0"  # 配置GPU
    cora_dataset = get_data()

    my_net = GraphCNN(in_c=cora_dataset.num_node_features, hid_c=8, out_c=cora_dataset.num_classes)
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")   # 检查设备

    my_net = my_net.to(device)  # 模型送入设备
    data = cora_dataset[0].to(device)  # 数据送入设备,也就是一张图

    optimizer = torch.optim.Adam(my_net.parameters(), lr=5e-3)  # 优化器

    # model train,这个train就是说归一化等可以重复使用,而设置成eval则就不行了,表示测试
    my_net.train()
    for epoch in range(200):
        optimizer.zero_grad()  # 每次缓存之后清零,不然梯度会累加

        output = my_net(data)  # 预测结果

        loss = F.nll_loss(output[data.train_mask], data.y[data.train_mask])  # 意思就是只取训练集
        loss.backward()

        print("epoch", epoch + 1, loss.item())
        optimizer.step()  # 优化器

    # model test
    my_net.eval()
    _, prediction = my_net(data).max(dim=1)

    target = data.y

    test_correct = prediction[data.test_mask].eq(target[data.test_mask]).sum().item()
    test_number = data.test_mask.sum().item()

    print("Accuracy of Test Samples:{}%".format(100*test_correct/test_number))

if __name__ == "__main__":
    main()

GAT运行结果:
图卷积神经网络笔记——第五章:(1)基于PyG库的图卷积的节点分类实战_第5张图片

你可能感兴趣的:(图卷积神经网络笔记,PyTorch,图神经网络,神经网络,深度学习,pytorch)