Pytorch 几何:张量大小有问题

Posted

技术标签:

【中文标题】Pytorch 几何:张量大小有问题【英文标题】:Pytorch geometric: Having issues with tensor sizes 【发布时间】:2020-12-16 00:30:00 【问题描述】:

这是我第一次使用 Pytorch 和 Pytorch 几何。我正在尝试使用 Pytorch Geometric 创建一个简单的图神经网络。我正在通过遵循 Pytorch 几何文档并扩展 InMemoryDataset 来创建自定义数据集。之后,我将数据集分成大小分别为(3496、437、439)的训练、验证和测试数据集。这些是每个数据集中的图形数量。这是我的简单神经网络

class Net(torch.nn.Module):
def __init__(self):
    super(Net, self).__init__()
    self.conv1 = GCNConv(dataset.num_node_features, 10)
    self.conv2 = GCNConv(10, dataset.num_classes)

def forward(self, data):
    x, edge_index, batch = data.x, data.edge_index, data.batch
    x = self.conv1(x, edge_index)
    x = F.relu(x)
    x = F.dropout(x, training=self.training)
    x = self.conv2(x, edge_index)

    return F.log_softmax(x, dim=1)

我在训练模型时收到此错误,这表明我的输入尺寸存在问题。也许是因为我的批量大小?

RuntimeError: The following operation failed in the TorchScript interpreter.
Traceback of TorchScript (most recent call last):
File "E:\Users\abc\Anaconda3\lib\site-packages\torch_scatter\scatter.py", line 22, in scatter_add
        size[dim] = int(index.max()) + 1
    out = torch.zeros(size, dtype=src.dtype, device=src.device)
    return out.scatter_add_(dim, index, src)
           ~~~~~~~~~~~~~~~~ <--- HERE
else:
    return out.scatter_add_(dim, index, src)
RuntimeError: index 13654 is out of bounds for dimension 0 with size 678

该错误专门发生在神经网络中的这行代码上,

x = self.conv1(x, edge_index)

编辑:添加了有关 edge_index 的更多信息,并更详细地解释了我正在使用的数据。

这是我试图传递的变量的形状

x: torch.Size([678, 43])
edge_index: torch.Size([2, 668])
torch.max(edge_index): tensor(541690)
torch.min(edge_index): tensor(1920)

我正在使用包含 Data(x=node_features, edge_index=edge_index, y=labels) 对象的数据列表。当我将数据集拆分为训练、验证和测试数据集时,我分别在每个数据集中得到(3496, 437, 439) 图表。最初我试图从我的数据集创建一个单一的图表,但我不确定它如何与 Dataloader 和 minibatches 一起使用。

train_loader = DataLoader(train_dataset, batch_size=batch_size)
val_loader = DataLoader(val_dataset, batch_size=batch_size)
test_loader = DataLoader(test_dataset, batch_size=batch_size)

这是从数据框生成图表的代码。我试图创建一个简单的图形,其中只有一些顶点和一些连接它们的边。我可能忽略了一些东西,这就是我遇到这个问题的原因。创建此图时,我尝试遵循 Pytorch 几何文档 (Pytorch Geometric: Creating your own dataset)

def process(self):
        data_list = []

        grouped = df.groupby('EntityId')
        for id, group in grouped:
            node_features = torch.tensor(group.drop(['Labels'], axis=1).values)
            source_nodes = group.index[1:].values
            target_nodes = group.index[:-1].values
            labels = torch.tensor(group.Labels.values)
            edge_index = torch.tensor([source_nodes, target_nodes])

            data = Data(x=node_features, edge_index=edge_index, y=labels)
            data_list.append(data)

        if self.pre_filter is not None:
            data_list = [data for data in data_list if self.pre_filter(data)]

        if self.pre_transform is not None:
            data_list = [self.pre_transform(data) for data in data_list]

        data, slices = self.collate(data_list)
        torch.save((data, slices), self.processed_paths[0])

如果有人可以帮助我在任何类型的数据上创建图表并将其与 GCNConv 一起使用,我将不胜感激。

【问题讨论】:

