You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GCN训练报错:批量数据索引越界问题的排查与解决

训练GCN时节点索引越界问题的解决

训练GCN模型过程中,按批次选取节点进行训练,节点ID范围为0-999,但原代码直接将节点ID作为索引获取节点相关数据并传入GCN,导致触发索引越界错误,报错信息如下:

RuntimeError: index 332 is out of bounds for dimension 0 with size 64

曾尝试通过节点ID查找其在批次中的索引来获取所需数据,但未找到可行的实现方式,最终通过重构代码解决了问题:构建节点ID到全局索引的映射生成邻接矩阵,改用邻接矩阵与特征矩阵作为GCN输入。

原问题代码

import torch
import torch.nn as nn
import torch.nn.functional as F
from torch_geometric.data import Data
from torch_geometric.nn import GCNConv
from torch_geometric.utils import train_test_split_edges
from torch_geometric.data import DataLoader as loader
import pandas as pd
import torch.optim as optim
from torch.utils.data import Dataset
from torch.nn.utils.rnn import pad_sequence

# feature
class GCN(nn.Module):
    def __init__(self, in_channels, hidden_channels, out_channels):
        super(GCN, self).__init__()
        self.conv1 = GCNConv(in_channels, hidden_channels)
        self.conv2 = GCNConv(hidden_channels, out_channels)

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

class MyDataset(Dataset):
    def __init__(self, nodes_file, edges_file, communities_file, features_file):
        self.nodes_data = pd.read_csv(nodes_file)
        self.edges_data = pd.read_csv(edges_file)
        self.communities_data = pd.read_csv(communities_file)
        self.features_data = pd.read_csv(features_file)

    def __len__(self):
        return len(self.nodes_data)

    def __getitem__(self, idx):
        node_id = self.nodes_data.iloc[idx]['ID']
        node_category = self.nodes_data.iloc[idx]['Category']
        node_community = self.communities_data[self.communities_data['ID'] == node_id]['Community'].values[0]
        edge_source = self.nodes_data.iloc[idx]['ID']
        edge_targets = eval(self.edges_data.iloc[idx]['neighbor'])

        # Get the corresponding features for the current node_id
        node_features = self.features_data[self.features_data['NodeID'] == node_id].iloc[:, 1:].values
        node_features = torch.tensor(node_features, dtype=torch.float)

        # You can process the node, edge, and community data as per your requirements
        # and return them as tensors
        return node_id, node_category, node_community, edge_source, edge_targets, node_features


def custom_collate_fn(batch):
    node_ids, node_categories, node_communities, edge_sources, edge_targets, node_features = zip(*batch)

    # Convert to PyTorch tensors
    node_ids = torch.tensor(node_ids, dtype=torch.long)
    node_categories = torch.tensor(node_categories, dtype=torch.long)
    node_communities = torch.tensor(node_communities, dtype=torch.long)
    edge_targets = [torch.tensor(targets) for targets in edge_targets]

    # Replicate edge_sources to have the same length as edge_targets
    edge_sources_replicated = [torch.tensor([source] * len(targets), dtype=torch.long) for source, targets in zip(edge_sources, edge_targets)]

    return node_ids, node_categories, node_communities, edge_sources_replicated, edge_targets, node_features

nodes_file = 'nodes.csv'
edges_file = 'RWR_features.csv'
communities_file = 'community.csv'
feature_file = 'node_features.csv'

dataset = MyDataset(nodes_file, edges_file, communities_file, feature_file)
dataloader = torch.utils.data.DataLoader(dataset, batch_size=64, shuffle=True, collate_fn=custom_collate_fn)


input_dim = 1000  # Replace with the actual input dimension
hidden_dim = 64
output_dim = 32
num_categories = 3  # Replace with the actual number of node categories
num_communities = 5  # Replace with the actual number of communities
num_epochs = 300

# GCN
gcn_model = GCN(input_dim, hidden_dim, output_dim)

# classify
...

