Float→quantized boundary marker — the entry stub of a quantizable model.
Placed in a float model at the point where the quantized region should
begin. On its own it does nothing to the numerics; it exists so the
quantization tooling has a named site to attach an activation observer and,
later, to swap in a runtime quantizer. It is the mirror image of
DeQuantStub, which marks the exit.
Its behaviour depends on which workflow prepared the model:
- PTQ (
lucid.quantization.prepare) attaches a bare observer as a forward hook and leaves the stub an identity — the observer passively records the activation range while calibration data flows through. - QAT (
lucid.quantization.prepare_qat) attaches alucid.quantization.FakeQuantizeasactivation_post_process; the stub then fake-quantizes its (floating-point) input on every forward so the network trains against the same rounding it will meet at inference.
Once calibrated, lucid.quantization.convert replaces the stub with a
runtime Quantize. In the QAT path the fake-quantize applied to a
real-valued input is
with the observed activation (scale, zero_point) and grid
bounds (0, 255 for the default quint8).
Integer inputs (e.g. token indices) are passed through untouched.
Parameters
qconfigobject= NoneNone (the
default) no qconfig attribute is set and the stub inherits the
surrounding model's config during prepare / convert.Notes
- A raw
QuantStub()is a no-op identity; it only acquires anactivation_post_processafterprepare/prepare_qatruns. - Use
QuantWrapperto bolt aQuantStub/DeQuantStubpair onto a model that has no explicit boundaries of its own. - It converts to
Quantize, which carries the calibrated qparams as buffers; the stub itself holds no scale / zero-point.
Examples
>>> import lucid, lucid.nn as nn
>>> class Net(nn.Module):
... def __init__(self) -> None:
... super().__init__()
... self.quant = nn.quantized.QuantStub()
... self.fc = nn.Linear(4, 2)
... self.dequant = nn.quantized.DeQuantStub()
... def forward(self, x):
... return self.dequant(self.fc(self.quant(x)))
A stub used *before* prepare is a plain identity — the common mistake is
to expect it to quantize on its own:
>>> stub = nn.quantized.QuantStub() # no observer attached yet
>>> x = lucid.randn(3)
>>> bool((stub(x) == x).all().item()) # identity until prepare() runs
TrueSee Also
- lucid.nn.quantized.DeQuantStub—The matching exit-side boundary marker.
- lucid.nn.quantized.Quantize—The runtime form this stub converts into.
- lucid.nn.quantized.QuantWrapper—Wraps a model in a stub pair.
- lucid.quantization.prepare—Attaches the observer this stub feeds.
Used by 1
Constructors
1Instance methods
1Identity for PTQ (a hook observes); fake-quant for QAT.
In QAT prepare_qat attaches a FakeQuantize as
activation_post_process — apply it so the input is fake-quantized
during training. In PTQ it's a bare observer fed by a forward hook,
so the stub stays an identity.