autofit.ClipperPriorBox#
- class ClipperPriorBox[source]#
Bases:
AbstractClipperHard projection onto the prior support, inset to stay strictly inside it.
The inset is keyed on the kind of each bound. Collapsing these three cases into one relative
margin * (upper - lower)is the obvious implementation and it is wrong in two separate ways, both silent:Two-sided finite (
UniformPrior,LogUniformPrior,TruncatedGaussianPrior) — inset bymarginrelative to the box width. This is deliberately not for prior support: those priors are inclusive at the limit (log_prioris finite exactly on the bound), so clipping onto the bound would already be valid. It is to avoid parking a lane exactly on a prior edge, where the model’s own transforms are prone to singularities (arctan2/sqrtat exactly 0) — the same reasonMultiStartGradientdraws its broad starts from the interior(0.15, 0.85)of the unit cube rather than from(0, 1).Unbounded (
GaussianPrior) — no inset, and critically no width arithmetic at all.lower + margin * (upper - lower)evaluates-inf + inf, which isNaN; clipping againstNaNbounds turns the coordinate intoNaNand the whole objective with it. That failure looks exactly like the lane death this class exists to prevent, so the guarantee that an unbounded coordinate passes through untouched holds only if the width is never computed for it.Half-open and exclusive (
LogGaussianPrior, whose support is(0, inf)) — inset by an absolutestrict_epsilon. A relative margin is identically zero here, there being no finite width, so it would clip exactly onto0.0, where the support is strict andlog_prioris-inf. Only an absolute nudge lands strictly inside. Which bounds are exclusive is read off the prior’slower_limit_strict/upper_limit_strict, never inferred from its type.
- Parameters:
margin (
float) – The relative inset applied to two-sided finite bounds, as a fraction of the box width.strict_epsilon (
float) – The absolute inset applied to half-open bounds whose support excludes the limit itself. Deliberately small: the floor it produces is a very low-density point, but it is finite, and the resulting steep prior gradient is what pushes the lane back into the bulk rather than leaving it dead.
Methods
The
(lower, upper)box, in physical parameter order.Project
vectoronto the prior support.- bounds_from_model(model)[source]#
The
(lower, upper)box, in physical parameter order.Unbounded coordinates are
-inf/+inf. The two arrays are returned separately because that is the shapeprojectbroadcasts against.Note that this is not the shape
scipy.optimize.minimizeaccepts: it reads a(lower, upper)tuple as a sequence of ``(min, max)`` pairs, which for a two-parameter model silently produces a wrong fit rather than an error. Callers handing these to scipy must build an explicitscipy.optimize.Bounds— see_bounds_from.- Parameters:
model – The model whose priors define the support.
- project(vector, model, xp=<module 'numpy' from '/home/docs/checkouts/readthedocs.org/user_builds/pyautofit/envs/latest/lib/python3.12/site-packages/numpy/__init__.py'>, scale=None, bijector=None)[source]#
Project
vectoronto the prior support.- Parameters:
vector – A parameter vector, either a single
(n_params,)vector or a batched(n_starts, n_params)array of them. Broadcasting handles both, so novmapis required of the caller. Physical unlessscaleorbijectoris given, in which case it is in that change of variables’ coordinates.model – The model whose priors define the support.
xp – The array module,
numpyorjax.numpy.scale – The per-parameter step scale from a
scaler, when the caller is stepping inphi = theta / scalerather than in physical parameters. The bounds are divided by it, so the projection happens in the caller’s own coordinates and no round-trip through physical space is needed. Scales are strictly positive, so dividing preserves the ordering of each(lower, upper)pair and+/-infstay+/-inf. Mutually exclusive withbijector.bijector – A resolved
AbstractBijector(.from_modelalready called), when the caller is stepping inphi = bijector.forward(theta). The inset bounds are computed in physical space (kind-aware — see the module docstring) and then mapped throughbijector.bounds_forward, which commutes with clipping because every bijector kind is monotone increasing. Mutually exclusive withscale.
- Returns:
A
(projected, clipped_mask)pair.clipped_maskis boolean, the sameshape as
vector, andTrueexactly where a coordinate was moved.