我正在做一个班级项目。我们正在尝试使用 Pytorch Geometric 和 GNN 来检测 Kaggle 上 IBM 数据集中的洗钱行为。我们所做的是创建一个带有edge_index、edge_attr 和edge_label 的Pytorch 几何数据对象,然后将数据对象拆分为train、val 和test 数据集。然而,数据集似乎没有正确分割。例如,edge_label是plit,但edge_index和edge_attr不是。
此外,我遇到的另一个问题是它一直说边缘索引在训练或验证期间超出范围。有时,它有效,但不一致。我不确定这是由分裂引起的。我也尝试创建一些手动随机分割,但索引问题仍然发生。
请帮忙!谢谢!
`# Convert to PyTorch tensors with correct dtypes
torch_edges_labels = torch.tensor(df.select("Is Laundering").collect(), dtype=torch.long).to(device) # Changed to torch.long
torch_edges = torch.tensor(edges.collect(), dtype=torch.long).t().contiguous().to(device)
torch_edges_features = torch.tensor(df_features.collect(), dtype=torch.float).to(device)
# # Create PyTorch Geometric Data object
pyGData = Data(
num_nodes=nodes.count(),
edge_index=torch_edges,
edge_attr=torch_edges_features,
edge_label=torch_edges_labels
).to(device)
# Initialize split transform with proper settings
split = transforms.RandomLinkSplit(
is_undirected=True,
split_labels=False,
num_val=0.2,
num_test=0.2,
)
# Perform split with proper error handling
try:
train_data, val_data, test_data = split(pyGData)`
每个训练、验证和测试数据集中的edge_index、edge_attr和edge_label应该正确分割。 此外,这可能有助于解决训练和评估期间边缘索引越界的问题。
RandomLinkSplit 专为链接预测任务而设计,可能会引入负采样等复杂性。 RandomLinkSplit 的工作原理是将边分成一个用于训练的子集、一个用于验证的子集以及最后一个用于测试的子集。它可选地具有负采样。 RandomSplitLink调整每个分割中的edge_index以包含分配给分割的边,但是,它不处理edge_attr或自定义_edge_label,如果split_label = True,它将相应地分割标签。尝试手动将数据拆分为训练集、验证集和测试集,以确保拆分edge_index、edge_attr 和edge_label。
示例:
相关进口:
import torch
from torch_geometric.data import Data
from sklearn.model_selection import train_test_split
from collections import Counter
手动拆分组件。
# Generate edge indices for splitting
num_edges = pyGData.edge_index.size(1)
edge_indices = torch.arange(num_edges)
# Convert tensors to numpy for sklearn
edge_indices_np = edge_indices.cpu().numpy()
edge_label_np = pyGData.edge_label.cpu().numpy()
# First split: Train vs Temp (Val + Test)
train_idx, temp_idx, y_train, y_temp = train_test_split(
edge_indices_np,
edge_label_np,
test_size=0.4, # 60% train, 40% temp
random_state=42,
stratify=edge_label_np
)
# Second split: Validation vs Test
val_size = 0.5 # Since temp is 40%, val and test each get 20%
val_idx, test_idx, y_val, y_test = train_test_split(
temp_idx,
y_temp,
test_size=0.5,
random_state=42,
stratify=y_temp
)
# Convert back to tensors
train_idx = torch.tensor(train_idx, dtype=torch.long)
val_idx = torch.tensor(val_idx, dtype=torch.long)
test_idx = torch.tensor(test_idx, dtype=torch.long)
将edge_index、edge_attr和edge_label与上面获得的索引分开:
train_data = Data(
num_nodes=num_nodes,
edge_index=pyGData.edge_index[:, train_idx],
edge_attr=pyGData.edge_attr[train_idx],
edge_label=pyGData.edge_label[train_idx]
).to(device)
val_data = Data(
num_nodes=num_nodes,
edge_index=pyGData.edge_index[:, val_idx],
edge_attr=pyGData.edge_attr[val_idx],
edge_label=pyGData.edge_label[val_idx]
).to(device)
test_data = Data(
num_nodes=num_nodes,
edge_index=pyGData.edge_index[:, test_idx],
edge_attr=pyGData.edge_attr[test_idx],
edge_label=pyGData.edge_label[test_idx]
).to(device)
即使禁用负采样(add_negative_train_samples=False 等),RandomLinkSplit 本质上也会从训练集中删除边缘并将其分配给验证集和测试集。
仍然可以使用RandomLinkSplit,但需要手动拆分edge_attr以进行匹配,因此首选手动。