Source code for pypielm.io.export
"""Model export to portable inference formats."""
from __future__ import annotations
from pathlib import Path
from typing import TYPE_CHECKING
import torch
if TYPE_CHECKING:
from pypielm.core.base import BasePIELM
def _make_example_input(
model: BasePIELM,
example_input: torch.Tensor | None,
input_dim: int,
) -> torch.Tensor:
if example_input is not None:
return example_input
# Try to infer input_dim from the feature map
fm = getattr(model, "_fm", None)
if fm is not None:
input_dim = getattr(fm, "input_dim", input_dim)
# Use the model's dtype for the dummy input
dtype = getattr(model, "dtype", torch.float64)
return torch.zeros(1, input_dim, dtype=dtype)
[docs]
def to_onnx(
model: BasePIELM,
path: str | Path,
*,
example_input: torch.Tensor | None = None,
input_dim: int = 2,
opset_version: int = 17,
) -> None:
"""Export *model* to ONNX format.
Requires ``onnx`` and ``onnxruntime`` (install via ``pip install pypielm[export]``).
Args:
model: A fitted PIELM model.
path: Destination ``.onnx`` file path.
example_input: Representative input tensor ``(1, d)`` for tracing.
If ``None``, a zero tensor of shape ``(1, input_dim)`` is used.
input_dim: Spatial dimension *d* (used when ``example_input`` is None).
opset_version: ONNX opset version.
"""
try:
import onnx # noqa: F401
except ImportError as e:
raise ImportError(
"ONNX export requires 'onnx'. Install with: pip install onnx onnxruntime"
) from e
path = Path(path)
path.parent.mkdir(parents=True, exist_ok=True)
x = _make_example_input(model, example_input, input_dim)
model.eval()
torch.onnx.export(
model,
(x,),
str(path),
opset_version=opset_version,
input_names=["X"],
output_names=["u"],
dynamic_axes={"X": {0: "batch_size"}, "u": {0: "batch_size"}},
)
[docs]
def to_torchscript(
model: BasePIELM,
path: str | Path,
*,
example_input: torch.Tensor | None = None,
input_dim: int = 2,
method: str = "trace",
) -> torch.jit.ScriptModule:
"""Export *model* to TorchScript.
Args:
model: A fitted PIELM model.
path: Destination ``.pt`` file path.
example_input: Representative input for tracing.
input_dim: Spatial dimension (used when ``example_input`` is None).
method: ``'trace'`` or ``'script'``.
Returns:
The compiled :class:`torch.jit.ScriptModule`.
"""
path = Path(path)
path.parent.mkdir(parents=True, exist_ok=True)
x = _make_example_input(model, example_input, input_dim)
model.eval()
if method == "trace":
scripted = torch.jit.trace(model, x)
elif method == "script":
scripted = torch.jit.script(model)
else:
raise ValueError(f"method must be 'trace' or 'script', got '{method}'")
torch.jit.save(scripted, str(path))
return scripted