| from __future__ import annotations |
|
|
| import json |
| from pathlib import Path |
|
|
| import gradio as gr |
| import numpy as np |
| import plotly.graph_objects as go |
| import torch |
| from model import ConditionalNeuralProcess |
| from safetensors.torch import load_file |
|
|
| ARTIFACT_DIR = Path(__file__).resolve().parent / "artifacts" / "neural-process-pocket" |
| MODEL = ConditionalNeuralProcess() |
| MODEL.load_state_dict(load_file(ARTIFACT_DIR / "model.safetensors")) |
| MODEL.eval() |
| REPORT = json.loads((ARTIFACT_DIR / "evaluation.json").read_text(encoding="utf-8")) |
|
|
|
|
| @torch.inference_mode() |
| def infer_function( |
| amplitude: float, |
| phase: float, |
| frequency: float, |
| context_points: int, |
| seed: int, |
| ) -> tuple[go.Figure, dict]: |
| rng = np.random.default_rng(int(seed)) |
| context_x = np.sort(rng.uniform(-5, 5, int(context_points))).astype(np.float32) |
| context_y = amplitude * np.sin(frequency * context_x + phase) |
| target_x = np.linspace(-5, 5, 300, dtype=np.float32) |
| true_y = amplitude * np.sin(frequency * target_x + phase) |
| mean, std = MODEL( |
| torch.from_numpy(context_x)[None, :, None], |
| torch.from_numpy(context_y.astype(np.float32))[None, :, None], |
| torch.from_numpy(target_x)[None, :, None], |
| ) |
| mean = mean[0, :, 0].numpy() |
| std = std[0, :, 0].numpy() |
| figure = go.Figure() |
| figure.add_trace( |
| go.Scatter( |
| x=np.concatenate([target_x, target_x[::-1]]), |
| y=np.concatenate([mean - 1.645 * std, (mean + 1.645 * std)[::-1]]), |
| fill="toself", |
| name="90% predictive interval", |
| line={"color": "rgba(0,0,0,0)"}, |
| ) |
| ) |
| figure.add_trace(go.Scatter(x=target_x, y=true_y, name="True function")) |
| figure.add_trace(go.Scatter(x=target_x, y=mean, name="CNP mean")) |
| figure.add_trace( |
| go.Scatter(x=context_x, y=context_y, mode="markers", name="Context") |
| ) |
| figure.update_layout(template="plotly_dark", xaxis_title="x", yaxis_title="y") |
| metrics = { |
| "live_rmse": float(np.sqrt(np.mean((mean - true_y) ** 2))), |
| "context_points": int(context_points), |
| "verified_500_task_rmse": REPORT["benchmark"][ |
| "conditional_neural_process" |
| ]["rmse"], |
| "verified_90_percent_coverage": REPORT["benchmark"][ |
| "conditional_neural_process" |
| ]["coverage_90"], |
| } |
| return figure, metrics |
|
|
|
|
| with gr.Blocks(title="Neural Process Pocket") as demo: |
| gr.Markdown( |
| "# Neural Process Pocket\n" |
| "Give the model a few observations and watch it infer a complete function " |
| "distribution with a learned uncertainty band." |
| ) |
| with gr.Row(): |
| amplitude = gr.Slider(0.1, 5.0, value=2.5, step=0.1, label="Amplitude") |
| phase = gr.Slider(0, 6.28, value=1.0, step=0.05, label="Phase") |
| frequency = gr.Slider(0.8, 1.2, value=1.0, step=0.02, label="Frequency") |
| context = gr.Slider(3, 20, value=5, step=1, label="Context points") |
| seed = gr.Slider(0, 100_000, value=2141, step=1, label="Seed") |
| initial = infer_function(2.5, 1.0, 1.0, 5, 2141) |
| chart = gr.Plot(value=initial[0]) |
| metrics = gr.JSON(value=initial[1]) |
| button = gr.Button("Infer function distribution", variant="primary") |
| button.click( |
| infer_function, |
| inputs=[amplitude, phase, frequency, context, seed], |
| outputs=[chart, metrics], |
| ) |
|
|
|
|
| if __name__ == "__main__": |
| demo.launch() |
|
|
|
|