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

AttributeError: 'tuple' object has no attribute 'as_list' #126

Closed ameya98 closed 4 years ago

ameya98 commented 4 years ago

Here, I create NetworkX graphs, and convert them to GraphsTuple.

# Generate G(n, m) random graphs! We will divide these into training and testing sets later!
def generate_graphs(num_graphs:int=1000, max_nodes:int=20, num_features:int=1) -> [nx.Graph]:

  # Create the G(n, m) random graphs in NetworkX.
  num_nodes = np.random.randint(low=2, high=max_nodes, size=num_graphs)
  num_edges = np.random.randint(low=1, high=100, size=num_graphs)
  graphs_nx = [nx.gnm_random_graph(n, m, seed=seed) for n, m in zip(num_nodes, num_edges)]

  # We have to add features, otherwise GraphNets will complain!
  for graph in graphs_nx:
    graph.graph["features"] = np.random.uniform(size=num_features)
    for node in graph.nodes:
      graph.nodes[node]["features"] = np.random.uniform(size=num_features)
    for edge in graph.edges:
      graph.edges[edge]["features"] = np.random.uniform(size=num_features)

  # Finally, convert to a GraphsTuple.
  return utils_np.networkxs_to_graphs_tuple(graphs_nx)

graphs = generate_graphs(num_graphs=num_graphs)

Now, I define the model:

graph_network = modules.GraphNetwork(
  edge_model_fn   = lambda: snt.Linear(output_size=num_features),
  node_model_fn   = lambda: snt.Linear(output_size=num_features),
  global_model_fn = lambda: snt.Linear(output_size=1),
)

But, if I call:

out_graphs = graph_network(graphs)

I get the following error:

/usr/local/lib/python3.6/dist-packages/graph_nets/blocks.py in _build(self, graph)
    244     # If the number of nodes are known at graph construction time (based on the
    245     # shape) then use that value to make the model compatible with XLA/TPU.
--> 246     if graph.nodes is not None and graph.nodes.shape.as_list()[0] is not None:
    247       num_nodes = graph.nodes.shape.as_list()[0]
    248     else:

AttributeError: 'tuple' object has no attribute 'as_list'

Seems like the graph.nodes attribute is a tuple when it should be a tf.Tensor. This is TensorFlow 2, btw. Any help?

alvarosg commented 4 years ago

Hi, you need to make sure your GraphsTuple contains tensors and not numpy arrays (which is what the utils_np method returns inside the GraphsTuple).

You could instead convert each networkx graph to a data dict using utils_np.networkx_to_data_dict, and then into GraphsTuple via utils_tf.data_dicts_to_graphs_tuple.

Of directly convert everything inside of the numpy GraphsTuple into a tensor using: graphs_tuple = tree.map_structure(lambda x: tf.constant(x) if x is not None else None, graphs_tuple_np)

Hope this helps!

ameya98 commented 4 years ago

I can confirm this works! Thanks a lot!

graphs_tuple = utils_tf.data_dicts_to_graphs_tuple([utils_np.networkx_to_data_dict(graph) for graph in graphs_nx])