PPNN / scripts /inference.py
zhangrenchao's picture
Upload folder using huggingface_hub
6ff9439 verified
Raw
History Blame Contribute Delete
2.72 kB
"""Run all PPNN replicas and save the complete verification payload."""
import sys
from pathlib import Path
import numpy as np
import torch
import yaml
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT))
from model.ppnn import FORMAT_VERSION, PPNN, ensemble_features
def main():
config = yaml.safe_load((ROOT / "conf/config.yaml").read_text())
data = np.load(ROOT / config["data"]["file"])
checkpoint = torch.load(ROOT / config["paths"]["checkpoint"], map_location="cpu", weights_only=False)
if str(data["format_version"]) != FORMAT_VERSION or checkpoint.get("format_version") != FORMAT_VERSION:
raise ValueError("data/checkpoint format version mismatch")
if data["ensemble"].shape[1:] != (50, 18) or len(data["station_id"]) != 537 or int(data["lead_hours"]) != 48:
raise ValueError("inference requires 50 members, 18 variables, 537 stations, and 48h lead")
scaling = checkpoint["scaling"]
continuous = ensemble_features(torch.from_numpy(data["ensemble"]), torch.from_numpy(data["auxiliary"]))
continuous = (continuous - scaling["feature_mean"]) / scaling["feature_std"]
station = torch.from_numpy(data["station_index"])
mus, sigmas = [], []
for state in checkpoint["model"]:
model = PPNN(int(checkpoint["model_config"]["hidden_size"]), eps=float(checkpoint["model_config"]["sigma_epsilon"]))
model.load_state_dict(state)
model.eval()
with torch.no_grad():
mu_scaled, sigma_scaled = model(continuous, station)
mus.append(mu_scaled * scaling["target_std"] + scaling["target_mean"])
sigmas.append(sigma_scaled * scaling["target_std"])
# The paper averages Gaussian parameters from random networks; this is not a mixture distribution.
mu = torch.stack(mus).mean(0).numpy()
sigma = torch.stack(sigmas).mean(0).numpy()
target = data["target"]
raw_t2m = data["ensemble"][:, :, 0]
if not all(np.isfinite(x).all() for x in (mu, sigma, target, raw_t2m)) or not np.all(sigma > 0):
raise RuntimeError("inference output is non-finite or has non-positive sigma")
output = ROOT / config["paths"]["inference"]
output.parent.mkdir(parents=True, exist_ok=True)
np.savez_compressed(output, mu=mu, sigma=sigma, targets=target, raw_ensemble_t2m=raw_t2m,
station_index=data["station_index"], station_id=data["station_id"], date_index=data["date_index"],
dates=data["dates"], lead_hours=data["lead_hours"], format_version=np.asarray(FORMAT_VERSION))
print(f"saved={output.relative_to(ROOT)} samples={len(mu)} replicas={len(mus)} raw_ensemble={raw_t2m.shape}")
if __name__ == "__main__":
main()