Training¶
Now, as you are familiar with operators and functions, let's learn an operator! In the following, we will learn the basics of training a neural operator in continuiti.
Operator¶
Given two sets of functions \(U\) and \(V\), assume we want to learn an operator
that maps functions \(u \in U\) to functions \(v \in V\).
In this example, we choose to learn the operator that maps the set of functions
to the set of functions
such that \(G(u_a) = v_a\). Let's consider \(x, y \in [0, 1]\) and start with the visualization of some functions in \(U\) and \(V\).
import torch
from continuiti.discrete import RegularGridSampler
from continuiti.data.function import FunctionSet
U = FunctionSet(lambda a: lambda x: torch.sin(a * torch.pi * x))
V = FunctionSet(lambda a: lambda y: a * torch.pi * torch.cos(a * torch.pi * y))
a = torch.Tensor([[1., 1.5, 2.]])
u_a = U(a)
v_a = V(a)
print(f"len(u) = {len(u_a)} ", f"len(v) = {len(v_a)}")
Note
In these examples, we hide the code for visualization, but you can find it in the source code of this notebook.
Discretization¶
Operator learning is about learning mappings between infinite dimensional spaces. To work with infinite-dimensional objects numerically, we have to discretize the input and output function somehow. In continuiti, this is done by point-wise evaluation.
Discretized functions can be collected in an OperatorDataset for
operator learning.
The OperatorDataset is a container of discretizations of input-output functions.
It contains tuples (x, u, y, v) of tensors, where every sample consists of
- the sensor positions
x, - the values
uof the input function at the sensor positions, - the evaluation points
y, and - the values
vof the output functions at the evaluation points.
If we already have a FunctionSet, we can use the FunctionOperatorDataset to
sample elements \(u \in U\) and \(v \in V\) evaluated at sampled positions.
Split data set into training, validation and test set.
Neural Operator¶
In order to learn the operator \(G\) with a neural network, we can train a neural operator.
A neural operator \(G_\theta\) takes an input function \(u\), evaluated at sensor positions \(x\), and maps it to a function \(v\) evaluated at (possibly different) evaluation points \(y\), such that $$ v(y) = G(u)(y) \approx G_\theta\left(x, u(x), y\right). $$
In this example, we train a DeepONet, a common neural operator architecture motivated by the universal approximation theorem for operators.
Training¶
continuiti provides the Trainer class
which implements a default training loop for neural operators.
It is instantiated with an Operator, an optimizer (Adam(lr=1e-3) by default),
and a loss function (MSELoss by default).
The fit method takes an OperatorDataset and trains the neural operator
up to a given tolerance on the training data (but at most for a
given number of epochs, 1000 by default).
Evaluation¶
The mapping of the trained operator can be evaluated at arbitrary positions, so let's plot the prediction of \(G_\theta\) on a fine resolution along with the target function.
Let us evaluate some training metrics, e.g., a validation error.
As you can observe, the neural operator is able to learn the operator \(G\) and generalizes well to unseen data. That's the basics!
Created: 2024-08-20