question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Shape Problem: Disjointloader and GCNConv (Node classification with multiple graphs)

See original GitHub issue

Hey, first of all im new in the field of Graph Neural Networks and using spektral now for like a month, i’m not sure if its really a bug, but im trying to solve these problems since weeks now and was checking the issues and the documentation of spektral.

I want to use GCN for Node classification and i have 115 Graphs (all with the same shape --> padded) and created a Dataset Object with the Dataset Class (example from the documentation). Each Graph contains 117 nodes, 322 features and 8 labels. Shape:

  • Labels y: (8,8) --> one-hot-encodded
  • Adjacency matrix a: (117, 117)
  • Feature matrix x: (117, 322)
  • e = None

I’m splitting the data into train and test and then using the Disjointloader (cause i read in an issue node classification with multiple graphs is the best way with Disjoint Mode). I was also playing with the batch size, but to make it very easy i’m trying to solve my problem with a batchsize =1. I also set the node_level argument “True” for my labels.

train_loader = DisjointLoader(data_train, batch_size=batch_size, epochs=epochs, node_level=True) test_loader = DisjointLoader(data_test, batch_size=batch_size)

For my node classification problem I want to use GCNConv (but I also tried the normal GCN class). I was trying to use the citation_gcn.py example and also the GCNConv (without boolean masks for now).

`class OCRGCN(Model): “”"Input - Node features of shape ([batch], n_nodes, n_node_features); - Modified Laplacian of shape ([batch], n_nodes, n_nodes); can be computed with spektral.utils.convolution.gcn_filter

Output
- Node features with the same shape as the input, but with the last
dimension changed to channels.

Args:
    Model (_type_): _description_
  """
def __init__(self, n_hidden, n_labels):
    super().__init__()

    # Define the GCN layer with n_hidden layers
    self.graph_conv = GCNConv(n_hidden)
    # Define the global pooling layer
    self.pool = GlobalSumPool()
    # Define the dropout layer, initialize dropout freq. to .5 (50%)
    self.dropout = Dropout(0.5)
    # Define the Dense layer, with softmax activation function
    self.dense = Dense(n_labels, "softmax")

def call(self, inputs):
    """Define class method to call model on input

    Args:
        inputs (_type_): _description_

    Returns:
        _type_: _description_
    """
    # inputs # ohne i
    out = self.graph_conv(inputs)
    out = self.dropout(out)
    # out # mit i --> Debugger
    out = self.pool(out)
    out = self.dense(out)

    return out

` Later in the main:

# Build GCN model model = OCRGCN(64, n_labels=8)

#Compile the model with adam optimizer and loss function model.compile(optimizer=Adam(learning_rate), loss="categorical_crossentropy") #Now we can train! We don't need to specify a batch size, since our loader is basically a generator model.fit(train_loader.load(), steps_per_epoch=train_loader.steps_per_epoch, epochs=epochs)

It didn’t worked and i got the following error: ValueError: too many values to unpack (expected 2)

Then I checked the shape of a batch from the loader. I just found out that there is also the batch index i. for batch in train_loader: (x, a, i), y = batch # labels have shape [batch, n_labels] if node_level=False or [n_nodes, n_labels] break But the GCN_Conv. Input just accepts 2dim (x, a). Then I deleted the i (hard codded) for testing, but the GlobalSumPool Layer requieres (x, a, i) in disjoint mode.

I also fixed the call method in the GCNConv Class: def call(self, inputs, mask=None): if len(inputs) == 2: x, a = inputs else: x, a, _ = inputs # So that the model can be used with DisjointLoader

