Task04 数据完全存于内存的数据集类+节点预测与边预测任务实践

参考链接:https://github.com/datawhalechina/team-learning-nlp/blob/master/GNN/Markdown%E7%89%88%E6%9C%AC/6-1-%E6%95%B0%E6%8D%AE%E5%AE%8C%E6%95%B4%E5%AD%98%E4%BA%8E%E5%86%85%E5%AD%98%E7%9A%84%E6%95%B0%E6%8D%AE%E9%9B%86%E7%B1%BB.md
https://github.com/datawhalechina/team-learning-nlp/blob/master/GNN/Markdown%E7%89%88%E6%9C%AC/6-2-%E8%8A%82%E7%82%B9%E9%A2%84%E6%B5%8B%E4%B8%8E%E8%BE%B9%E9%A2%84%E6%B5%8B%E4%BB%BB%E5%8A%A1%E5%AE%9E%E8%B7%B5.md

第一节、数据完全存于内存的数据集类

一、在PyG中自定义数据完全存于内存的数据集类

PyG定义使用数据的一般过程:
1.从网上下载原始数据;
2.对原始数据预处理,为每一个图样本生成一个Data对象;
3.对每一个Data对象执行数据处理,使其转换成新的Data对象;
4.过滤Data对象;
5.保存Data对象到文件;
6.获取Data对象,在每一次获取Data对象时,都先对Data对象做数据变换(于是获取到的是数据变换后的Data对象)。
实际中并非需要严格执行每一个步骤,以上步骤在特定的条件下可以被跳过。

二、InMemoryDataset基类简介

在PyG中,通过继承InMemoryDataset 类来自定义一个数据可全部存储到内存的数据集类。

class InMemoryDataset(root: Optional[str] = None,transform: Optional[Callable] = None, pre_transform:Optional[Callable] = None, pre_filter:Optional[Callable] = None)

InMemoryDataset类初始化方法参数说明:

  • root:字符串类型,存储数据集的文件夹的路径。该文件夹下有两个文件夹:
    一个文件夹记录在raw_dir,它用于存储未处理的文件;
    另一个文件夹记录在processed_dir,它用于存储处理后的数据,以后从此文件夹下加载文件即可获得Data对象。
    注:raw_dir和processed_dir都是属性方法,可以自定义要使用的文件夹。
  • transform 函数:接受Data 对象为参数,对其转换后返回。此函数在每一次数据访问时被调用,主要用于数据增广(Data Augmentation)。
  • pre_transform 函数:接受 Data 对象为参数,对其转换后返回。此函数在样本 Data 对象保存到文件前调用,主要用于只需要做一次的大量预计算。
  • pre_filter 函数:可以在保存前手动过滤掉数据对象。例如:过滤样本类别。

创建一个InMemoryDataset,要实现以下四个基本方法:
1.raw_file_names() —— 这是一个属性方法,返回一个文件名列表,文件在raw_dir 文件夹中,否则调用process() 函数下载文件到raw_dir 文件夹。
2.processed_file_names()——这是一个属性方法,返回一个文件名列表,文件在processed_dir 文件夹中,否则调用process() 函数对样本做预处理,然后保存到processed_dir 文件夹。
3.download() ——将原始数据文件下载到raw_dir 文件夹。
4.process() ——对样本做预处理,然后保存到processed_dir 文件夹。

三、InMemoryDataset数据集类实例

以公开数据集PubMed 为例。PubMed 数据集存储的是文章引用网络,文章对应图的结点,如果两篇文章存在引用关系(无论引用与被引),则这两篇文章对应的结点之间存在边。
该数据集类的使用:
在生成一个PlanetoidPubMed 类的对象时,程序运行流程如下:

  • 首先检查数据原始文件是否已下载:
    检查self.raw_dir 目录下是否存在raw_file_names() 属性方法返回的每个文件,如有文件不存在,则调用download() 方法执行原始文件下载。
  • 其次检查数据是否经过处理:
    1.检查之前对数据做变换的方法:检查self.processed_dir 目录下是否存在pre_transform.pt 文件。
    2.检查之前样本过滤的方法:检查self.processed_dir 目录下是否存在pre_filter.pt 文件。
    3.检查是否存在处理好的数据:检查self.processed_dir 目录下是否存在self.processed_paths 方法返回的所有文件。
  • 最后查看这个数据集。

