import sys from pathlib import Path # 获取项目根目录(inference.py上级的上级) root_path = Path(__file__).parent.parent sys.path.append(str(root_path)) import torch import os import glob import numpy as np import h5py from tqdm import tqdm from model.dgmr import DGMR from onescience.utils.YParams import YParams from onescience.datapipes.climate import ERA5Datapipe def get_stats(data_dir, channels): """从新版 h5 中读取变量列表与归一化参数(均值/标准差)""" h5_files = sorted(glob.glob(os.path.join(data_dir, "data", "*.h5"))) with h5py.File(h5_files[0], "r") as f: ds = f["fields"] all_variables = [v.decode() if isinstance(v, bytes) else v for v in ds.attrs["variables"]] mu = f["global_means"][:] # [1, C, 1, 1] std = f["global_stds"][:] channel_indices = [all_variables.index(v) for v in channels] means = mu[:, channel_indices, :, :] stds = std[:, channel_indices, :, :] return means, stds if __name__ == "__main__": current_path = os.getcwd() sys.path.append(current_path) ## Model config init config_file_path = os.path.join(current_path, "conf/config.yaml") cfg = YParams(config_file_path, "model") ## DataLoader init cfg_data = YParams(config_file_path, "datapipe") means, stds = get_stats(cfg_data.dataset.data_dir, cfg_data.dataset.channels) cfg['N_in_channels'] = len(cfg_data.dataset.channels) cfg['N_out_channels'] = len(cfg_data.dataset.channels) datapipe = ERA5Datapipe( dataset_dir=cfg_data.dataset.data_dir, used_variables=cfg_data.dataset.channels, used_years=cfg_data.dataset.test_time, distributed=False, input_steps=cfg.num_context, output_steps=cfg.forecast_steps, batch_size=1, num_workers=4, ) test_dataloader, _ = datapipe.get_dataloader("test") device = "cuda:0" if torch.cuda.is_available() else "cpu" ckpt = torch.load(f"{cfg.checkpoint_dir}/model_bak.pth", map_location=device, weights_only=False) model = DGMR( forecast_steps=cfg.forecast_steps, num_context=cfg.num_context, input_channels=cfg.input_channels, output_shape=cfg.output_shape, conv_type=cfg.conv_type, latent_channels=cfg.latent_channels, context_channels=cfg.context_channels, generation_steps=cfg.generation_steps, grid_lambda=cfg.grid_lambda, precip_weight_cap=cfg.precip_weight_cap, ).to(device) model.load_state_dict(ckpt["model_state_dict"]) model.eval() os.makedirs('result/output/', exist_ok=True) print(f"📂 infer results will be generated to './result/output/'") with torch.no_grad(): for data in tqdm(test_dataloader, desc="Inferring testset", unit="batch"): invar = data[0].to(device, dtype=torch.float32) # [1, num_context, C, H, W] gen = model.generator(invar).cpu().numpy() # [1, forecast_steps, C, H, W] for t in range(gen.shape[1]): fname = data[4][cfg.num_context + t][0] # 该预测帧对应的时刻 pred_var = gen[0, t] # [C, H, W] pred_var = pred_var * stds + means np.save(f"result/output/{fname}.npy", pred_var)