Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
df1105f
initial example of two year data
rogerkuou Feb 27, 2026
fef01cf
update examples notebook
rogerkuou Feb 27, 2026
2b3ac47
add example training scritps
rogerkuou Feb 27, 2026
2bdf8b5
add example slurm file
rogerkuou Feb 27, 2026
1159fbc
update fig dir
rogerkuou Feb 27, 2026
3e2c4b4
add README
rogerkuou Feb 27, 2026
994d36b
Merge branch 'main' into 25_test_two_year_data
rogerkuou Feb 27, 2026
8cd1c8f
Apply suggestions from code review
rogerkuou Mar 18, 2026
fe8f024
fix conflicts
rogerkuou Mar 18, 2026
a3ba05d
separate training and inference
rogerkuou Mar 18, 2026
3c99673
update model exportation with checkpoint
rogerkuou Mar 18, 2026
2b4c7c5
add inference scripts
rogerkuou Mar 18, 2026
9ed2e00
use logging to replace print
rogerkuou Mar 18, 2026
1de1cfb
update example slurm scripts
rogerkuou Mar 18, 2026
efa17a1
force example notebook to be identical as main
rogerkuou Mar 26, 2026
25297dc
Apply suggestions from code review
rogerkuou Mar 26, 2026
6b04a27
revert changes in model file
rogerkuou Mar 26, 2026
ba0408f
remove inference script
rogerkuou Mar 26, 2026
74a180c
maintain the same config in example script as example notebook
rogerkuou Mar 26, 2026
eeb29ff
update the training loop
rogerkuou Mar 26, 2026
8481c08
update logger and log file
rogerkuou Mar 26, 2026
baba960
update the training script and slurm file
rogerkuou Mar 27, 2026
e89d4e4
document the efficiency calculation in README
rogerkuou Mar 27, 2026
3a5dbd6
add an example slurm log
rogerkuou Mar 27, 2026
4fd95d9
Merge branch 'main' into 25_test_two_year_data
rogerkuou Apr 20, 2026
fb94642
add docstring to datasets
rogerkuou Apr 20, 2026
17a8294
update example training script with train_monthly_model function
rogerkuou Apr 20, 2026
13714f9
update slurm
rogerkuou Apr 20, 2026
228c18a
update training script
rogerkuou Apr 20, 2026
8898cbf
add logger to training script
rogerkuou Apr 23, 2026
c799baf
enable printing in slurm logv files
rogerkuou Apr 23, 2026
92fbdeb
add constraints on the lattitude
rogerkuou Apr 23, 2026
3b9cae6
add slurm output file of a subset
rogerkuou Apr 23, 2026
7494f4a
add a full SLURM log file
rogerkuou Apr 23, 2026
a13472b
update readme
rogerkuou Apr 23, 2026
9cbd7e6
update slurm job time to 4hrs default
rogerkuou Apr 23, 2026
e9996e4
Update scripts/README.md
rogerkuou Apr 29, 2026
6bd6391
update longitude constraint
rogerkuou May 4, 2026
cfb2d7c
Merge branch 'main' into 25_test_two_year_data
rogerkuou Jun 15, 2026
2981bbd
update training script with new etting
rogerkuou Jun 15, 2026
4fe2aa2
config data paths
rogerkuou Jun 15, 2026
7b2eef3
update training script
rogerkuou Jun 17, 2026
8ea313d
update training script
rogerkuou Jun 17, 2026
7fac495
update training script
rogerkuou Jun 17, 2026
e5c3e48
update training parameters
rogerkuou Jun 18, 2026
1c0a61a
fix residuals
rogerkuou Jun 19, 2026
3dd0364
variable names
rogerkuou Jun 19, 2026
78b3a8c
add scripts to run best tuned model on test dataset
rogerkuou Aug 13, 2026
66560b0
doc best hypterparameters
rogerkuou Aug 13, 2026
1e93be5
remove shebang
rogerkuou Aug 14, 2026
eaa9d8f
solve conflict
rogerkuou Aug 16, 2026
dbfbd47
reorgnize folder
rogerkuou Aug 16, 2026
aa2779b
formatting
rogerkuou Aug 16, 2026
f1a8fab
merge run best model for example
rogerkuou Aug 16, 2026
90f94f1
rename training.slurm
rogerkuou Aug 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions scripts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Scripts

