Models¶
BaseModel
¶
Bases: LightningModule, ABC
A base class for all models used in the IceNet-MP project.
ignored_hparams = frozenset(('latitudes_fn', 'longitudes_fn'))
class-attribute
¶
name = name
instance-attribute
¶
hemisphere = hemisphere
instance-attribute
¶
latitudes_fn = latitudes_fn
instance-attribute
¶
longitudes_fn = longitudes_fn
instance-attribute
¶
n_forecast_steps = n_forecast_steps
instance-attribute
¶
n_history_steps = n_history_steps
instance-attribute
¶
input_spaces = [DataSpace.from_dict(space) for space in input_spaces]
instance-attribute
¶
output_space = DataSpace.from_dict(output_space)
instance-attribute
¶
optimizer_cfg = optimizer
instance-attribute
¶
scheduler_cfg = scheduler
instance-attribute
¶
lr_scheduler_cfg = lr_scheduler
instance-attribute
¶
loss_cfg
property
writable
¶
Get the loss configuration.
test_metrics = MetricCollection(deepcopy(_common_metrics))
instance-attribute
¶
train_metrics = MetricCollection(deepcopy(_common_metrics))
instance-attribute
¶
validation_metrics = MetricCollection(deepcopy(_common_metrics))
instance-attribute
¶
latitudes
cached
property
¶
longitudes
cached
property
¶
multistage_only
property
¶
configure_optimizers()
¶
Construct the optimizer and optional scheduler from the config.
forward(inputs)
abstractmethod
¶
Forward step of the model.
- start with multiple [NTCHW] inputs, one for each input dataset
- return a single [NTCHW] output representing the predicted output
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inputs
|
dict[str, TensorNTCHW]
|
Dictionary of dataset name to TensorNTCHW with shape [batch, n_history_steps, C_input_k, H_input_k, W_input_k] |
required |
Returns:
| Type | Description |
|---|---|
TensorNTCHW
|
Predicted TensorNTCHW with shape [batch, n_forecast_steps, C_output, H_output, W_output] |
loss(prediction, target)
¶
Calculate the loss given a prediction and target.
process_batch(batch)
¶
Process a batch before the forward pass and loss computation.
Subclasses can override this to extract or transform inputs before the standard
training/validation steps. The returned dict must include a "target" key.
test_step(batch, _batch_idx)
¶
Run the test step, in PyTorch eval model (i.e. no gradients).
- Separate the batch into inputs and target
- Run inputs through the model
- Return the prediction, target and loss
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
batch
|
dict[str, TensorNTCHW]
|
Dictionary mapping dataset name to its contents. There is one entry for each input dataset and one for the target. Each of these is a TensorNTCHW with (batch_size, n_history_steps, C, H, W). |
required |
Returns:
| Type | Description |
|---|---|
ModelStepOutput
|
A ModelStepOutput containing the prediction, target and loss for the batch. |
training_step(batch, _batch_idx)
¶
Run the training step.
- Separate the batch into inputs and target
- Run inputs and target through the model
- Calculate the loss wrt. the target
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
batch
|
dict[str, TensorNTCHW]
|
Dictionary mapping dataset name to its contents. There is one entry for each input dataset and one for the target. Each of these is a TensorNTCHW with (batch_size, n_history_steps, C, H, W). |
required |
Returns:
| Type | Description |
|---|---|
ModelStepOutput
|
A ModelStepOutput containing the prediction, target and loss for the batch. |
validation_step(batch, _batch_idx)
¶
Run the validation step.
A batch contains one tensor for each input dataset and one for the target These are [NTCHW] tensors with (batch_size, n_history_steps, C, H, W)
- Separate the batch into inputs and target
- Run inputs through the model
- Calculate and log the loss wrt. the target
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
batch
|
dict[str, TensorNTCHW]
|
Dictionary mapping dataset name to its contents. There is one entry for each input dataset and one for the target. Each of these is a TensorNTCHW with (batch_size, n_history_steps, C, H, W). |
required |
Returns:
| Type | Description |
|---|---|
ModelStepOutput
|
A ModelStepOutput containing the prediction, target and loss for the batch. |
DDPM
¶
Bases: BaseModel
Denoising Diffusion Probabilistic Model (DDPM).
Input space
TensorNTCHW with shape (batch_size, n_history_steps + n_history_steps * n_era5_channels, height, width) - OSISAF input: T historical steps, singleton channel squeezed - ERA5 input: T historical steps times number of channels, resized to OSISAF resolution
Output space
TensorNTCHW with shape (batch_size, n_forecast_steps * n_output_channels, height, width) - Forecasted outputs per timestep and channel, flattened along the channel dimension
ignored_hparams = BaseModel.ignored_hparams | {'mask_dir'}
class-attribute
¶
use_autoregressive = use_autoregressive
instance-attribute
¶
osisaf_key = self.output_space.name
instance-attribute
¶
restrict = RestrictRange(RangeRestriction(restrict_range), min_val=0, max_val=1)
instance-attribute
¶
mask = Mask(mask_type=mask_type, output_shape=self.output_space.shape, mask_dir=mask_dir)
instance-attribute
¶
era5_space = era5_space['channels']
instance-attribute
¶
osisaf_channels = osisaf_space['channels']
instance-attribute
¶
base_output_channels = self.output_space['channels']
instance-attribute
¶
output_channels = self.base_output_channels
instance-attribute
¶
timesteps = timesteps
instance-attribute
¶
cond_channels = 64
instance-attribute
¶
input_channels = self.cond_channels
instance-attribute
¶
era5_norm = torch.nn.InstanceNorm3d(self.era5_space, affine=True)
instance-attribute
¶
era5_compressed_channels = 32
instance-attribute
¶
era5_projector = torch.nn.Sequential(torch.nn.Conv3d(self.era5_space, self.era5_compressed_channels, kernel_size=1), torch.nn.SiLU())
instance-attribute
¶
osisaf_encoder = SimpleEncoder2D(in_channels=self.n_history_steps * self.osisaf_channels, out_channels=self.cond_channels // 2)
instance-attribute
¶
era5_encoder = torch.nn.Sequential(torch.nn.Conv2d(in_channels=self.era5_compressed_channels * self.n_history_steps, out_channels=self.cond_channels // 2, kernel_size=3, padding=1), torch.nn.GroupNorm(4, self.cond_channels // 2), torch.nn.SiLU())
instance-attribute
¶
model = UNetDiffusion(input_channels=self.input_channels, output_channels=self.output_channels, timesteps=self.timesteps, kernel_size=kernel_size, start_out_channels=start_out_channels, time_embed_dim=time_embed_dim, normalization=normalization, activation=activation, dropout_rate=dropout_rate)
instance-attribute
¶
diffusion = GaussianDiffusion(timesteps=timesteps)
instance-attribute
¶
learning_rate = learning_rate
instance-attribute
¶
forward(*args, **kwargs)
¶
sample(batch)
¶
Generate forecasts using a reverse diffusion process.
This method selects between two diffusion sampling strategies:
- Non-autoregressive (parallel) sampling:
- The model generates the entire future sequence in a single diffusion process.
-
No temporal dependency exists between forecast steps.
-
Autoregressive sampling:
- Forecast steps are generated sequentially.
- Each step is produced via an independent diffusion process.
- The conditioning tensor is updated after each step to incorporate previously generated outputs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
batch
|
dict[str, TensorNTCHW]
|
Dictionary containing the input data. |
required |
Returns:
| Type | Description |
|---|---|
TensorNCHW
|
torch.Tensor: Forecast tensor of shape: [B, n_forecast_steps * base_output_channels, H, W] The output format is identical in both modes.
|
Notes
- The diffusion process follows v-parameterization.
- Sampling begins from standard Gaussian noise.
prepare_inputs(batch)
¶
Encode OSISAF and ERA5 separately, then concatenate.
ERA5 -> Norm -> Project -> Resize -> Flatten Time -> Encode
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
batch
|
dict[str, TensorNTCHW]
|
Dictionary with osisaf key (e.g. 'osisaf-south') [B, T, C, H, W] 'era5' [B, T, C, H2, W2] |
required |
Returns:
| Type | Description |
|---|---|
TensorNCHW
|
Conditioning tensor [B, cond_channels, H, W] |
training_step(batch, _batch_idx)
¶
One training step using DDPM v-prediction loss.
During training, the clean target (SIC) is corrupted using the forward diffusion process by adding noise at a randomly sampled timestep. The model is trained to predict the corresponding v-target.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
batch
|
dict[str, TensorNTCHW]
|
Dictionary containing: - input tensors (used to prepare conditioning inputs) - "target": groundtruth SIC tensor |
required |
Returns:
| Name | Type | Description |
|---|---|---|
ModelStepOutput |
ModelStepOutput
|
|
ModelStepOutput
|
|
|
ModelStepOutput
|
|
|
ModelStepOutput
|
|
validation_step(batch, _batch_idx)
¶
One validation step using full diffusion sampling.
During validation, samples are generated by starting from noise and iteratively denoising conditioned on the inputs. The final prediction is compared to the groundtruth SIC using the configured evaluation loss.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
batch
|
dict[str, TensorNTCHW]
|
Dictionary containing: - input tensors (used to prepare conditioning inputs) - "target": groundtruth SIC tensor |
required |
Returns:
| Name | Type | Description |
|---|---|---|
ModelStepOutput |
ModelStepOutput
|
|
ModelStepOutput
|
|
|
ModelStepOutput
|
|
|
ModelStepOutput
|
|
test_step(batch, _batch_idx)
¶
One test step using full diffusion sampling and metric evaluation.
During testing, predictions are generated by starting from noise and running the reverse diffusion process conditioned on the inputs. The final reconstructed SIC is compared to the groundtruth target using the configured loss and test metrics.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
batch
|
dict[str, TensorNTCHW]
|
Dictionary containing: - input tensors (used to prepare conditioning inputs) - "target": groundtruth SIC tensor |
required |
Returns:
| Name | Type | Description |
|---|---|---|
ModelStepOutput |
ModelStepOutput
|
|
ModelStepOutput
|
|
|
ModelStepOutput
|
|
|
ModelStepOutput
|
|
EncodeProcessDecode
¶
Bases: BaseModel
Model that encodes to latent space, processes, then decodes back.
ignored_hparams = BaseModel.ignored_hparams | {'mask_dir'}
class-attribute
¶
target_variable_indices = target_variable_indices
instance-attribute
¶
encoders = [hydra.utils.instantiate(encoders[input_space.name], data_space_in=input_space, latent_space=encoders['latent_space'], latitudes_fn=self.latitudes_fn, longitudes_fn=self.longitudes_fn) for input_space in self.input_spaces]
instance-attribute
¶
target_encoder = hydra.utils.instantiate(encoders[self.output_space.name], data_space_in=DataSpace(name='target', channels=self.output_space.channels, shape=self.output_space.shape), latent_space=encoders['latent_space'], latitudes_fn=self.latitudes_fn, longitudes_fn=self.longitudes_fn)
instance-attribute
¶
processor = hydra.utils.instantiate(processor, data_space=combined_latent_space, data_space_target=self.target_encoder.data_space_out, n_forecast_steps=self.n_forecast_steps, n_history_steps=self.n_history_steps, target_channel_offset=self.find_target_channel_offset())
instance-attribute
¶
decoder = hydra.utils.instantiate(decoder, data_space_in=combined_latent_space, data_space_out=self.output_space, mask_dir=mask_dir)
instance-attribute
¶
multistage_only
property
¶
encode_inputs(inputs)
¶
Encode all input datasets and concatenate along the channel dimension.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inputs
|
dict[str, TensorNTCHW]
|
Dictionary with one TensorNTCHW entry per input dataset with shape (batch, n_history_steps, n_input_channels_k, H_input_k, W_input_k) |
required |
Returns:
| Type | Description |
|---|---|
TensorNTCHW
|
TensorNTCHW with shape (batch_size, n_history_steps, n_latent_channels_total, latent_height, latent_width) |
forward(inputs)
¶
Forward step of the model (used for inference).
- start with multiple [NTCHW] inputs each with shape [batch, n_history_steps, n_input_channels_k, H_input_k, W_input_k]
- encode inputs to [NTCHW] latent space [batch, n_history_steps, n_latent_channels, H_latent, W_latent]
- concatenate inputs in [NTCHW] latent space [batch, n_history_steps, n_latent_channels_total, H_latent, W_latent]
- process in latent space [NTCHW][batch, n_forecast_steps, n_latent_channels_total, H_latent, W_latent]
- decode back to [NTCHW] output space [batch, n_forecast_steps, n_output_channels, H_output, W_output]
- add a skip connection from the most recent target value to every forecast step
find_target_channel_offset()
¶
Find the channel offset of the target dataset within the combined latent space, if present.
get_persistence(inputs)
¶
Extract persistence if needed for a skip connection.
train(mode=True)
¶
Set training mode, with decoder frozen if computing loss in latent space.
training_step(batch, _batch_idx)
¶
Run the training step.
If the processor returns a loss in its ProcessorOutput (rather than None),
this is used for backpropagation. We use no_grad to compute the decoded
prediction, which allows us to calculate metrics and log outputs, but the
usefulness of these will depend on what ProcessorOutput.prediction contains.
Otherwise, the standard encode-process-decode path is used and the loss is computed by comparing the decoded prediction to the target.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
batch
|
dict[str, TensorNTCHW]
|
Dictionary with one NTCHW entry per input dataset (n_history_steps) and a "target" entry (n_forecast_steps). |
required |
Returns:
| Type | Description |
|---|---|
ModelStepOutput
|
A ModelStepOutput containing the prediction, target and loss. |
Persistence
¶
Bases: BaseModel
automatic_optimization = False
instance-attribute
¶
model = nn.Identity()
instance-attribute
¶
variable_indices = target_variable_indices
instance-attribute
¶
configure_optimizers()
¶
Persistence model does not need an optimizer.
forward(inputs)
¶
Forward step of the model.
- start with multiple [NTCHW] inputs each with shape [batch, n_history_steps, C_input_k, H_input_k, W_input_k]
- find the input with the same name as the output space
- select the channels corresponding to the target variables
- take the last time step and repeat it n_forecast_steps times