第二节、节点预测与边预测任务实践

一、目标

能够掌握应对实际中节点预测问题或边预测问题的能力。

二、节点预测任务实践

首先定义GAT(注意力机制层)神经网络模型:

class GAT(torch.nn.Module):
    def __init__(self, num_features,
        hidden_channels_list, num_classes):
        super(GAT, self).__init__()
        torch.manual_seed(12345)
        hns = [num_features] + hidden_channels_list
        conv_list = []
        for idx in range(len(hidden_channels_list)):
            conv_list.append((GATConv(hns[idx],
            hns[idx+1]), 'x, edge_index -> x'))
            conv_list.append(ReLU(inplace=True),)
        self.convseq = Sequential('x, edge_index',conv_list)
        self.linear = Linear(hidden_channels_list[-1],num_classes)
    def forward(self, x, edge_index):
        x = self.convseq(x, edge_index)
        x = F.dropout(x, p=0.5, training=self.training)
        x = self.linear(x)
        return x
  • 神经网络由多个GATConv 顺序相连而构成,因此此模型使用了torch_geometric.nn.Sequential 容器。
  • 通过hidden_channels_list参数来设置每一层GATConv的outchannel,所以hidden_channels_list长度即为GATConv的层数。通过修改hidden_channels_list,就可构造出不同的图神经网络。

完整的代码可见于codes/node_classification.py。

三、边预测任务实践

边预测任务,目标是预测两个节点之间是否存在边。一个图数据集会有节点属性x和边端点edge_index。而edge_index存储的是正样本,没有负样本。为了构建边预测任务,需要生成一些负样本,即采样一些不存在边的节点对作为负样本边,正负样本数量要平衡。要将样本分为训练集、验证集和测试集,进行模型训练,验证和预测。可以通过train_test_split_edges函数随机切分实现。

3.1获取数据集并进行分析

import os.path as osp
from torch_geometric.utils import negative_sampling
from torch_geometric.datasets import Planetoid
import torch_geometric.transforms as T
from torch_geometric.utils import train_test_split_edges

注意:
为什么训练集要包含边的正向与反向,而验证集与测试集都只包含了边的一个方向?
因为,训练集用于训练,训练时一条边的两个端点要互传信息,只考虑一个方向的话,只能由一个端点传信息给另一个端点,而验证集与测试集的边用于衡量检验边预测的准确性,只需考虑一个方向的边即可。

3.2构造边预测图神经网络

import torch
from torch_geometric.nn import GCNConv

class Net(torch.nn.Module):
    def __init__(self, in_channels, out_channels):
        super(Net, self).__init__()
        self.conv1 = GCNConv(in_channels, 128)
        self.conv2 = GCNConv(128, out_channels)

    def encode(self, x, edge_index):
        x = self.conv1(x, edge_index)
        x = x.relu()
        return self.conv2(x, edge_index)

    def decode(self, z, pos_edge_index, neg_edge_index):
        edge_index = torch.cat([pos_edge_index, neg_edge_index], dim=-1)
        return (z[edge_index[0]] * z[edge_index[1]]).sum(dim=-1)

    def decode_all(self, z):
        prob_adj = z @ z.t()
        return (prob_adj > 0).nonzero(as_tuple=False).t()

边预测的神经网络主要由两部分组成:

  • 编码(encode):与节点表征生成一样;
  • 解码(decode):根据边两端节点的表征生成边为真的几率(odds)。

3.3训练边预测图神经网络

步骤如下:
Step1:定义单个epoch的训练过程;
Step2:定义单个epoch验证与测试过程;
Step3:运行完整的训练、验证与测试。

四、总结

通过上面所学的知识,我学会了:
1.更好的理解InMemoryDataset基类、简化的InMemory数据集类和数据集的使用及代码的实现,虽然很多模型是已经构建好的,但是很多代码还是需要多花点时间吸收和实践的。
2.更加深刻的理解节点预测与边预测的运用,以及如何合理的运用数据建立模型。
3.非常感谢DataWhale提供这么好的学习机会以及DW成员们的辛勤付出。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容