Source code for unilab.training.onnx_export

"""ONNX export and onnxruntime numeric verification helpers for play entrypoints."""

from __future__ import annotations

import numpy as np
import torch


[docs] def export_policy_onnx( export_module: torch.nn.Module, onnx_path: str, export_inputs: tuple[torch.Tensor, ...], *, input_names: list[str], output_names: list[str] | None = None, opset_version: int = 17, ) -> None: """Export ``export_module`` to ``onnx_path`` and print the artifact path. Args: export_module: Module traced by ``torch.onnx.export``. onnx_path: Destination file path for the exported graph. export_inputs: Positional example inputs matching ``input_names``. input_names: ONNX input names, aligned positionally with ``export_inputs``. output_names: ONNX output names; defaults to ``["action"]``. opset_version: ONNX opset version; defaults to 17. """ if output_names is None: output_names = ["action"] with torch.inference_mode(): torch.onnx.export( export_module, export_inputs, onnx_path, input_names=input_names, output_names=output_names, opset_version=opset_version, ) print(f"Exported actor ONNX to {onnx_path}")
[docs] def verify_policy_onnx( export_module: torch.nn.Module, onnx_path: str, verify_inputs: tuple[torch.Tensor, ...], *, input_names: list[str], max_diff_tol: float = 1e-4, ) -> tuple[float, float]: """Compare PyTorch and ONNX Runtime outputs on identical inputs. Runs ``export_module`` and the exported graph at ``onnx_path`` on ``verify_inputs``, prints the max/mean absolute difference, and prints a warning when the max difference exceeds ``max_diff_tol``. Args: export_module: Module that was exported to ``onnx_path``. Tuple outputs are compared on their first element. onnx_path: Exported ONNX graph to verify. verify_inputs: Positional inputs matching ``input_names``. input_names: ONNX input names, aligned positionally with ``verify_inputs``. max_diff_tol: Absolute max-difference tolerance before warning. Returns: ``(max_diff, mean_diff)`` between PyTorch and ONNX Runtime outputs. """ import onnxruntime as ort sess = ort.InferenceSession(onnx_path, providers=["CPUExecutionProvider"]) with torch.inference_mode(): pt_output = export_module(*verify_inputs) if isinstance(pt_output, tuple): pt_output = pt_output[0] pt_np = pt_output.cpu().numpy() onnx_inputs = { name: value.cpu().numpy().astype(np.float32) for name, value in zip(input_names, verify_inputs, strict=True) } onnx_output = sess.run(None, onnx_inputs)[0] max_diff = float(np.max(np.abs(pt_np - onnx_output))) mean_diff = float(np.mean(np.abs(pt_np - onnx_output))) print(f"ONNX vs PyTorch — max_diff: {max_diff:.2e}, mean_diff: {mean_diff:.2e}") if max_diff > max_diff_tol: print("WARNING: ONNX output diverges from PyTorch!") else: print("ONNX export verified OK.") return max_diff, mean_diff