But now i get another error. It seems that the shape [1, 64 is [batchsize, n_hidden] and [8, 8] is the shape of my labels.

tensorflow.python.framework.errors_impl.InvalidArgumentError: Graph execution error:

Detected at node ‘gradient_tape/ocrgcn/dense/MatMul/MatMul_1’ defined at (most recent call last): File “/root/OCR%20POC/GCN/OCR_POC/GCN_model_disjoint_mode.py”, line 410, in <module> main() File “/root/OCR%20POC/GCN/OCR_POC/GCN_model_disjoint_mode.py”, line 94, in main model.fit(train_loader.load(), steps_per_epoch=train_loader.steps_per_epoch, epochs=epochs) File “/root/paddle/lib/python3.9/site-packages/keras/utils/traceback_utils.py”, line 64, in error_handler return fn(*args, **kwargs) File “/root/paddle/lib/python3.9/site-packages/keras/engine/training.py”, line 1384, in fit tmp_logs = self.train_function(iterator) File “/root/paddle/lib/python3.9/site-packages/keras/engine/training.py”, line 1021, in train_function return step_function(self, iterator) File “/root/paddle/lib/python3.9/site-packages/keras/engine/training.py”, line 1010, in step_function outputs = model.distribute_strategy.run(run_step, args=(data,)) File “/root/paddle/lib/python3.9/site-packages/keras/engine/training.py”, line 1000, in run_step outputs = model.train_step(data) File “/root/paddle/lib/python3.9/site-packages/keras/engine/training.py”, line 863, in train_step self.optimizer.minimize(loss, self.trainable_variables, tape=tape) File “/root/paddle/lib/python3.9/site-packages/keras/optimizer_v2/optimizer_v2.py”, line 530, in minimize grads_and_vars = self._compute_gradients( File “/root/paddle/lib/python3.9/site-packages/keras/optimizer_v2/optimizer_v2.py”, line 583, in _compute_gradients grads_and_vars = self._get_gradients(tape, loss, var_list, grad_loss) File “/root/paddle/lib/python3.9/site-packages/keras/optimizer_v2/optimizer_v2.py”, line 464, in _get_gradients grads = tape.gradient(loss, var_list, grad_loss) Node: ‘gradient_tape/ocrgcn/dense/MatMul/MatMul_1’ Matrix size-incompatible: In[0]: [1,64], In[1]: [8,8] [[{{node gradient_tape/ocrgcn/dense/MatMul/MatMul_1}}]] [Op:__inference_train_function_623]

/root/OCR%20POC/GCN/OCR_POC/GCN_model_disjoint_mode.py(94)main() -> model.fit(train_loader.load(), steps_per_epoch=train_loader.steps_per_epoch, epochs=epochs) (Pdb) n –Return– /root/OCR%20POC/GCN/OCR_POC/GCN_model_disjoint_mode.py(94)main()->None -> model.fit(train_loader.load(), steps_per_epoch=train_loader.steps_per_epoch, epochs=epochs)

I guess my data shape and the GCN Model dont fit together, but i was following the instructions and examples. But at this point, I really dont know what to do and I hope that someone can help me with the problem or suggest alternative ways.

Thank you!

Ps: Sorry, for the weird format of the code snippets. I dont know why it doesnt work as supposed.

Issue Analytics

  • State:closed
  • Created a year ago
  • Reactions:1
  • Comments:6 (2 by maintainers)

github_iconTop GitHub Comments

3reactions
danielegrattarolacommented, Jul 6, 2022

If you want to do node-level prediction, then you should remove the global pooling layer from your model. In this case, the model will output one prediction of size 9 per graph in the batch (32), hence the outputs/logits will have shape (32, 9) but the targets will have shape (n_nodes_in_batch, 9). If you remove the global pooling layer, the output of the model will be as expected.

1reaction
CCAI-Ericcommented, Jul 7, 2022

Thanks a lot that helped!

I also had an issue with the shape of my labels! It was because of the stupid One-hot-encoder of sklearn, which returned a sparse-matrix covered by a np array! That issued another error! Since i fixed that with the flag sparse=False, the training finally started!

Thanks a lot for helping, im closing the issue!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Node classification with Graph Convolutional Network (GCN)
In this notebook, we'll be training a model to predict the class or label of a node, commonly known as node classification. We...
Read more >
Getting started - Spektral
In this tutorial, we will go over the main features of Spektral while creating a graph neural network for graph classification.
Read more >
Understanding Graph Convolutional Networks for Node ...
Understanding Graph Convolutional Networks for Node Classification · In this article, we'll dive deeper into Graph Convolutional Networks ...
Read more >
3. Graph Classification.ipynb - Colaboratory - Google Colab
Graph classification refers to the problem of classifiying entire graphs (in contrast to nodes), given a dataset of graphs, based on some structural...
Read more >
A Comprehensive Introduction to Graph Neural Networks ...
Node Classification with GNN. We will create a GCN model structure that contains two GCNConv layers relu activation and a dropout rate of...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found