## Structure

- `data_preparation.*`: Scripts for preparing the data for training, tuning and evaluation. Mainly converting large netCDF files to Zarr storage with specific chunking strategies. This allows executing training for larger-than-memory datasets.
- `example_training.*`: example training script
- `tuning.*`: Scripts for hyperparameter tuning.
- `run_best_tuned_model.*`: Scripts for running the best tuned model on the test set.
- `logs`:
- `eso4clima_24438134_subset.out`: example SLURM job output file of an execution on a subset of the global dataset. The dataset has two years of data (2020-2021) and the spatial coverage is from 30S to 30N and from 30W to 30E.
- `eso4clima_24449471_full.out`: example SLURM job output file of an execution on the full dataset, two years of data (2020-2021) and almost global coverage (from 80S to 80N and from 179.99W to 179.99E). The training only executed for 1 hour and cuted off by SLURM time limit.

## Experiments

### Tuning experiments

- datasplit: train set = 2020, validation set = 2021, test set = 2022
- path of tuning results: `/work/<account_id>/eso4clima/tune/`.
- test loss: 0.036662004509047774
- hyperparameters of the best model:

```
{'patch_size': 8,
'overlap': 1,
'embed_dim': 64,
'dropout': 0.2,
'hidden': 32,
'spatial_depth': 3,
'spatial_heads': 2,
'optimizer_lr': 0.001787422899066508,
'batch_config': {'batch_size': 100, 'accumulation_steps': 2}}
```

### Training experiments

- Use the best hyperparameters found in the tuning experiments to train the model on the training set and evaluate it on the test set.
- Use three years 2018-2020 for training, 2021 for validation and 2022 for testing.
- Prepared data is stored in `/work/<account_id>/eso4clima/preprocessed/sst/`.
- Load one year data following example in `run_best_tuned_model.py` script. Then concatenate the three years as `xr.concat([da_2018, da_2019, da_2020], dim="M")`.
- In dataloader, use `load_lazy=True`.


263 changes: 263 additions & 0 deletions scripts/logs/eso4clima_24438134_subset.out

Large diffs are not rendered by default.

232 changes: 232 additions & 0 deletions scripts/logs/eso4clima_24449471_full.out

Large diffs are not rendered by default.

184 changes: 184 additions & 0 deletions scripts/run_best_tuned_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
import argparse
from pathlib import Path

import xarray as xr
from ray import tune

from climanet.dataset import DataLoaderConfig, STDataset
from climanet.predict import PredictionConfig, predict_monthly_var
from climanet.utils import data_preparation, read_st_data


def build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
description=(
"Load the best Ray Tune checkpoint, prepare the test data, and evaluate the "
"trained model on the 2023 test period."
)
)
parser.add_argument(
"--experiment-path",
type=Path,
required=True,
help="Path to the Ray Tune experiment directory containing the checkpoint.",
)
parser.add_argument(
"--test-data-dir",
type=Path,
required=True,
help="Directory containing the test NetCDF files.",
)
parser.add_argument(
"--lsm-file-path",
type=Path,
required=True,
help="Path to the land-sea mask NetCDF file.",
)
parser.add_argument(
"--run-dir",
type=Path,
default=Path("./run_dir_tune_test").resolve(),
help="Directory used for the evaluation run and saved logs.",
)
parser.add_argument(
"--var-name",
type=str,
default="tos",
help="Variable name to evaluate in the NetCDF files.",
)
parser.add_argument(
"--year",
type=str,
default="2022",
help="Year pattern to include in the test files (e.g. 2022).",
)
return parser


def main() -> None:
args = build_parser().parse_args()
experiment_path = args.experiment_path.resolve()
test_data_dir = args.test_data_dir.resolve()
lsm_file_path = args.lsm_file_path.resolve()
run_dir = args.run_dir.resolve()
run_dir.mkdir(parents=True, exist_ok=True)

if not experiment_path.exists():
raise FileNotFoundError(
f"Experiment directory does not exist: {experiment_path}"
)
if not test_data_dir.exists():
raise FileNotFoundError(f"Test data directory does not exist: {test_data_dir}")
if not lsm_file_path.exists():
raise FileNotFoundError(f"LSM file does not exist: {lsm_file_path}")

