Expand description
Crate-wide control of pseudo-random number generation for reproducibility Crate-wide control of pseudo-random number generation for reproducibility
Most randomized components in the crate draw their RNG through make_rng (or its sibling
make_rng_opt, for callers that stay deterministic unless explicitly seeded). A single
set_global_seed call makes them reproducible together. This routes randomness through one
entry point for:
- neural-network components: weight initialization, dropout/noise masks, and the
Sequentialminibatch shuffle - machine-learning estimators: k-means, SVC/LinearSVC, MeanShift, Isolation Forest, and others
- utilities:
train_test_split, t-SNE
§Seed resolution
make_rng resolves a per-consumer random_state: Option<u64> against the process-global
(thread-local) seed as follows:
Some(seed): use that seed. The global stays untouchedNone, with a global seed set: derive an independent sub-seed from the global streamNone, with no global seed: seed from entropy (not reproducible)
Because an explicit Some seed never consumes the global stream, adding or removing a seeded
component does not change the seeds the unseeded ones get. Unseeded components, by contrast,
draw from the shared stream in construction order, so their reproducibility is order-sensitive
(this matches Keras’ global-seed behavior)
§Threading
The global seed is thread-local: set_global_seed only affects the thread that calls
it, so set the seed on the same thread that constructs your models. This is lock-free, and
because the default test harness spawns a fresh thread per test, each test starts unseeded.
Under --test-threads=1, however, all tests share one thread. A test that sets a global seed
should call clear_global_seed afterwards, ideally with a drop guard so it runs even on
panic. This avoids leaking the seed into a later test that expects unseeded behavior
§Intentional exclusions
Not every pseudo-random draw in the crate goes through this module. A draw is worth routing
here only when it has a real, lasting effect on the result. The utils dimensionality
reducers (pca, kernel_pca) are left out, for 2 reasons:
- Their iterative eigensolvers (PCA’s
PowerIteration, and KernelPCA’sLanczosandPowerIteration) seed a starting vector with a fixed constant. These methods converge to the same eigenvectors regardless of the starting vector, so the seed only pins an arbitrary eigenvector sign. It has no effect on reproducibility worth routing through the global seed - Randomized SVD (
SVDSolver::Randomized(u64)) takes its seed as a public argument, so the caller always supplies it. There is no unseeded path for the global to fill
General rule: route a draw through this module only when an unseeded call would make a pseudo-random choice that changes the result
Functions§
- clear_
global_ seed - Clears the thread-local global seed, restoring entropy-based behavior for unseeded components
- set_
global_ seed - Sets the thread-local global seed