Invalid edge ID Error when training using GatedGraphConv

Hello everyone,

When training a model with GatedGraphConv for some reason DGLError: Invalid edge rises.

Model:

class GatedGNNModel(torch.nn.Module):
    def __init__(self, in_dim, hidden_dim, n_steps, n_etypes, n_classes):
        super(GatedGNNModel, self).__init__()
        self.in_dim = in_dim
        self.out_dim = hidden_dim
        self.n_steps = n_steps
        self.n_etypes = n_etypes
        self.n_classes = n_classes

        # Define topology and functions

        # GatedGraphConv Layer
        self.g_conv = dgl.nn.pytorch.GatedGraphConv(self.in_dim, self.out_dim, self.n_steps, n_etypes)

        # Linear (Classification Layer)
        self.output_layer = torch.nn.Linear(self.out_dim, self.n_classes)

        # Functions and properties
        self.activation = torch.nn.LeakyReLU()
        self.dropout = torch.nn.Dropout(0.2)

    def forward(self, g, h, e_list, labels):
        labels = labels.cuda()
        g = g.to(torch.device("cuda"))
        _h = h.cuda()
        _e_list = etypes.cuda()
        h = torch.nn.functional.leaky_relu(self.g_conv(g, _h, _e_list))
        h = self.dropout(h)
        g.ndata['h'] = _h
        readout_features = dgl.max_nodes(g, 'h')
        logits = torch.nn.functional.leaky_relu(self.output_layer(readout_features))
        preds = torch.argmax(logits, -1)
        _labels = labels.cuda()
        loss = torch.nn.functional.cross_entropy(logits, _labels)
        
        return loss, preds

Training loop:

for epoch in range(50):
    
    model.train()
    for batched_graph, labels in train_dataloader:
        feats = batched_graph.ndata['node_feat']
        etypes = batched_graph.edata['edge_type']
        opt.zero_grad()
        loss, preds = model(batched_graph, feats, etypes, labels)
        loss.backward()
        opt.step()
        
    
    with torch.no_grad():
        y_preds = []
        y_trues = []
        
        model.eval()
        for v_graph, v_label in test_dataloader:
            v_feats = v_graph.ndata['node_feat']
            v_etypes = v_graph.edata['edge_type']
            v_loss, v_preds = model(v_graph, v_feats, v_etypes, v_label)
            y_pred = preds.cpu().tolist()
            
            y_preds.append(y_pred[0])
            y_trues.append(v_label[0])
    

    f1 = f1_score(y_trues, y_preds, average='macro')
    acc = accuracy_score(y_trues, y_preds)
    
    print("="*100)
    print(f"Epoch {epoch}")
    print("Dev F1 %.2f" % f1 * 100)
    print("Dev Acc %.2f" % acc * 100)
    print("="*100)
    

As for the dataset, it consists of networkx graphs (where some are multigraphs). I have converted each raw graph as follows (then save the whole set in a .bin using dgl.save_graphs):

dgl.from_networkx(nx_graph, node_attrs=['node_feat'], edge_attrs=['edge_type'], edge_id_attr_name='eid')

Where node_feat is a 769-dim tensor and edge_type is a tensor that contains the types of edges (values between 0 and 9)

Error:

---------------------------------------------------------------------------
DGLError                                  Traceback (most recent call last)
Input In [58], in <cell line: 1>()
     19 v_feats = v_graph.ndata['node_feat']
     20 v_etypes = v_graph.edata['edge_type']
---> 21 v_loss, v_preds = model(v_graph, v_feats, v_etypes, v_label)
     22 y_pred = preds.cpu().tolist()
     24 y_preds.append(y_pred[0])

File /usr/local/lib/python3.9/dist-packages/torch/nn/modules/module.py:1130, in Module._call_impl(self, *input, **kwargs)
   1126 # If we don't have any hooks, we want to skip the rest of the logic in
   1127 # this function, and just call forward.
   1128 if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks
   1129         or _global_forward_hooks or _global_forward_pre_hooks):
-> 1130     return forward_call(*input, **kwargs)
   1131 # Do not call functions when jit is used
   1132 full_backward_hooks, non_full_backward_hooks = [], []

Input In [54], in GatedGNNModel.forward(self, g, h, e_list, labels)
     25 _h = h.cuda()
     26 _e_list = etypes.cuda()
---> 27 h = torch.nn.functional.leaky_relu(self.g_conv(g, _h, _e_list))
     28 h = self.dropout(h)
     29 g.ndata['h'] = _h

File /usr/local/lib/python3.9/dist-packages/torch/nn/modules/module.py:1130, in Module._call_impl(self, *input, **kwargs)
   1126 # If we don't have any hooks, we want to skip the rest of the logic in
   1127 # this function, and just call forward.
   1128 if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks
   1129         or _global_forward_hooks or _global_forward_pre_hooks):
-> 1130     return forward_call(*input, **kwargs)
   1131 # Do not call functions when jit is used
   1132 full_backward_hooks, non_full_backward_hooks = [], []

File /usr/local/lib/python3.9/dist-packages/dgl/nn/pytorch/conv/gatedgraphconv.py:161, in GatedGraphConv.forward(self, graph, feat, etypes)
    158     eids = th.nonzero(
    159         etypes == i, as_tuple=False).view(-1).type(graph.idtype)
    160     if len(eids) > 0:
--> 161         graph.apply_edges(
    162             lambda edges: {
    163                 'W_e*h': self.linears[i](edges.src['h'])},
    164             eids
    165         )
    166 graph.update_all(fn.copy_e('W_e*h', 'm'), fn.sum('m', 'a'))
    167 a = graph.ndata.pop('a')  # (N, D)

File /usr/local/lib/python3.9/dist-packages/dgl/heterograph.py:4460, in DGLHeteroGraph.apply_edges(self, func, edges, etype, inplace)
   4458     edata = core.invoke_gsddmm(g, func)
   4459 else:
-> 4460     edata = core.invoke_edge_udf(g, eid, etype, func)
   4462 if self._graph.number_of_etypes() == 1 or etype is not None:
   4463     self._set_e_repr(etid, eid, edata)

File /usr/local/lib/python3.9/dist-packages/dgl/core.py:76, in invoke_edge_udf(graph, eid, etype, func, orig_eid)
     74     edata = graph._edge_frames[etid]
     75 else:
---> 76     u, v = graph.find_edges(eid)
     77     edata = graph._edge_frames[etid].subframe(eid)
     78 if len(u) == 0:

File /usr/local/lib/python3.9/dist-packages/dgl/heterograph.py:3168, in DGLHeteroGraph.find_edges(self, eid, etype)
   3166     max_eid = F.as_scalar(F.max(eid, 0))
   3167     if max_eid >= self.num_edges(etype):
-> 3168         raise DGLError('Invalid edge ID {:d}'.format(max_eid))
   3170 if len(eid) == 0:
   3171     empty = F.copy_to(F.tensor([], self.idtype), self.device)

DGLError: Invalid edge ID 9

Thank you

Hi @mootez, could you provide a script that can reproduce your error? So that we can better help you find the problem.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.