Command-line reference
Run python -m torch_bsf COMMAND in an environment with PyTorch-BSF installed.
--help works at the top level and on every subcommand. Paths are relative to
the current working directory. The examples below use Python to create files,
so they work with either a POSIX shell or PowerShell.
fit
fit solves weighted least squares. In addition to the shared options:
Option |
Default |
Meaning |
|---|---|---|
|
Required |
Model archive destination, independent of its filename extension. |
|
Disabled |
Log the result using the optional MLflow integration. Requires the
|
|
MLflow configuration |
Explicit tracking URI; requires |
Header and weighted product example
Run this Python code in a fresh working directory. It writes a square’s four
corners and center, a scalar response x + 2*y, and matching weights. All
three training files have one header row:
from pathlib import Path
Path("params.csv").write_text(
"u0,u1,v0,v1\n1,0,1,0\n0,1,1,0\n1,0,0,1\n0,1,0,1\n0.5,0.5,0.5,0.5\n",
encoding="utf-8",
)
Path("values.csv").write_text("response\n0\n1\n2\n3\n1.5\n", encoding="utf-8")
Path("weights.csv").write_text("weight\n1\n1\n1\n1\n4\n", encoding="utf-8")
Path("query.csv").write_text("0.75,0.25,0.5,0.5\n", encoding="utf-8")
python -m torch_bsf fit --params params.csv --values values.csv --weights weights.csv --header 1 --dimensions 1,1 --degree 1 --save square.bsf
python -m torch_bsf predict --model square.bsf --params query.csv --save prediction.csv
The prediction file contains one numeric value, approximately 1.25.
Prediction input has no header; predict has no --header option.
cross-validate
cross-validate uses the shared regression options and the following options:
Option |
Default |
Meaning |
|---|---|---|
|
|
Number of shuffled folds, at least two and at most the observation count. |
|
|
Local random seed for reproducible splits. |
Using the files above:
python -m torch_bsf cross-validate --params params.csv --values values.csv --weights weights.csv --header 1 --dimensions 1,1 --degree 1 --folds 3 --seed 7
The JSON contains success, aggregate metrics (mean_mse, std_mse,
pooled_mse), and folds. Each fold includes zero-based train and
test row indices after header removal, held-out mse / mae metrics,
and solver status. No model is saved, and there is no --save option.
select-degree
select-degree adds required --degrees INTEGER [INTEGER ...] to the shared
regression and validation options. Candidates are nonnegative integers, each
applied to every product factor. --degree is still required to construct
the initial space; it does not restrict the candidate list.
python -m torch_bsf select-degree --params params.csv --values values.csv --weights weights.csv --header 1 --dimensions 1,1 --degree 1 --degrees 0 1 --folds 3 --seed 7 > selection.json
The JSON contains success, best_degree and candidates (each with
degree and validation metrics). All candidates use identical splits.
The eligible candidate with smallest pooled held-out MSE wins; input order
breaks exact ties. Failed candidates remain visible but cannot win. If none
is eligible, best_degree is null and the exit code is 1.
Selection does not refit or save a model. Read best_degree from the report,
then explicitly fit that degree on all observations. This Python snippet runs
the refit without shell-specific JSON processing:
import json
import subprocess
import sys
selection = json.loads(Path("selection.json").read_text(encoding="utf-8"))
if not selection["success"]:
raise RuntimeError("No candidate passed validation")
refit = subprocess.run([
sys.executable, "-m", "torch_bsf", "fit",
"--params", "params.csv", "--values", "values.csv",
"--weights", "weights.csv", "--header", "1", "--dimensions", "1,1",
"--degree", str(selection["best_degree"]), "--save", "selected.bsf",
], capture_output=True, text=True, check=True)
predict
predict reads the saved space and coefficients; it accepts none of the
shared regression options except --params.
Option |
Default |
Meaning |
|---|---|---|
|
Required |
Saved model archive. |
|
Required |
Headerless numeric CSV of barycentric coordinates. |
|
Omitted |
Headerless single column of integer cell IDs, one per parameter row. Required for a multi-cell model; optional for a single-cell model. |
|
Required |
Headerless numeric CSV destination, one row per input and one column per model output. Row order is preserved; values use NumPy scientific notation. |
Multi-cell prediction
Create a model in Python before invoking the CLI. This example uses a segment
and a triangle with constant outputs 3 and 7, respectively, so that
cell routing and padding can be checked independently of fitting:
import numpy as np
import torch
from torch_bsf import BezierModel, BezierSpace, Points
from torch_bsf.geometry import SimploidalSet
from torch_bsf.io import save_model
domain = SimploidalSet()
segment = domain.add_simplex(1)
triangle = domain.add_simplex(2)
space = BezierSpace.on_set(domain, degree=1)
coefficients = torch.full((space.n_controls, 1), 7., dtype=torch.float64)
coefficients[list(space.cells[space.cell_id(segment)].controls)] = 3.
model = BezierModel(space, coefficients)
save_model("multi.bsf", model)
points = Points.from_cells(space, [
(segment, [[0.25, 0.75]]),
(triangle, [[0.2, 0.3, 0.5]]),
])
np.savetxt("multi-params.csv", points.parameters.numpy(), delimiter=",")
np.savetxt("cells.csv", points.cell_ids.numpy(), fmt="%d", delimiter=",")
multi-params.csv contains rows 0.25,0.75,0 and 0.2,0.3,0.5. The
segment row is padded to the saved space width, three columns. Only the active
coordinates for the selected cell are evaluated. Use zero padding for portable
files. Resolve IDs with space.cell_id(handle) or export Points.cell_ids
as above: compiled IDs include faces and need not equal builder insertion order.
python -m torch_bsf predict --model multi.bsf --params multi-params.csv --cell-ids cells.csv --save multi-prediction.csv
This writes two rows, approximately 3 and 7. Omitting --cell-ids for this
model is an input error, even when all requested cells have the same width.
minimize
minimize optimizes a copied initial model using simplex-weighted objectives.
It accepts the following options, and none of the shared regression options:
Option |
Default |
Meaning |
|---|---|---|
|
Required |
Initial saved model. |
|
Required |
Importable differentiable vector objective; see shape contract below. |
|
Required |
Destination for the returned model, including after iteration exhaustion. |
|
|
Positive number of updates. |
|
|
Finite positive constant step size. |
|
|
Positive number of fixed domain samples used for optimization. |
|
|
Local seed for samples and update ordering. |
Save an initial segment model and write the objective module into the working directory using Python:
from torch_bsf import BezierModel, BezierSpace
from torch_bsf.io import save_model
initial = BezierModel(BezierSpace.simplex(1, degree=1), [[0.], [1.]])
save_model("initial.bsf", initial)
Path("objectives.py").write_text(
"import torch\n\n"
"def costs(values):\n"
" x = values[:, 0]\n"
" return torch.stack((x.square(), (x - 1).square()), dim=1)\n",
encoding="utf-8",
)
python -m torch_bsf minimize --init initial.bsf --objective objectives:costs --save optimized.bsf --max-iter 20 --step-size 0.05 --n-samples 100 --seed 0
The module must be on Python’s import path (the current directory works for
this command). costs receives predicted values with shape
(n_samples, n_outputs) and returns differentiable finite objective values
with shape (n_samples, dimension + 1) for a positive-dimensional simplex
of that dimension.
Here one predicted scalar produces two competing costs, matching the segment’s
two barycentric coordinates. The CLI wraps the function with
linear_scalarization and minimizes sum_i coordinate_i * cost_i per row.
Keep operations in PyTorch to preserve gradients.
This callable takes one argument; the Python API’s general
loss(values, points) takes two. Ordinary product coordinates have one
normalization per factor and do not satisfy the scalarization’s single-simplex
sum/shape requirement. Use the Python API with an explicit loss for those
domains or for custom stopping criteria.
Zero-dimensional models are supported by regression and prediction, but CLI
minimization does not support them. Their parameter width is zero: returning
one objective column fails the scalarization’s shape check, and returning zero
columns fails its coordinate-sum check. Use the Python API with a general
loss(values, points) for a constant domain.
The CLI sets an iteration budget without a gradient tolerance. Consequently
this example returns success: false, status: "iteration_limit", exit
code 1, and a ConvergenceWarning on stderr, even if the objective decreased.
It still saves optimized.bsf. Inspect the report before deciding to use it.
Output, failures and saved files
fit, cross-validate, select-degree and minimize print one JSON
object on stdout after returning a result. Warnings go to stderr. predict
writes its CSV and produces no stdout on success. Redirect stdout to capture
JSON independently of warnings. Help text is printed on stdout and exits 0.
For example, a successful fit report has the following structure (additional
diagnostic fields are omitted here; numeric values depend on the data):
{
"success": true,
"status": "solved",
"message": "Least-squares optimum computed.",
"model_saved": true,
"metrics": {"data_mse": 0.0, "objective": 0.0},
"diagnostics": {"solution_available": true}
}
An exhausted minimize report is
{"success": false, "status": "iteration_limit", "objective": 0.16},
with an illustrative objective value. A selection report has the form
{"success": true, "best_degree": 1, "candidates": [...]}.
JSON output uses Python’s allow_nan=True: unavailable or overflowing metrics
may appear as NaN, Infinity or -Infinity. These tokens are accepted
by Python’s JSON reader but are outside strict JSON; consumers must handle them.
Exit code |
Meaning / output |
File behavior |
|---|---|---|
|
Successful result, prediction, or help. |
|
|
A returned numerical result has |
|
|
Argument parsing or caught |
Invalid inputs normally fail before saving. This is not an atomic transaction: a later write or tracking error may occur after an artifact was created. Existing files are not removed or rolled back. |
These codes describe handled paths. Unexpected exceptions, including uncaught
ArithmeticError in minimization, can produce a traceback and process failure
without JSON or a saved returned model. Do not interpret every exit 1 as a
structured numerical result. Check stdout and the report fields.
For a reproducible input error using the headered files above:
python -m torch_bsf fit --params params.csv --values values.csv --header 1 --dimensions 1,1 --degree 1 --solver sparse --diagnostics full --save invalid.bsf
This reports error: full SVD diagnostics require --solver=dense on stderr,
exits 2, prints no JSON and creates no invalid.bsf. Likewise, headers in a
prediction CSV fail numeric loading; strip them before prediction.