google-deepmind / graph_nets

Build Graph Nets in Tensorflow
https://arxiv.org/abs/1806.01261
Apache License 2.0
5.34k stars 783 forks source link

Error when calling trained model: "AttributeError: tuple object has no attribute "as_list" #145

Closed robertswil closed 2 years ago

robertswil commented 2 years ago

Followed recommendation in this issue; didn't work.

Here's the code. Given a list of nx.Graph objects, make a prediction with the trained model.

data_dicts = [utils_np.networkx_to_data_dict(nx.to_directed(g)) for g in nx_graphs]
graphs_tuple = utils_np.data_dicts_to_graphs_tuple(data_dicts)

model(graphs_tuple, num_processing_steps)

Throws exception:

..\graph_nets\utils_tf.py in _get_shape(tensor)
     99    """
    100    
--> 101    shape_list = tensor.shape.as_list()
    102    if all(s is not None for s in shape_list):
    103      return shape_list

Attribute error: 'tuple' object has no attribute 'as_list'
alvarosg commented 2 years ago

Thank you for your message!

Followed recommendation in this issue; didn't work.

This indeed looks very similar do the linked issue, and usually this happens when the input is a numpy array instead of a tensor, and indicates some missing conversion. Could you confirm what is the error you get with the proposed solutions in that issue. Both this:

data_dicts = [utils_np.networkx_to_data_dict(nx.to_directed(g)) for g in nx_graphs]
graphs_tuple = utils_tf.data_dicts_to_graphs_tuple(data_dicts)
model(graphs_tuple, num_processing_steps)

and this:

import tree  # pip install dm-tree
data_dicts = [utils_np.networkx_to_data_dict(nx.to_directed(g)) for g in nx_graphs]
graphs_tuple_np = utils_np.data_dicts_to_graphs_tuple(data_dicts)
graphs_tuple = tree.map_structure(lambda x: tf.constant(x) if x is not None else None, graphs_tuple_np)

model(graphs_tuple, num_processing_steps)
robertswil commented 2 years ago

Hey thanks for the suggestions. Turns out I was also running into an issue where utils_tf.data_dicts_to_graphs_tuple() cannot handle graphs without edges (btw, can that functionality be added with an edge shape hint a la utils_np.networkx_to_graphs_tuple()?). I added some dummy edges to the sets and now it works! Thanks.

alvarosg commented 2 years ago

Thanks for your reply!

There are usually two different situations for graphs that don't have edges:

In the first case, actually the correct behavior for the model is to actually output None, so the hint should not be necessary.

In the second case, even if one graph in the dataset does not have edges, the outputs should have edges with shape [0, edge_size]. For data_dicts_to_graphs_tuple, th input data dict for a specific graph with no edges within a dataset where other graphs have edges should have a field with shape edges with shape [0, edge_size], and this would already play the role of the edge_size_hint, so the edge_size_hint field should not be necessary.

The reason for networkx_to_graphs_tuple to have an edge size hint, is that for a networkx graph with no edges, even if other graphs in the dataset do have edges, there is not way to encode the edge shape anywhere, so it has to be passed separately.

Hope this helps!