Choosing tau_infer

For v0.7 typed decoding, the replacement for legacy tau_infer is StrictDecodePolicy.rejection_threshold. It is applied to the authoritative canonical denominator score abs(Q_hat) after (P, Q) normalization. A sample inside the threshold keeps its finite core but receives operational REJECT; it is not relabelled as algebraic bottom.

Use this guide when you need to pick one deployment threshold and defend it in terms of saved artifacts rather than ad hoc tuning.

Legacy validation contract (v0.6.1)

Every strict-inference entry point re-validates tau_infer and tau_train through the shared zeroproof.layers._capability validators. Illegal values raise ValueError / TypeError at construction, decoding, checkpoint load, and bundle validation — the historical tau_infer = 0 fail-open path is refused before any prediction is produced.

  • tau_infer must be finite and strictly positive. 0.0, -0.0, negative, NaN, and ±Inf are refused.
  • tau_train is optional. When present it must be finite, strictly positive, and >= tau_infer. tau_train == tau_infer is accepted; tau_train < tau_infer is refused.
  • Both constraints apply identically through: InferenceConfig(...), decode_strict_censored_3way(...), TrainingConfig(...) (its tau_train_min / tau_train_max fields), and validate_bundle(bundle_dir) (reads the metadata tau_infer / tau_train from the exported metadata.json).
  • Eager strict decoders also reject a positive tau_infer that narrows to 0.0 in the backend denominator dtype. Complex denominators use their real component dtype for that check. Promote the denominator dtype or choose a portable threshold before producing a prediction.
  • Exact-zero denominators are classified as bottom independently of the |Q| < tau_infer comparison; tau_infer = 0 remains invalid.
  • A finite denominator above tau_infer is still subject to finite-precision execution. If the computed quotient is non-finite after division, eager strict decoding classifies the sample as a fault bottom before returning.

The rest of this section describes the schema-v1/v2 compatibility decoder. New schema-v3 bundles use StrictDecodePolicy, as shown below.

Default workflow

  1. Start from a held-out split or replay batch that matches deployment.
  2. Normalize every (P, Q) with the canonical gauge and cache abs(Q_hat) plus the task labels you care about.
  3. Sweep candidate thresholds before freezing a bundle.
  4. Record the chosen threshold in the exported bundle's hashed decoder policy.

If you also want to monitor the train/infer gray zone, set tau_train above tau_infer so strict inference can emit gap_mask.

Sweep first, then freeze

The supported post-hoc helper remains tau_infer_sweep_from_q_abs(...) for API compatibility. Pass canonical abs(Q_hat) scores, not raw denominator magnitudes. It turns cached scores into false-positive, false-negative, and bottom-rate curves without rerunning the full model:

from zeroproofml.metrics import tau_infer_sweep_from_q_abs, write_tau_infer_sweep

curves = tau_infer_sweep_from_q_abs(
    q_abs=canonical_denominator_scores,
    is_in_range=is_in_range,
    taus=[1e-6, 3e-6, 1e-5, 3e-5, 1e-4],
)
write_tau_infer_sweep("results/tau_calibration", curves, provenance={"split": "held_out"})

That writes both a machine-readable JSON artifact and a compact Markdown report. Use the sweep to pick the smallest threshold that still meets the deployment's numerical-safety requirement.

Gauge scope: a sweep is comparable across projective rescalings only when its input is the canonical score. Raw abs(Q) data is a legacy, head-specific calibration artifact and must be normalized before it informs a v0.7 policy.

DOSE calibration-set workflow

The DOSE benchmark writes the calibration workflow into the run artifact so the chosen operating point can be audited without rerunning notebooks:

python -m pip install "zeroproofml[benchmarks]"
python -m zeroproofml.benchmarks dose --mode contract --seeds 1 --device cpu

For DOSE runs, the benchmark runner emits:

  • aggregated/dose_operating_points.json
  • aggregated/dose_operating_points.md
  • aggregated/dose_diagnostics.json

dose_operating_points.json selects safety_first, accuracy_first, and direction_aware candidates from the aggregate metrics. It also records the tau_infer / tau_train values observed in each per-seed result. When the seed result includes split provenance, the artifact includes the deterministic calibration/evaluation split recipe and uses the provenance-weighted bottom cost fault_rate + 0.5 * semantic_bottom_rate; otherwise it falls back to the merged bottom_rate.

Treat that JSON file as the release-facing operating-point record. The Markdown sidecar is the human-readable summary for paper reviews and deployment notes.

Practical selection rules

  • Prefer a threshold derived from held-out canonical denominator scores, not a training default.
  • Keep the choice task-specific: censoring, robotics, and RF runs usually want different operating points.
  • If false accepts are the safety risk, bias tau_infer upward.
  • If unnecessary abstention is the main cost, bias tau_infer downward and use gap_mask for extra monitoring.
  • Re-run the sweep whenever the model family, normalization, or input preprocessing changes.

The reference robotics deployment currently retains this pattern under an explicit schema-v2 compatibility export. It does not qualify its raw-|Q| threshold as a v0.7 semantic policy.

Ship the threshold with the bundle

Once chosen, freeze the canonical-score threshold in StrictDecodePolicy and export the raw projective model:

from zeroproofml.inference import StrictDecodePolicy, export_bundle

policy = StrictDecodePolicy(
    rejection_threshold=1e-5,
    ambiguity_band=1e-6,
    coordinate_axis=None,  # use -1 for one shared denominator across the last axis
)
export_bundle(model, (x_example,), "bundle_dir", decode_policy=policy)

metadata.json records the complete decoder policy and its semantic-identity hash, so downstream consumers can verify the exact gate that was shipped.