daily_files = list(
test_data_dir.glob(f"{args.year}*_hr_ERA5dc_masked_{args.var_name}*.nc")
)
monthly_files = list(
test_data_dir.glob(f"{args.year}*_mon_ERA5dc_masked_{args.var_name}*.nc")
)

if not daily_files:
raise FileNotFoundError(
f"No daily test files found for year '{args.year}' in '{test_data_dir}'"
)
if not monthly_files:
raise FileNotFoundError(
f"No monthly test files found for year '{args.year}' in '{test_data_dir}'"
)

print(f"Using daily files ({len(daily_files)}): {daily_files[:3]} ...")
print(f"Using monthly files ({len(monthly_files)}): {monthly_files[:3]} ...")

daily_data_test = xr.open_mfdataset(
daily_files, combine="by_coords", parallel=False
)
monthly_data_test = xr.open_mfdataset(
monthly_files, combine="by_coords", parallel=False
)

test_data_zarr_dir = run_dir / "test_data_zarr"
test_data_zarr_dir.mkdir(parents=True, exist_ok=True)

_ = data_preparation(
daily_data_test[args.var_name],
monthly_data_test[args.var_name],
calculate_residuals=True,
is_hourly=True,
save_to_zarr=True,
run_dir=test_data_zarr_dir,
)

input_da, input_da_nan_mask, monthly_da, padded_days_mask, time_features = (
read_st_data(
data_path=test_data_zarr_dir,
var_name=args.var_name,
)
)

lsm_mask = xr.open_dataset(lsm_file_path)

num_patches = (10, 10)
patch_size = (1, 4, 4)
spatial_patch_size = (
patch_size[1] * num_patches[0],
patch_size[2] * num_patches[1],
)
stride = (spatial_patch_size[0] // 5, spatial_patch_size[1] // 5)

dataset_test = STDataset(
input_da=input_da,
input_da_nan_mask=input_da_nan_mask,
monthly_da=monthly_da,
padded_days_mask=padded_days_mask,
time_features=time_features,
land_mask=lsm_mask["lsm"],
patch_size=(1, *spatial_patch_size),
stride=stride,
sh_embed_dim=96,
sh_order_L=10,
verbose=True,
load_lazy=False,
)
print(f"Created test dataset with {len(dataset_test)} patches.")

analysis = tune.ExperimentAnalysis(str(experiment_path))
best_result = analysis.get_best_trial("loss", "min")
best_checkpoint = best_result.checkpoint
model_path = Path(best_checkpoint.path) / "checkpoint.pt"
print(f"Best checkpoint path: {model_path}")

prediction_config = PredictionConfig(
calculate_residuals=True,
return_numpy=True,
save_predictions=False,
return_loss=True,
device="cpu",
verbose=False,
)

dataloader_config = DataLoaderConfig(
batch_size=10,
shuffle=True,
num_workers=0,
pin_memory=False,
persistent_workers=False,
device="cpu",
multiprocessing_context=None,
)

test_loss = predict_monthly_var(
model=model_path,
dataset=dataset_test,
dataloader_config=dataloader_config,
prediction_config=prediction_config,
run_dir=run_dir,
)

print("Test loss:")
print(test_loss)


if __name__ == "__main__":
main()
24 changes: 24 additions & 0 deletions scripts/run_best_tuned_model.slurm
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/bin/bash
#SBATCH --job-name=climanet_eval
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=128
#SBATCH --time=02:00:00
#SBATCH --account=bd0854
#SBATCH --partition=compute
#SBATCH --output=climanet_eval_%j.out
#SBATCH --error=climanet_eval_%j.err

set -euo pipefail

source /home/b/b383704/eso4clima/ClimaNet/.venv/bin/activate

python -u /home/b/b383704/eso4clima/run_best_tuned_model/run_best_tuned_model.py \
--experiment-path /work/bd0854/eso4clima/tune/sst_01 \
--test-data-dir /work/bd0854/b380103/eso4clima/output/sst/concatenated/ \
--lsm-file-path /home/b/b383704/eso4clima/data/era5_lsm_bool.nc \
--run-dir /home/b/b383704/eso4clima/run_best_tuned_model/run_dir \
--var-name tos \
--year 2022

printf "\nFinished evaluation run.\n"
Loading
Loading