I have a GNN that works when I specify the loader as:
loader = spektral.data.loaders.DisjointLoader(dataset, batch_size=1)
However, when I increase the batch size, e.g.:
loader = spektral.data.loaders.DisjointLoader(dataset, batch_size=2)
I get:
Traceback (most recent call last):
File "/Users/hca/PycharmProjects/Switching%20notes/ai/tests/test.py", line 30, in <module>
model.fit(loader.load(), steps_per_epoch=loader.steps_per_epoch, epochs=3)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/tensorflow/python/keras/engine/training.py", line 1100, in fit
tmp_logs = self.train_function(iterator)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/tensorflow/python/eager/def_function.py", line 828, in __call__
result = self._call(*args, **kwds)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/tensorflow/python/eager/def_function.py", line 888, in _call
return self._stateless_fn(*args, **kwds)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/tensorflow/python/eager/function.py", line 2942, in __call__
return graph_function._call_flat(
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/tensorflow/python/eager/function.py", line 1918, in _call_flat
return self._build_call_outputs(self._inference_function.call(
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/tensorflow/python/eager/function.py", line 555, in call
outputs = execute.execute(
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/tensorflow/python/eager/execute.py", line 59, in quick_execute
tensors = pywrap_tfe.TFE_Py_Execute(ctx._handle, device_name, op_name,
tensorflow.python.framework.errors_impl.InvalidArgumentError: Incompatible shapes: [26,1] vs. [2,13]
[[node gradient_tape/binary_crossentropy/logistic_loss/mul/BroadcastGradientArgs (defined at Users/hca/PycharmProjects/Switching%20notes/ai/tests/test.py:30) ]] [Op:__inference_train_function_3011]
Function call stack:
train_function
Here it seems to me that the loader adds an additional dimension to the target variable, but this dimension is not expected in the model itself. I can specify a batch size inside model.fit()
, and that works if I don't specify a batch size larger than 1 inside DisjointLoader
, but I am not sure how these interact and whether that is a good idea? Is there something else that I should do when I want to run batches?
Also, regarding node-level classification, when I specify
loader = spektral.data.loaders.DisjointLoader(dataset, node_level=True)
I get:
Traceback (most recent call last):
File "/Users/hca/PycharmProjects/Switching%20notes/ai/tests/test.py", line 30, in <module>
model.fit(loader.load(), steps_per_epoch=loader.steps_per_epoch, epochs=3)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/tensorflow/python/keras/engine/training.py", line 1100, in fit
tmp_logs = self.train_function(iterator)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/tensorflow/python/eager/def_function.py", line 828, in __call__
result = self._call(*args, **kwds)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/tensorflow/python/eager/def_function.py", line 888, in _call
return self._stateless_fn(*args, **kwds)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/tensorflow/python/eager/function.py", line 2942, in __call__
return graph_function._call_flat(
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/tensorflow/python/eager/function.py", line 1918, in _call_flat
return self._build_call_outputs(self._inference_function.call(
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/tensorflow/python/eager/function.py", line 555, in call
outputs = execute.execute(
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/tensorflow/python/eager/execute.py", line 59, in quick_execute
tensors = pywrap_tfe.TFE_Py_Execute(ctx._handle, device_name, op_name,
tensorflow.python.framework.errors_impl.InvalidArgumentError: TypeError: `generator` yielded an element of ((TensorSpec(shape=(13, 36), dtype=tf.float64, name=None), SparseTensorSpec(TensorShape([13, 13]), tf.int64), TensorSpec(shape=(13,), dtype=tf.int64, name=None)), TensorSpec(shape=(1, 13), dtype=tf.float64, name=None)) where an element of ((TensorSpec(shape=(None, 36), dtype=tf.float64, name=None), SparseTensorSpec(TensorShape([None, None]), tf.int64), TensorSpec(shape=(None,), dtype=tf.int64, name=None)), TensorSpec(shape=(None,), dtype=tf.float64, name=None)) was expected.
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/tensorflow/python/ops/script_ops.py", line 247, in __call__
return func(device, token, args)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/tensorflow/python/ops/script_ops.py", line 135, in __call__
ret = self._func(*args)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/tensorflow/python/autograph/impl/api.py", line 620, in wrapper
return func(*args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/tensorflow/python/data/ops/dataset_ops.py", line 976, in generator_py_func
raise TypeError(
TypeError: `generator` yielded an element of ((TensorSpec(shape=(13, 36), dtype=tf.float64, name=None), SparseTensorSpec(TensorShape([13, 13]), tf.int64), TensorSpec(shape=(13,), dtype=tf.int64, name=None)), TensorSpec(shape=(1, 13), dtype=tf.float64, name=None)) where an element of ((TensorSpec(shape=(None, 36), dtype=tf.float64, name=None), SparseTensorSpec(TensorShape([None, None]), tf.int64), TensorSpec(shape=(None,), dtype=tf.int64, name=None)), TensorSpec(shape=(None,), dtype=tf.float64, name=None)) was expected.
[[{{node EagerPyFunc}}]]
[[IteratorGetNext]] [Op:__inference_train_function_3015]
Function call stack:
train_function
In this case, the shape of y
is (1, 13)
, where (None,)
is expected. However, in the dataset, y
has the dimensions (13,)
, which seems to me could have been correct, had DisjointLoader
not changed that to (1, 13)
. What am I missing here?
My GNN code is as follows:
import spektral
from dataset_class import GNN_Dataset
from spektral.data.dataset import Dataset
from spektral.layers import GraphSageConv
from tensorflow.keras.layers import Dense, Input
from tensorflow.keras.models import Model
class SN_GNN(Model):
def __init__(self):
super().__init__()
self.X_in = Input(shape=(13, ),
name='X_in')
self.A_in = Input(shape=(None,),
sparse=True,
name='A_in')
self.GraphSage = GraphSageConv(32)
self.output_layer = Dense(1, activation='softmax')
def call(self, inputs):
x, a = inputs[0], inputs[1]
x = self.GraphSage([x, a])
out = self.output_layer(x)
return out
model = SN_GNN()
dataset = GNN_Dataset('/dataset/sn/')
loader = spektral.data.loaders.DisjointLoader(dataset, node_level=True)
model.compile(optimizer='Adam', loss='binary_crossentropy')
model.fit(loader.load(), steps_per_epoch=loader.steps_per_epoch, epochs=3)