Edge Classification with one node type

I followed the instructions from the error:

AssertionError: The HeteroNodeDataView has only one node type. please pass a tensor directly

Therefore, I changed

node_features = graph.nodes[node_type].data['feature']
labels = graph.edges[target_edge].data['label']
train_mask = graph.edges[target_edge].data['train_mask']
feats = {'node': node_features}
opt = torch.optim.Adam(model.parameters())
for epoch in range(100):
    model.train()
    pred = model(graph, feats, target_edge)
    # pred = model(graph, node_features, target_edge)
    loss = ((pred[train_mask] - labels[train_mask]) ** 2).mean()
    opt.zero_grad()
    loss.backward()
    opt.step()
    print(loss.item())

to

node_features = graph.nodes[node_type].data['feature']
labels = graph.edges[target_edge].data['label']
train_mask = graph.edges[target_edge].data['train_mask']
opt = torch.optim.Adam(model.parameters())
for epoch in range(100):
    model.train()
    pred = model(graph, node_features, target_edge)
    loss = ((pred[train_mask] - labels[train_mask]) ** 2).mean()
    opt.zero_grad()
    loss.backward()
    opt.step()
    print(loss.item())

But now I get the following error

RuntimeError: Tensor.__contains__ only supports Tensor or scalar, but you passed in a <class 'str'>.

This is caused by

    def __contains__(self, element):
        r"""Check if `element` is present in tensor

        Args:
            element (Tensor or scalar): element to be checked
                for presence in current tensor"
        """
        if has_torch_function_unary(self):
            return handle_torch_function(Tensor.__contains__, (self,), self, element)
        if isinstance(element, (torch.Tensor, Number)):
            # type hint doesn't understand the __contains__ result array
            return (element == self).any().item()  # type: ignore[union-attr]

        raise RuntimeError(
            "Tensor.__contains__ only supports Tensor or scalar, but you passed in a %s." %
            type(element)
        )

where element is ‘node’
This is triggered by the fact that the code executes the second part of the if.

 if isinstance(inputs, tuple) or g.is_block:
            if isinstance(inputs, tuple):
                src_inputs, dst_inputs = inputs
            else:
                src_inputs = inputs
                dst_inputs = {k: v[:g.number_of_dst_nodes(k)] for k, v in inputs.items()}

            for stype, etype, dtype in g.canonical_etypes:
                rel_graph = g[stype, etype, dtype]
                if rel_graph.number_of_edges() == 0:
                    continue
                if stype not in src_inputs or dtype not in dst_inputs:
                    continue
                dstdata = self.mods[etype](
                    rel_graph,
                    (src_inputs[stype], dst_inputs[dtype]),
                    *mod_args.get(etype, ()),
                    **mod_kwargs.get(etype, {}))
                outputs[dtype].append(dstdata)
        else:
            for stype, etype, dtype in g.canonical_etypes:
                rel_graph = g[stype, etype, dtype]
                if rel_graph.number_of_edges() == 0:
                    continue
                if stype not in inputs: # <--- error from the stacktrace
                    continue
                dstdata = self.mods[etype](
                    rel_graph,
                    (inputs[stype], inputs[dtype]),
                    *mod_args.get(etype, ()),
                    **mod_kwargs.get(etype, {}))
                outputs[dtype].append(dstdata)

How should I format my input, which is a Tensor of shape(no_nodes, no_features) to be a tuple?

This is the stack trace

Using backend: pytorch
Traceback (most recent call last):
 File "/home/tudor/projects/xtailab/task2_graph_attention/test_scripts/hetero-edge_classif.py", line 159, in <module>
   pred = model(graph, node_features, target_edge)
 File "/home/tudor/.miniconda3/envs/xtailab/lib/python3.9/site-packages/torch/nn/modules/module.py", line 889, in _call_impl
   result = self.forward(*input, **kwargs)
 File "/home/tudor/projects/xtailab/task2_graph_attention/test_scripts/hetero-edge_classif.py", line 144, in forward
   h = self.sage(g, x)
 File "/home/tudor/.miniconda3/envs/xtailab/lib/python3.9/site-packages/torch/nn/modules/module.py", line 889, in _call_impl
   result = self.forward(*input, **kwargs)
 File "/home/tudor/projects/xtailab/task2_graph_attention/test_scripts/hetero-edge_classif.py", line 129, in forward
   h = self.conv1(graph, inputs)
 File "/home/tudor/.miniconda3/envs/xtailab/lib/python3.9/site-packages/torch/nn/modules/module.py", line 889, in _call_impl
   result = self.forward(*input, **kwargs)
 File "/home/tudor/.miniconda3/envs/xtailab/lib/python3.9/site-packages/dgl/nn/pytorch/hetero.py", line 187, in forward
   if stype not in inputs:
 File "/home/tudor/.miniconda3/envs/xtailab/lib/python3.9/site-packages/torch/tensor.py", line 648, in __contains__
   raise RuntimeError(
RuntimeError: Tensor.__contains__ only supports Tensor or scalar, but you passed in a <class 'str'>.

Process finished with exit code 1

Seems that your conv1 is a HeteroGraphConv instance. The input feature to that module must be a dictionary. I can see that you have changed the dictionary to a tensor due to the AssertionError above. Could you also show the stack trace of that error?

Traceback (most recent call last):
  File "/home/tudor/projects/xtailab/task2_graph_attention/test_scripts/hetero-edge_classif.py", line 160, in <module>
    pred = model(graph, node_feats, target_edge)
  File "/home/tudor/.miniconda3/envs/xtailab/lib/python3.9/site-packages/torch/nn/modules/module.py", line 889, in _call_impl
    result = self.forward(*input, **kwargs)
  File "/home/tudor/projects/xtailab/task2_graph_attention/test_scripts/hetero-edge_classif.py", line 145, in forward
    return self.pred(g, h, etype)
  File "/home/tudor/.miniconda3/envs/xtailab/lib/python3.9/site-packages/torch/nn/modules/module.py", line 889, in _call_impl
    result = self.forward(*input, **kwargs)
  File "/home/tudor/projects/xtailab/task2_graph_attention/test_scripts/hetero-edge_classif.py", line 90, in forward
    graph.ndata['h'] = h  # assigns 'h' of all node types in one shot
  File "/home/tudor/.miniconda3/envs/xtailab/lib/python3.9/site-packages/dgl/view.py", line 78, in __setitem__
    assert isinstance(val, dict) is False, \
AssertionError: The HeteroNodeDataView has only one node type. please pass a tensor directly

Process finished with exit code 1

So I guess your graph is heterogeneous but only has one node type? In that case you will need to change

graph.ndata['h'] = h

to

graph.ndata['h'] = h[your_node_type]
1 Like

Yes, I had one node type and multiple edge types.

It worked!
Thank you very much!

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