ReactiveBayes / ReactiveBayes/ExponentialFamilyProjection.jl
[MINOR] User-provided `rng` is force-reseeded; per-iteration Monte Carlo noise is independent of `niterations`
Nobody has claimed this yet.
- Dominant language
- Julia
- Stars
- 11
- Forks
- 1
- PR merge metrics
- No merged PRs in 30d
Description
[MINOR] User-provided rng is force-reseeded; per-iteration Monte Carlo noise is independent of niterations
Summary
prepare_state! reseeds the projection RNG to a fixed seed on every call:
src/strategies/control_variate.jl:161src/strategies/bonnet/strategy.jl:117src/strategies/bonnet/gauss_newton.jl:105
Random.seed!(getrng(parameters), getseed(parameters))
Random.rand!(getrng(parameters), current_ef, get_samples(state))
Two consequences:
- The documented
rngfield ofProjectionParametersis effectively ignored. Whatever RNG the user supplies is overwritten withseedon the firstprepare_state!. Onlyseedmatters. - Common random numbers across all iterations. Because the same seed is reused every iteration, every gradient step is computed from the same sample realization. Increasing
niterationsdoes not reduce Monte-Carlo gradient noise at all — only increasingnsamplesdoes. The converged fixed point is thereby biased by the (fixed) sample realization.
Evidence (Julia 1.12.6)
Two projections with rng = StableRNG(999) vs rng = StableRNG(777), both seed = 42, produced byte-identical sample sets (get_samples(state1) == get_samples(state2) -> true).
Note
The reseeding is intentional (comment: "reset the RNG state ... to ensure that the gradient computation is stable"), and it does make a projection deterministic. The issue is the misleading API surface: ProjectionParameters(rng=...) suggests the RNG is honoured when it is not, and users reasonably expect more iterations to reduce gradient noise.
Certification precision: prepare_state! reseeds to seed then calls Random.rand!(rng, current_ef, samples), so the random stream (uniform draws) is identical every iteration, but the actual sample values still shift because current_ef (the variational distribution being sampled) evolves during optimisation. The practical claim — no fresh independent draws per iteration, so niterations does not reduce MC gradient noise — is unchanged.
Suggested fix
Either (a) honour a user-supplied rng (don't reseed when one is explicitly provided), or (b) document prominently that rng is ignored in favour of seed and that niterations does not reduce sampling noise. Option (a) is the cleaner API.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Compare the prepare_state! implementations at src/strategies/control_variate.jl:161, src/strategies/bonnet/strategy.jl:117, and src/strategies/bonnet/gauss_newton.jl:105. Trace how getrng(parameters) and getseed(parameters) are used, then decide whether the API should honor an explicitly supplied rng or document the reseeding behavior. Done means the chosen behavior is consistent across all three entry points and matches ProjectionParameters semantics.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- julia
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 58/100