zhangrenchao commited on
Commit
f58cc34
·
verified ·
1 Parent(s): 281c4f7

Publish WeatherBench2 reproduction

Browse files
.gitattributes CHANGED
@@ -1,35 +1 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
- *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
- *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz filter=lfs diff=lfs merge=lfs -text
33
- *.zip filter=lfs diff=lfs merge=lfs -text
34
- *.zst filter=lfs diff=lfs merge=lfs -text
35
- *tfevents* filter=lfs diff=lfs merge=lfs -text
 
1
+ *.pt binary
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
conf/config.yaml ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ seed: 42
2
+ data: {path: data/data.npz, samples: 8, variables: 8, grid: [24, 48]}
3
+ model: {variables: 8, hidden: 16}
4
+ train: {lr: 0.001}
5
+ paths: {checkpoint: result/checkpoints/weatherbench2.pt, training_metrics: result/training/metrics.json, predictions: result/output/predictions.npz, evaluation: result/evaluation/metrics.json, figure: result/evaluation/comparison.png}
config.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"model_name":"WeatherBench2","model_type":"weatherbench2","architectures":["WB2Baseline"],"framework":"PyTorch","domain":"weather-benchmark","task":"forecast-evaluation","implementation":{"entry_point":"model/weatherbench2.py"},"architecture":{"headline_variables":8,"grid":[120,240],"ensemble_members":8},"data":{"source":"ERA5","evaluation_year":2020},"configuration_sources":["conf/config.yaml","model/weatherbench2.py","scripts/fake_data.py","scripts/train.py","scripts/inference.py","scripts/result.py"]}
model/weatherbench2.py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ import json,torch,yaml
2
+ from pathlib import Path
3
+ from torch import nn
4
+ def cfg(r):return yaml.safe_load((Path(r)/'conf/config.yaml').read_text())
5
+ class WB2Baseline(nn.Module):
6
+ def __init__(self,variables=8,hidden=16):super().__init__();self.n=nn.Sequential(nn.Conv2d(variables,hidden,3,padding=1),nn.ReLU(),nn.Conv2d(hidden,variables,3,padding=1));self.model_config={'variables':variables,'hidden':hidden}
7
+ def forward(self,x):return x+self.n(x)
8
+ def write(p,o):p=Path(p);p.parent.mkdir(parents=True,exist_ok=True);p.write_text(json.dumps(o,indent=2)+'\n')
scripts/fake_data.py ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ from pathlib import Path
2
+ import numpy as np,yaml;R=Path(__file__).resolve().parents[1];c=yaml.safe_load((R/'conf/config.yaml').read_text());g=np.random.default_rng(3);x=g.normal(size=(8,8,24,48)).astype('f');y=x+.1;p=R/c['data']['path'];p.parent.mkdir(parents=True,exist_ok=True);np.savez(p,input=x,target=y,latitude=np.linspace(-90,90,24));print(p)
scripts/inference.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ from pathlib import Path
2
+ import sys,numpy as np,torch;R=Path(__file__).resolve().parents[1];sys.path.insert(0,str(R));from model.weatherbench2 import *
3
+ c=cfg(R);d=np.load(R/c['data']['path']);z=torch.load(R/c['paths']['checkpoint'],weights_only=True);m=WB2Baseline(**z['model_config']);m.load_state_dict(z['model']);base=m(torch.tensor(d['input'])).detach().numpy();ens=np.stack([base+np.random.default_rng(i).normal(0,.02,base.shape) for i in range(8)]);p=R/c['paths']['predictions'];p.parent.mkdir(parents=True,exist_ok=True);np.savez(p,ensemble=ens,target=d['target'],latitude=d['latitude']);print(p)
scripts/result.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ from pathlib import Path
2
+ import sys,numpy as np,matplotlib;matplotlib.use('Agg');import matplotlib.pyplot as plt;R=Path(__file__).resolve().parents[1];sys.path.insert(0,str(R));from model.weatherbench2 import *
3
+ c=cfg(R);d=np.load(R/c['paths']['predictions']);e=d['ensemble'];t=d['target'];mean=e.mean(0);rmse=float(np.sqrt(np.mean((mean-t)**2)));crps=float(np.mean(abs(e-t[None]))-.5*np.mean(abs(e[:,None]-e[None,:])));spread=float(e.std(0).mean());write(R/c['paths']['evaluation'],{'rmse':rmse,'crps':crps,'spread_skill':spread/(rmse+1e-8)});plt.imshow(mean[0,0]-t[0,0]);p=R/c['paths']['figure'];p.parent.mkdir(parents=True,exist_ok=True);plt.savefig(p);print(p)
scripts/train.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+ import sys,os,numpy as np,torch;import torch.distributed as dist
3
+ from torch.nn.parallel import DistributedDataParallel as DDP
4
+ R=Path(__file__).resolve().parents[1];sys.path.insert(0,str(R));from model.weatherbench2 import *
5
+ c=cfg(R);rank=int(os.getenv('RANK',0));world=int(os.getenv('WORLD_SIZE',1));ddp=world>1
6
+ if ddp:dist.init_process_group('gloo')
7
+ d=np.load(R/c['data']['path']);base=WB2Baseline(**c['model']);m=DDP(base) if ddp else base;opt=torch.optim.Adam(m.parameters(),lr=c['train']['lr']);ids=np.arange(rank,len(d['input']),world);loss=((m(torch.tensor(d['input'][ids]))-torch.tensor(d['target'][ids]))**2).mean();opt.zero_grad();loss.backward();opt.step();v=loss.detach().double()
8
+ if ddp:dist.all_reduce(v);v/=world
9
+ p=R/c['paths']['checkpoint']
10
+ if rank==0:p.parent.mkdir(parents=True,exist_ok=True);torch.save({'model':base.state_dict(),'model_config':c['model']},p);write(R/c['paths']['training_metrics'],{'mse':float(v),'world_size':world});print(p)
11
+ if ddp:dist.destroy_process_group()
weight/.gitkeep ADDED
File without changes