FixedQParamsObserver
ObserverBaseFixedQParamsObserver(scale: float, zero_point: int, qscheme: QScheme = per_tensor_affine, qdtype: QDtype = quint8, eps: float = 1e-08)Observer with a fixed (scale, zero_point) — no statistics collected.
For ops whose output range is known a priori, calibration is pointless: the grid
can be fixed once and for all. The canonical cases are bounded activations —
sigmoid → [0, 1], softmax → [0, 1], tanh → [-1, 1] — where
the ideal (scale, zero_point) is a closed-form function of the dtype grid, not
something the data can improve on. FixedQParamsObserver carries that fixed pair,
makes forward a pure identity (no statistics gathered), and returns the supplied
qparams verbatim from calculate_qparams.
When to pick it. Use it on the output of a range-bounded op so calibration does
not waste effort (or worse, under-shoot the true bound) estimating a range you
already know. For a sigmoid/softmax output on the unsigned quint8 grid
[0, 255] the natural choice is scale = 1/256, zero_point = 0 (mapping
[0, 1] onto the full grid); a tanh output [-1, 1] uses scale = 2/256
with a mid-grid zero_point. For every unbounded tensor, use a statistics-collecting
observer (MinMaxObserver, HistogramObserver, …) instead.
There is no statistic and no reduction — the qparams are the constants themselves:
independent of any observed data.
Parameters
scalefloatzero_pointint0 maps to.epsfloat= 1e-8ObserverBase; unused because the
scale is fixed (never derived, so never floored).Attributes
Notes
- Identity forward.
forwardreturnsxunchanged and collects nothing — the two buffers are set once at construction and never move. - No calibration needed.
calculate_qparamsnever raises (unlikePlaceholderObserver); it simply returns the stored(scale, zero_point), so it is valid to call immediately after construction with no forward passes. - Buffers, not stats.
scale/zero_pointare registered buffers, so they persist throughstate_dictand move with.to(device)like any other buffer. - Metadata fields.
qscheme/epsare stored for interface symmetry but do not affect the returned qparams.
Examples
A fixed observer for a sigmoid output on the quint8 grid — the [0, 1]
range maps onto [0, 255] with scale = 1/256:
>>> import lucid.quantization as Q
>>> obs = Q.FixedQParamsObserver(scale=1.0 / 256, zero_point=0)
>>> scale, zero_point = obs.calculate_qparams() # valid with no calibration
>>> round(scale.item(), 6), int(zero_point.item())
(0.003906, 0)
The forward is a pure identity — feeding data changes nothing:
>>> import lucid
>>> before = obs.scale.item()
>>> _ = obs(lucid.randn(4, 4))
>>> obs.scale.item() == before
TrueSee Also
- lucid.quantization.PlaceholderObserver—Dtype carrier whose qparams instead raise.
- lucid.quantization.MinMaxObserver—Statistics-collecting observer for unbounded ops.
- lucid.quantization.calculate_qparams—The range-based reduction this observer skips.
- lucid.quantization.FakeQuantize—Wraps an observer for QAT.