Download scripts/inference.py from OneScience-Group/FPINNs: direct link, hf CLI and curl.
- Browser
- Download file 5.19 kB
-
https://huggingface.co/OneScience-Group/FPINNs/resolve/c29de7580a3da003de6041b5fa8e20aa8d3886ea/scripts/inference.py
- Command line
-
hf download hf://OneScience-Group/FPINNs@c29de7580a3da003de6041b5fa8e20aa8d3886ea/scripts/inference.py
-
curl -L -o inference.py https://huggingface.co/OneScience-Group/FPINNs/resolve/c29de7580a3da003de6041b5fa8e20aa8d3886ea/scripts/inference.py
5.19 kB
| from __future__ import annotations | |
| import sys | |
| from collections.abc import Mapping | |
| from pathlib import Path | |
| import matplotlib | |
| matplotlib.use("Agg") | |
| import matplotlib.pyplot as plt | |
| import numpy as np | |
| import torch | |
| PROJECT_ROOT = Path(__file__).resolve().parents[1] | |
| sys.path.insert(0, str(PROJECT_ROOT)) | |
| sys.path.insert(0, str(Path(__file__).resolve().parent)) | |
| from common import ( # noqa: E402 | |
| checkpoint_state, | |
| load_config, | |
| project_path, | |
| relative_l2, | |
| resolve_device, | |
| resolve_dtype, | |
| ) | |
| from data_utils import batched_predict, load_allen_cahn # noqa: E402 | |
| from model.fpinn import build_model # noqa: E402 | |
| DEFAULT_CONFIG = PROJECT_ROOT / "conf" / "config.yaml" | |
| TASKS = ("forward", "inverse") | |
| def main() -> None: | |
| config_path = DEFAULT_CONFIG.resolve() | |
| config = load_config(config_path) | |
| common = config["common"] | |
| task = str(common["task"]).lower() | |
| if task not in TASKS: | |
| raise ValueError("common.task must be one of: forward, inverse") | |
| task_config = config["tasks"][task] | |
| device = resolve_device(str(common["device"])) | |
| dtype = resolve_dtype(str(common["dtype"])) | |
| weight_dir = project_path(common["weight_dir"], PROJECT_ROOT) | |
| result_dir = project_path(common["result_dir"], PROJECT_ROOT) | |
| checkpoint_path = weight_dir / task_config["output"]["checkpoint_name"] | |
| if not checkpoint_path.is_file(): | |
| raise FileNotFoundError( | |
| f"checkpoint not found: {checkpoint_path}. Run scripts/train.py first." | |
| ) | |
| checkpoint = torch.load(checkpoint_path, map_location="cpu", weights_only=True) | |
| if not isinstance(checkpoint, Mapping): | |
| raise ValueError(f"invalid FPINN checkpoint: {checkpoint_path}") | |
| state, metadata = checkpoint_state(checkpoint) | |
| checkpoint_task = metadata.get("task", task) | |
| if checkpoint_task != task: | |
| raise ValueError( | |
| f"checkpoint task is {checkpoint_task}, but common.task is {task}" | |
| ) | |
| model_config = metadata.get("model_config", config["model"]) | |
| pde_config = metadata.get("pde_config", task_config["pde"]) | |
| data_config = dict(metadata.get("data_config", config["data"])) | |
| data_path = project_path(data_config["mat_file"], PROJECT_ROOT) | |
| dataset = load_allen_cahn(data_path) | |
| model = build_model(task, model_config, pde_config, dtype).to( | |
| device=device, dtype=dtype | |
| ) | |
| model.load_state_dict(state, strict=True) | |
| model.eval() | |
| prediction = batched_predict( | |
| model, | |
| np.asarray(dataset["coordinates"]), | |
| int(data_config["evaluation_batch_size"]), | |
| device, | |
| dtype, | |
| ) | |
| exact = np.asarray(dataset["exact"]) | |
| error = relative_l2(prediction, exact) | |
| rmse = float(np.sqrt(np.mean((prediction - exact) ** 2))) | |
| max_error = float(np.max(np.abs(prediction - exact))) | |
| result_dir.mkdir(parents=True, exist_ok=True) | |
| predictions_path = result_dir / task_config["output"]["predictions_name"] | |
| figure_path = result_dir / task_config["output"]["figure_name"] | |
| payload = { | |
| "coordinates": dataset["coordinates"], | |
| "exact": exact, | |
| "prediction": prediction, | |
| "relative_l2": error, | |
| "rmse": rmse, | |
| "max_abs_error": max_error, | |
| } | |
| if task == "inverse": | |
| payload["lambda_1"] = model.lambda_1.item() | |
| payload["lambda_2"] = model.lambda_2.item() | |
| np.savez_compressed(predictions_path, **payload) | |
| shape = dataset["grid_shape"] | |
| exact_grid = exact.reshape(shape) | |
| prediction_grid = prediction.reshape(shape) | |
| error_grid = np.abs(prediction_grid - exact_grid) | |
| extent = ( | |
| float(np.min(dataset["space"])), | |
| float(np.max(dataset["space"])), | |
| float(np.min(dataset["time"])), | |
| float(np.max(dataset["time"])), | |
| ) | |
| figure, axes = plt.subplots(1, 3, figsize=(15, 4)) | |
| for axis, title, field in zip( | |
| axes, | |
| ("Exact", "FPINN", "Absolute error"), | |
| (exact_grid, prediction_grid, error_grid), | |
| strict=True, | |
| ): | |
| image = axis.imshow( | |
| field, | |
| extent=extent, | |
| origin="lower", | |
| aspect="auto", | |
| cmap="viridis" if title != "Absolute error" else "hot", | |
| ) | |
| axis.set_title(title) | |
| axis.set_xlabel("x") | |
| axis.set_ylabel("t") | |
| figure.colorbar(image, ax=axis) | |
| title = f"Allen-Cahn {task} | L2={error:.3e}" | |
| if task == "inverse": | |
| title += ( | |
| f" | lambda=({model.lambda_1.item():.3e}, " | |
| f"{model.lambda_2.item():.3e})" | |
| ) | |
| figure.suptitle(title) | |
| figure.tight_layout() | |
| figure.savefig(figure_path, dpi=150) | |
| plt.close(figure) | |
| print(f"Config: {config_path}") | |
| print(f"Task: {task}") | |
| print(f"Data: {data_path}") | |
| print(f"Checkpoint: {checkpoint_path}") | |
| print(f"Device: {device}") | |
| print(f"Relative L2={error:.6e}, RMSE={rmse:.6e}, MaxAbs={max_error:.6e}") | |
| if task == "inverse": | |
| print( | |
| f"Recovered lambda_1={model.lambda_1.item():.8e}, " | |
| f"lambda_2={model.lambda_2.item():.8e}" | |
| ) | |
| print(f"Predictions: {predictions_path}") | |
| print(f"Plot: {figure_path}") | |
| if __name__ == "__main__": | |
| main() | |