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 几何:张量大小有问题的主要内容,如果未能解决你的问题,请参考以下文章