# train loop
for epoch in range(num_epochs):
    for batch_data in dataloader:
        node_ids, node_categories, node_communities, edge_sources_list, edge_targets_list, node_feature = batch_data
        
        # print('node_ids:', node_ids)
        # print('len:', len(node_ids))
        # print('node_categories:', node_categories)
        # print('len:', len(node_categories))
        # print('node_communities:', node_communities)
        # print('len:', len(node_communities))
        # print('edge_sources:', edge_sources)
        # print('len:', len(edge_sources))
        # print('edge_targets', edge_targets)
        # print('len:', len(edge_targets))
        
        node_feature = torch.cat(node_feature, dim=0)
        
        # print('node_feature', node_feature)
        # print('len:', len(node_feature))

        
        edge_sources = torch.cat(edge_sources_list, dim=0)
        edge_targets = torch.cat(edge_targets_list, dim=0)
        # print(edge_sources)
        # print(len(edge_sources))
        # print(edge_targets)
        # print(len(edge_targets))

        edge_index = torch.stack([edge_sources, edge_targets], dim=0)

        # print(edge_index)


        x = gcn_model(node_feature, edge_index)

修复后的代码

import pandas as pd
import numpy as np

def load_data():
    # Load nodes.csv
    nodes_df = pd.read_csv('nodes.csv')
    
    # Load community.csv
    community_df = pd.read_csv('community.csv')
    
    # Load node_features.csv
    node_features_df = pd.read_csv('node_features.csv')
    
    # Load RWR_features.csv
    rwr_features_df = pd.read_csv('RWR_features.csv', usecols=['node', 'neighbor'])
    rwr_features_df['neighbor'] = rwr_features_df['neighbor'].apply(eval)
    rwr_features_df['neighbor'] = rwr_features_df['neighbor'].apply(lambda x: [int(i) for i in x])
    
    # Create mapping from node ID to index
    node_to_index = {node_id: index for index, node_id in enumerate(nodes_df['ID'])}
    
    # Create adjacency matrix
    num_nodes = len(nodes_df)
    adj = np.zeros((num_nodes, num_nodes))
    for _, row in rwr_features_df.iterrows():
        node_id = row['node']
        neighbor_ids = row['neighbor']
        for neighbor_id in neighbor_ids:
            adj[node_to_index[node_id]][node_to_index[neighbor_id]] = 1
            adj[node_to_index[neighbor_id]][node_to_index[node_id]] = 1  # Assuming undirected graph
    
    # Create feature matrix
    feature_columns = node_features_df.columns[1:]  # Exclude the first column (ID)
    feature = node_features_df[feature_columns].values
    
    # Create class labels
    class_label = nodes_df['Category'].values
    
    # Create community labels
    com_label = community_df['Community'].values
    
    # Split indices for train, val, and test sets (You can modify this split ratio as needed)
    num_train = int(num_nodes * 0.6)
    num_val = int(num_nodes * 0.2)
    num_test = num_nodes - num_train - num_val
    
    # Generate random indices for train, val, and test sets
    indices = np.random.permutation(num_nodes)
    train_idx = indices[:num_train]
    val_idx = indices[num_train:num_train + num_val]
    test_idx = indices[num_train + num_val:]
    
    return adj, feature, class_label, com_label, train_idx, val_idx, test_idx

# Usage
adj, feature, class_label, com_label, train_idx, val_idx, test_idx = load_data()

class MyDataset(Dataset):
    def __init__(self, adj, feature, class_label, com_label):
        self.adj = adj
        self.feature = feature
        self.class_label = class_label
        self.com_label = com_label
        
    def __len__(self):
        return len(self.class_label)
    
    def __getitem__(self, idx):
        return idx, self.adj[idx] , self.feature[idx], self.class_label[idx], self.com_label[idx]

将邻接矩阵与特征矩阵传入GCN:

gcn_feature = gcn_model(batch_adj, batch_feature)

内容的提问来源于stack exchange,提问作者Da-qiong

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 20:14:57