How to create, run and optimize models¶
This guide shows you how to create models using the \(\mu\mathcal{G}\) compiler, how to run them on your datasets, and how to let the compiler trace them before you run them.
Creating a model¶
To create a model, simply pass its \(\mu\mathcal{G}\) expression to the compile method on the MGCompiler instance.
It is possible to automatically print a summary of the compiled model by setting the verbose argument to True:
Finally, to enable automatic memoization, set the memoize argument to True:
# 'a' is computed only once inside the model
model = compiler.compile('((a || b);c) || a', memoize=True)
Running a model¶
The model can be run using any of the TensorFlow APIs that exist for this purpose: directly calling the model, using call, using predict, or using
predict_on_batch. In each of these cases, it is necessary to use the adequate loader for the dataset we will be feeding into the model. For datasets
consisting of a single graph we will be using the SingleGraphLoader, while for datasets consisting of multiple graphs, we will use the
MultipleGraphLoader. Both of these loaders are implemented in Spektral. The loaders convert a graph, or a batch of
graphs, into a list of TensorFlow Tensor objects, one each corresponding to the x, a, e and y arguments used to define the graph. The output of a
SingleGraphLoader will be a two-element tuple ((x, a, [e]), y) if y was specified in the graph, otherwise it will be a one-element tuple ((x, a, [e]),).
The MultipleGraphLoader shares the same output structure as the SingleGraphLoader, additionally adding a i tensor to the tail of the three-element
tuple on the left (e.g. ((x, a, [e], i), y)). The meaning of this tensor will be explained below.
Note
The loader chosen here must correspond the CompilerConfig object we used to instantiate the compiler.
To load a dataset with the SingleGraphLoader pass the dataset to it:
It is possible to specify the number of epochs that the loader will generate. Set epochs to 1 if you want that the loader simply returns the single graph in
the dataset once. If epochs is left as None, the loader will keep returning the graph every time it is called.
Similarly, to load a dataset with the MultipleGraphLoader, just pass the dataset to it.
from libmg import MultipleGraphLoader
dataset = MyDataset(...)
loader = MultipleGraphLoader(dataset)
It is again possible to specify the number of epochs. This time, since the dataset used with this loader has more than one graph, the epochs number specify how
many times to cycle through all the graphs. Set it to 1 to just show each graph once, None to keep cycling, or any other integer to cycle that amount of
times. The number of graphs to batch together is specified with the batch_size argument. For example, if batch_size=2 and the dataset has 10 graphs, the
loader will return 5 batches of 2 graphs. Each batch is structured according to Spektral's disjoint mode.
The loader therefore adds an i Tensor to its outputs. This tensor is used to specify to which graph belongs each row of the node features matrix x. For
example, if we batched two graphs and the x features matrix is [[1], [2], [3], [4]] (each node has one integer feature) and i is [0, 0, 1, 1] it
means that the first graph in the batch has two nodes with features [1] and [2] and the second graph has two nodes with features [3] and [4].
Using call or by directly calling the model¶
When using call on the model, we should obtain the graphs from the loader by iterating on the load method:
equivalently, we can also directly call the model:
If there is only one graph, it can also be obtained directly with:
If the true labels are present, they are not to be passed as inputs to the model:
Using predict¶
Using predict, you should fill in the steps arguments with the steps_per_epoch attribute of the loader:
Using predict_on_batch¶
Using predict_on_batch, you should just pass the batch of graphs:
Warning
For the time being, due to TensorFlow assertion checks, it is not possible to use the predict_on_batch API on datasets whose graphs have edge labels.
Training a model¶
Models can be trained in the usual manner as in TensorFlow. The model must first be compiled by TensorFlow (a distinct operation from compiling in \(\mu\mathcal{G}\)), specifying the optimizer and the loss function:
# Using stochastic gradient descent and mean squared error
model.compile(optimizer='sgd', loss='mse')
Then, we can train the model using fit, by specifying the steps_per_epoch using the loader and the number of epochs:
Note
The loader in this case should have been instantiated with epochs=None, since the fit method will specify the epochs.
Tracing a model¶
Tracing is performed automatically by running the model on some data. At any rate, it is possible to create dummy data which the compiler will use to trace
the model for you. In order to do that, we simply call the trace method on the compiler by passing in the model and the API we will be using to run the
model (either call, predict, or predict_on_batch):
Warning
The trace method with the second argument set to call returns a @tf.function that runs model.call on its inputs. Therefore the return value is
no longer a TensorFlow model, but a Python Callable and the typical TensorFlow methods (predict, fit, etc.) and the libmg model attributes will be no longer available.