Reproducibility

A representation you cannot reproduce is a representation you cannot trust in production or in a paper. PreTab treats reproducibility as a contract: deterministic fitting, a portable declarative spec, a stable fingerprint, and an immutable lifecycle. This page covers all four.

Deterministic fitting

random_state seeds every stochastic step: the target-aware selectors, k-means landmark placement, and the randomized feature maps. Set it to an integer whenever you need repeatable output, for example in tests or published experiments.

from pretab import Preprocessor

pre = Preprocessor(numerical_method="rbf", random_state=0)

Note

With a fixed random_state, repeated fits on the same data produce identical output. Methods with no stochastic component ignore the seed. The standalone kernel approximations (RandomFourierFeaturesTransformer, NystroemFeaturesTransformer) accept random_state directly; they are fit outside Preprocessor since they operate on the whole feature block.

Portable serialization

to_spec writes a fitted Preprocessor to a versioned, declarative schema, and from_spec reconstructs it. The spec records the schema and library versions, the resolved parameters, and the per-representation fitted state (parameters, knots, centers, columns, scaling).

spec = pre.to_spec()                 # returns a dict
pre.to_spec("representation.json")   # or writes JSON to a path

restored = Preprocessor.from_spec("representation.json")

Important

Load specs only from trusted sources. Reconstruction restricts imports to pretab, scikit-learn, numpy, and scipy, reconstructs dataclasses only from an exact, closed allow-list, and bypasses estimator initialization and pickle hooks. These restrictions are not a sandbox: importing library modules can still execute code. Use the same PreTab and dependency versions when restoring; recorded versions are informational, and cross-version compatibility is not guaranteed.

Supported built-in representations reproduce transform bit-for-bit in the same environment. Third-party representations and pretrained language models are not supported by the JSON serializer; unsupported state raises PretabSerializationError.

Fingerprint

fingerprint_ is a SHA-256 hash over a canonical view of the fitted representation: the resolved config, the schema, the fitted parameters, the output-column order, the seeds, the library versions, and the output precision.

pre.fit(df, y)
pre.fingerprint_

Inference reports and advisory lifecycle flags are excluded from the fingerprint. The fingerprint is deterministic within a process and across processes, and it survives a to_spec / from_spec round-trip. Two preprocessors with the same fingerprint will produce the same output; a change to config, data, seed, or version changes the fingerprint.

Tip

Log the fingerprint alongside model metrics. If it changes unexpectedly between runs, your representation changed, which is exactly the signal you want before you chase a metric regression.

reproducibility_report() returns a structured summary for logging: the fingerprint, versions, seed, output dtype and format, output widths, and the per-feature families.

pre.reproducibility_report()

Immutable lifecycle

A fitted representation moves through a small set of explicit states, which prevents accidental mutation of something you intend to deploy.

State

Meaning

UNFITTED

Constructed, not yet fit.

FITTED

Fit and ready to transform.

FROZEN

Locked against parameter changes.

STALE

Marked as no longer current, with a reason.

pre.freeze()          # lock it
pre.is_frozen()       # True
pre.set_params(...)   # raises FrozenRepresentationError while frozen

Freezing is useful when a representation is validated and about to ship. To make a fresh, unfrozen copy, use clone_unfitted(). To retrain, refit(X, y) returns a new fitted object and leaves the original untouched, and mark_stale(reason) records why an existing one should no longer be used.

Warning

fit, fit_transform, and set_params on a frozen preprocessor raise FrozenRepresentationError. This is deliberate: a deployed representation should not silently change shape. Use refit to produce a new object instead of mutating the old one.

Where to go next