CNO
Convolutional Neural Operator (CNO)¤
neojax.models.cno.CNO
¤
Convolutional Neural Operator (CNO).
A U-Net-style convolutional architecture, in which every convolution is
paired with an alias-free activation \(\Sigma_{s, s'}\) that
upsamples, applies the leaky ReLU and downsamples again with
low-pass filters, such that the network maps between function
spaces instead of between fixed grids. Implements the classic
variant of the reference (CNO2d_classic) for any number of spatial dimensions.
The input is lifted to a latent space and passed through an encoder of
n_layers levels. Each level consists of n_res residual blocks, whose
output is kept for the skip connection, and a downsampling block (D-block).
The bottleneck applies n_res_neck residual blocks. The decoder has
n_layers levels, each consisting of an upsampling block (U-block)
and optionally an invariant block (I-block) applied after the skip
connection of the corresponding encoder level was concatenated
(along the channel dimension).
The channels double with every encoder level, starting
at channel_multiplier. The output lives on the same grid as the input.
All spatial sizes of the input must be divisible by 2 ** n_layers.
The model is otherwise resolution-agnostic, since the filters only depend on
the ratio of the input and output resolution of the blocks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
PRNGKeyArray
|
PRNG key for parameter initialization. |
required |
in_channels
|
int
|
Number of input channels (e.g. coordinates + initial conditions). |
required |
out_channels
|
int
|
Number of output channels (e.g. solution field). |
required |
ndim
|
int
|
Number of spatial dimensions of the input (e.g. 1, 2 or 3). |
required |
n_layers
|
int
|
Number of encoder (and decoder) levels. Must be at least 1. |
required |
n_res
|
int
|
Number of residual blocks per encoder level. Default is 1. |
1
|
n_res_neck
|
int
|
Number of residual blocks in the bottleneck. Default is 6. |
6
|
channel_multiplier
|
int
|
Number of channels after the first encoder level.
The lifted input has |
32
|
latent_lift_proj_channels
|
int
|
Number of latent channels inside the lifting and projection blocks. Default is 64. |
64
|
conv_kernel
|
int
|
Odd size of the convolution kernels along each dimension. Default is 3. |
3
|
cutoff_den
|
float
|
Denominator of the cutoff frequency of the filters, see |
2.0001
|
half_width_mult
|
float
|
Multiplier of the half-width of the transition band
of the filters, see |
0.8
|
filter_size
|
int
|
Number of filter taps per phase of the resampling, see |
6
|
add_inv
|
bool
|
Whether to add an invariant block after the concatenation of the skip connection in each decoder level. Default is True. |
True
|
positional_embedding
|
Union[GridEmbeddingNd, Literal['grid'], NoneType]
|
Positional embedding to apply
to last channels of raw input before passing through the CNO.
Default is None. Pass |
None
|
batch_norm
|
bool
|
Whether to apply batch normalization after the convolutions of
the blocks (but not in the lifting and projection), as in the reference.
If |
True
|
batch_axis_name
|
str
|
Name of the |
'batch'
|
batch_norm_momentum
|
float
|
Weight of the running statistics (not of the batch
statistics) in their update if |
0.9
|
pad_mode
|
Literal['wrap', 'reflect', 'constant']
|
Padding mode of the convolutions and activations. Use |
'constant'
|
negative_slope
|
float
|
Negative slope of the leaky ReLU. Default is |
0.2
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
ValueError
|
If an invalid positional embedding is passed. |
Stateful models (batch normalization)
With batch_norm=True (the default, as in the reference), the model has running
statistics and is stateful (is_stateful() returns True), following the
convention of Equinox:
- The model and its initial state are created with
model, state = eqx.nn.make_with_state(CNO)(...). - The model is called as
out, state = model(x, state), and has to be called inside of ajax.vmapover the batch withaxis_name=batch_axis_name, in which the state is not mapped:in_axes=(0, None), out_axes=(0, None). The batch statistics are computed over this axis (see example). inference=Trueuses the running statistics instead of the batch statistics and leaves the state unchanged.
CNO's with batch_norm=False are stateless and called as out = model(x).
Differences to the reference
- The batch normalization uses the
"batch"mode ofeqx.nn.BatchNorm: Like PyTorch, the batch statistics are used for training. For inference, an (initialization-corrected) exponential moving average of the batch statistics is used. - The reference supports different input and output resolutions
(
out_size) and enlarging the input to a multiple of2 ** n_layers(expand_input). Neither are supported. The output has the resolution of the input. - The reference builds an unused invariant block in the last decoder level, which is omitted here.
Internal Attributes
These fields store the internal layers state (and weights).
- positional_embedding (
GridEmbeddingNd | None): Positional embedding. - lift (
CNOLiftProjectBlock): Maps inputs to the latent space. - encoder (
tuple[CNOConvBlock, ...]): Downsampling blocks of the encoder. - res_nets (
tuple[tuple[CNOResidualBlock, ...], ...]): Residual blocks of each encoder level. - res_net_neck (
tuple[CNOResidualBlock, ...]): Residual blocks of the bottleneck. - ed_expansion (
tuple[CNOConvBlock, ...]): Invariant blocks applied to the features passed from the encoder to the decoder. - decoder_inv (
tuple[CNOConvBlock, ...] | None): Invariant blocks of the decoder orNone. - decoder (
tuple[CNOConvBlock, ...]): Upsampling blocks of the decoder. - project (
CNOLiftProjectBlock): Maps the latent features to the output channels. - n_layers (
int): Number of encoder (and decoder) levels. - ndim (
int): Number of spatial dimensions.
Examples:
import equinox as eqx
import jax
import jax.numpy as jnp
import jax.random as jr
from neojax.models import CNO
key = jr.key(0)
model = CNO(
key=key,
in_channels=3,
out_channels=1,
ndim=2,
n_layers=3,
n_res=1,
n_res_neck=2,
channel_multiplier=8,
batch_norm=False,
)
x = jnp.ones((3, 32, 32))
# out.shape = (1, 32, 32)
out = model(x)
# Batch normalization (default): stateful model
model, state = eqx.nn.make_with_state(CNO)(
key=key,
in_channels=3,
out_channels=1,
ndim=2,
n_layers=3,
n_res=1,
n_res_neck=2,
channel_multiplier=8,
batch_norm=True,
)
xs = jnp.ones((4, 3, 32, 32))
batched_model = jax.vmap(
model, axis_name="batch", in_axes=(0, None), out_axes=(0, None)
)
# outs.shape = (4, 1, 32, 32)
outs, state = batched_model(xs, state)
Cite
Convolutional Neural Operators for robust and accurate learning of PDEs
@inproceedings{NEURIPS2023_f3c1951b,
author = {Raonic, Bogdan and Molinaro,
Roberto and De Ryck, Tim and Rohner, Tobias and Bartolucci,
Francesca and Alaifari, Rima and Mishra,
Siddhartha and de B\'{e}zenac, Emmanuel},
booktitle = {Advances in Neural Information Processing Systems},
doi = {10.52202/075280-3376},
editor = {A. Oh and T. Naumann and A. Globerson
and K. Saenko and M. Hardt and S. Levine},
pages = {77187--77200},
title = {Convolutional Neural Operators for
robust and accurate learning of PDEs},
volume = {36},
year = {2023}
}
is_stateful() -> bool
¤
Whether the model is stateful, i.e. uses batch normalization.
Returns:
| Type | Description |
|---|---|
bool
|
|
__call__(x: Inexact[Array, 'in_c ...'], state: equinox.nn._stateful.State | None = None, *, key: PRNGKeyArray | None = None, inference: bool = False) -> Inexact[Array, 'out_c ...'] | tuple[Inexact[Array, 'out_c ...'], equinox.nn._stateful.State]
¤
Forward pass of the CNO model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
Inexact[Array, 'in_c ...']
|
Input array of shape |
required |
state
|
State | None
|
The state holding the running statistics of the batch
normalizations. Required if (and only if) |
None
|
key
|
PRNGKeyArray | None
|
Unused. Accepted for API compatibility with other neojax models. |
None
|
inference
|
bool
|
Whether to use the running statistics of the batch normalizations
instead of the batch statistics. Has no effect if the model is stateless.
Default is |
False
|
Returns:
| Type | Description |
|---|---|
Inexact[Array, 'out_c ...'] | tuple[Inexact[Array, 'out_c ...'], State]
|
The predicted field of shape |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the number of spatial dimensions of |
ValueError
|
If a spatial dimension of |
ValueError
|
If a state is required, but not given or vice versa. |