请记住 scatter_add 执行此操作:pytorch.org/docs/stable/tensors.html#torch.Tensor.scatter_add_ ,我认为问题来自您的 edge_index。您可以编辑以显示 edge_index 的最小值和最大值吗?您能否确认您使用的是具有 678 个节点的图?这感觉有点奇怪,因为图的边通常比顶点多(特别是如果你想对它们执行卷积) @trialNerror 我编辑了我的问题。 好的,所以问题肯定来自您的图表,而不是来自您的网络。在 GCNConv 中,scatter_add 将在某个时刻创建一个长度为 edge_index.max()+1(即 541691)的张量 out。然后它将同时迭代这个张量和x(大小为[678,43])。因此,您的图中存在一个明显的问题:您的边正在索引不存在的顶点。我的意思是,显然最低的顶点索引是 1920,它已经大于 x 维度。那么你能清楚你是如何构建图表的吗? @trialNerror 我添加了生成图表的部分代码。 您能否提供一个示例熊猫数据框(我假设这就是 df 的内容)。不一定是您的实际数据,而是一些具有相同属性(标签,结构......)的数据,以便我们最终拥有某种可重现的代码? :) 【参考方案1】:

我同意@trialNerror - 这是一个数据问题。您的edge_index 应该指的是数据节点,它的max 不应该那么高。既然您不想向我们展示数据并要求“在任何类型的数据上创建图表”,就在这里。

我大部分时间都没有改变你的Net。您可以使用声明的常量来匹配您的数据。

import torch
import torch.nn as nn
import torch.nn.functional as F

from torch_geometric.nn import GCNConv
from torch_geometric.data import Data

num_node_features = 100
num_classes = 2
num_nodes = 678
num_edges = 1500
num_hidden_nodes = 128

x = torch.randn((num_nodes, num_node_features), dtype=torch.float32)
edge_index = torch.randint(low=0, high=num_nodes, size=(2, num_edges), dtype=torch.long)
y = torch.randint(low=0, high=num_classes, size=(num_nodes,), dtype=torch.long)

class Net(torch.nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = GCNConv(num_node_features, num_hidden_nodes)
        self.conv2 = GCNConv(num_hidden_nodes, num_classes)

    def forward(self, data):
        x, edge_index = data.x, data.edge_index
        x = self.conv1(x, edge_index)
        x = F.relu(x)
        x = F.dropout(x, training=self.training)
        x = self.conv2(x, edge_index)

        return F.log_softmax(x, dim=1)

data = Data(x=x, edge_index=edge_index, y=y)

net = Net()

optimizer = torch.optim.Adam(net.parameters(), lr=1e-2)
for i in range(1000):
    output = net(data)
    loss = F.cross_entropy(output, data.y)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    if i % 100 == 0:
        print('Accuracy: ', (torch.argmax(output, dim=1)==data.y).float().mean())

输出

Accuracy:  tensor(0.5059)
Accuracy:  tensor(0.8702)
Accuracy:  tensor(0.9159)
Accuracy:  tensor(0.9233)
Accuracy:  tensor(0.9336)
Accuracy:  tensor(0.9484)
Accuracy:  tensor(0.9602)
Accuracy:  tensor(0.9676)
Accuracy:  tensor(0.9705)
Accuracy:  tensor(0.9749)

(是的,我们可以过度拟合随机数据)

【讨论】:

【参考方案2】:

这绝对是数据问题,我也遇到了同样的问题。特别是要非常小心你的 edge_index'es。同样,我不能在没有看到代码的情况下提出改进建议,但是您的最大节点索引是 541k 但您的 x 大小仅为 678 x 43?!?

我想知道您是否遇到批处理问题。 pytorch_geometric 中的批处理相当奇怪。该模块会将您的所有图表组合成“一个”图表,其中各个图表片段未连接。它将构造适当的新边缘索引,将卷积作为“一个”图进行,然后再次将它们拆分。我想知道您是否正在尝试为它做 pytorch 几何的工作,并在不需要时将所有数据组合成一个批处理。检查文档中的 Batch 类。这是在 pytorch 几何中批量处理事物的唯一方法。

【讨论】:

以上是关于Pytorch 几何:张量大小有问题的主要内容,如果未能解决你的问题,请参考以下文章

Pytorch 张量到 numpy 数组

pytorch torch.empty()函数(返回填充有未初始化数据的张量。 张量的形状由可变的参数大小定义)

PyTorch 张量广播

将 PyTorch 张量转换为 python 列表

『PyTorch』第二弹_张量

PyTorch 中的连接张量