使用PyTorch训练GCN做链接预测时遇AttributeError报错求助
问题排查:PyTorch Geometric链接预测中的AttributeError错误
报错信息
AttributeError: 'tuple' object has no attribute 'x'
问题原因
- 数据集拆分返回值处理错误:
RandomLinkSplit执行后会返回包含训练集、验证集、测试集的三元组(train_data, val_data, test_data),但你直接将这个三元组赋值给了data变量,导致后续访问data.x时,实际是在访问tuple的属性,触发报错。 - 节点特征未初始化:原始
Data对象只设置了edge_index和num_nodes,没有定义节点特征x,而GCN模型的输入依赖节点特征,这会引发后续训练错误。 - 链接预测逻辑错误:原代码直接将边索引传入模型获取输出,不符合链接预测的常规逻辑——需要先学习节点嵌入,再通过节点嵌入计算边的预测得分。
修正后的完整代码
数据处理与模型定义
import torch import pandas as pd from torch_geometric.data import Data from torch_geometric.transforms import RandomLinkSplit from torch_geometric.nn import GCNConv # 加载边列表数据 df = pd.read_csv('Alliances_torch.csv') # 提取源节点和目标节点 src = df['Source'].values tgt = df['Target'].values # 计算总节点数 num_nodes = max(max(src), max(tgt)) + 1 # 初始化节点特征:示例用全1向量,可根据业务替换为真实节点属性 x = torch.ones((num_nodes, 1), dtype=torch.float) # 创建完整的Data对象,包含节点特征、边索引和节点数 data = Data(x=x, edge_index=torch.tensor([src, tgt]), num_nodes=num_nodes) # 拆分数据集:正确接收三元组返回值 transform = RandomLinkSplit(num_val=0.1, num_test=0.1) train_data, val_data, test_data = transform(data) # 定义GCN模型 class GCN(torch.nn.Module): def __init__(self, num_features, hidden_size, num_classes): super(GCN, self).__init__() self.conv1 = GCNConv(num_features, hidden_size) self.conv2 = GCNConv(hidden_size, num_classes) def forward(self, x, edge_index): x = self.conv1(x, edge_index) x = torch.relu(x) x = self.conv2(x, edge_index) return x # 初始化模型、优化器和损失函数 model = GCN(num_features=1, hidden_size=16, num_classes=1) optimizer = torch.optim.Adam(model.parameters(), lr=0.01) criterion = torch.nn.BCEWithLogitsLoss()
训练与测试代码
# 训练函数:基于训练集数据执行 def train(): model.train() optimizer.zero_grad() # 先学习全图节点嵌入 out = model(train_data.x, train_data.edge_index) # 提取训练正边两端节点的嵌入,通过点积计算边得分 src_nodes = train_data.train_pos_edge_index[0] tgt_nodes = train_data.train_pos_edge_index[1] edge_scores = (out[src_nodes] * out[tgt_nodes]).sum(dim=1) # 计算损失 loss = criterion(edge_scores, train_data.train_pos_edge_label.float()) loss.backward() optimizer.step() # 测试函数:基于测试集数据评估 def test(): model.eval() with torch.no_grad(): out = model(test_data.x, test_data.edge_index) src_nodes = test_data.test_pos_edge_index[0] tgt_nodes = test_data.test_pos_edge_index[1] edge_scores = (out[src_nodes] * out[tgt_nodes]).sum(dim=1) # 生成预测结果并计算准确率 pred = (edge_scores > 0).flatten() correct = pred.eq(test_data.test_pos_edge_label).sum().item() acc = correct / test_data.test_pos_edge_label.size(0) return acc # 执行50轮训练与测试 for epoch in range(1, 51): train() test_acc = test() print('Epoch {:03d}, Test Acc: {:.4f}'.format(epoch, test_acc))
内容的提问来源于stack exchange,提问作者Oscar Fernando CV
相关产品推荐
相关产品推荐

