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

数据完整存储与内存的数据集类

使用数据集的一般过程

  1. 从网络上下载数据原始文件;
  2. 对数据原始文件做处理,为每一个图样本生成一个Data对象
  3. 对每一个Data对象执行数据处理,使其转换成新的Data对象;
  4. 过滤Data对象;
  5. 保存Data对象到文件;
  6. 获取Data对象,在每一次获取Data对象时,都先对Data对象做数据变换(于是获取到的是数据变换后的Data对象)。

InMemoryDataset基类简介

class PlanetoidPubMed(InMemoryDataset):
    r""" 节点代表文章,边代表引用关系。
   		 训练、验证和测试的划分通过二进制掩码给出。
    参数:
        root (string): 存储数据集的文件夹的路径
        transform (callable, optional): 数据转换函数,每一次获取数据时被调用。
        pre_transform (callable, optional): 数据转换函数,数据保存到文件前被调用。
    """

    url = 'https://github.com/kimiyoung/planetoid/raw/master/data'


    def __init__(self, root, transform=None, pre_transform=None):

        super(PlanetoidPubMed, self).__init__(root, transform, pre_transform)
        self.data, self.slices = torch.load(self.processed_paths[0])

    @property
    def raw_dir(self):
        return osp.join(self.root, 'raw')

    @property
    def processed_dir(self):
        return osp.join(self.root, 'processed')

    @property
    def raw_file_names(self):
        names = ['x', 'tx', 'allx', 'y', 'ty', 'ally', 'graph', 'test.index']
        return ['ind.pubmed.{}'.format(name) for name in names] # 写上数据集原始文件有哪些

    @property
    def processed_file_names(self):
        return 'data.pt'    # 处理过的数据要保存在哪些文件里,在此例子中只有data.pt

    def download(self):
        for name in self.raw_file_names:
            download_url('{}/{}'.format(self.url, name), self.raw_dir)  # 我们实现下载数据到self.raw_dir文件夹的逻辑

    def process(self):
        data = read_planetoid_data(self.raw_dir, 'pubmed')
        data = data if self.pre_transform is None else self.pre_transform(data)
        torch.save(self.collate([data]), self.processed_paths[0])

    def __repr__(self):
        return '{}()'.format(self.name)

在我们生成一个PlanetoidPubMed类的对象时,程序运行流程如下:

  1. 检查数据原始文件是否已下载
  2. 其次,检查数据是否经过处理

节点预测与边预测任务实践

节点预测

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

该例子是由多个GAT相连接,用在PlanetoidPubMed数据集上,准确率为0.7750.

边预测

  • 边预测任务,目标是预测两个节点之间是否存在边
  • 拿到一个图数据集,我们有节点属性x,边端点edge_index。edge_index存储的便是正样本。为了构建边预测任务,我们需要生成一些负样本,即采样一些不存在边的节点对作为负样本边,正负样本数量应平衡。此外要将样本分为训练集、验证集和测试集三个集合。
  • PyG中为我们提供了现成的采样负样本边的方法,train_test_split_edges(data, val_ratio=0.05, test_ratio=0.1)
  • 该函数将自动地采样得到负样本,并将正负样本分成训练集、验证集和测试集三个集合。它用train_pos_edge_index、train_neg_adj_mask、val_pos_edge_index、val_neg_edge_index、test_pos_edge_index和test_neg_edge_index,六个属性取代edge_index属性。
  • train_neg_adj_mask与其他属性格式不同,其实该属性在后面并没有派上用场,后面我们仍然需要进行一次训练集负样本采样
  • 训练集应该包含边的正向与反向,验证集与测试集都只需要包含了边的一个方向

网络结构如下:

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()

运用在cora数据集上,test准确率为0.8883

实践问题一:尝试使用PyG中的不同的网络层去代替GCNConv,以及不同的层数和不同的out_channels,来实现节点分类任务。

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((GCNConv(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

model = GAT(num_features=dataset.num_features, hidden_channels_list=[200, 150, 100], num_classes=dataset.num_classes).to(device)

实践问题二:在边预测任务中,尝试用torch_geometric.nn.Sequential容器构造图神经网络

class Net(torch.nn.Module):
    def __init__(self, in_channels, out_channels):
        super(Net, self).__init__()
        conv_list = []
        conv_list.append((GCNConv(in_channels, 128), 'x, edge_index -> x'))
        conv_list.append(ReLU(inplace=True),)
        conv_list.append((GCNConv(128, out_channels), 'x, edge_index -> x'))
        self.convseq = Sequential('x, edge_index', conv_list)

    def encode(self, x, edge_index):
        return self.convseq(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()

思考问题三:如下方代码所示,我们以data.train_pos_edge_index为实际参数来进行训练集负样本采样,但这样采样得到的负样本可能包含一些验证集的正样本与测试集的正样本,即可能将真实的正样本标记为负样本,由此会产生冲突。但我们还是这么做,这是为什么?
可能是因为验证集和测试集比较小?

使用优化算法,以优化VMD算法的惩罚因子惩罚因子 (α) 和分解层数 (K)。 1、将量子粒子群优化(QPSO)算法与变分模态分解(VMD)算法结合 VMD算法背景: VMD算法是一种自适应信号分解算法,主要用于分解信号为不同频率带宽的模态。 VMD的关键参数包括: 惩罚因子 α:控制带宽的限制。 分解层数 K:决定分解出的模态数。 QPSO算法背景: 量子粒子群优化(QPSO)是一种基于粒子群优化(PSO)的一种改进算法,通过量子行为模型增强全局搜索能力。 QPSO通过粒子的量子行为使其在搜索空间中不受位置限制,从而提高算法的收敛速度与全局优化能力。 任务: 使用QPSO优化VMD中的惩罚因子 α 和分解层数 K,以获得信号分解的最佳效果。 计划: 定义适应度函数:适应度函数根据VMD分解的效果来定义,通常使用重构信号的误差(例如均方误差、交叉熵等)来衡量分解的质量。 初始化QPSO粒子:定义粒子的位置和速度,表示 α 和 K 两个参数。初始化时需要在一个合理的范围内为每个粒子分配初始位置。 执行VMD分解:对每一组 α 和 K 参数,运行VMD算法分解信号。 更新QPSO粒子:使用QPSO算法更新粒子的状态,根据适应度函数调整粒子的搜索方向和位置。 迭代求解:重复QPSO的粒子更新步骤,直到满足终止条件(如适应度函数达到设定阈值,或最大迭代次数)。 输出优化结果:最终,QPSO算法会返回一个优化的 α 和 K,从而使VMD分解效果最佳。 2、将极光粒子(PLO)算法与变分模态分解(VMD)算法结合 PLO的优点与适用性 强大的全局搜索能力:PLO通过模拟极光粒子的运动,能够更高效地探索复杂的多峰优化问题,避免陷入局部最优。 鲁棒性强:PLO在面对高维、多模态问题时有较好的适应性,因此适合海上风电时间序列这种非线性、多噪声的数据。 应用场景:PLO适合用于优化VMD参数(α 和 K),并将其用于风电时间序列的预测任务。 进一步优化的建议 a. 实现更细致的PLO更新策略,优化极光粒子的运动模型。 b. 将PLO优化后的VMD应用于真实的海上风电数据,结合LSTM或XGBoost等模型进行风电功率预测
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值