ReactiveBayes / ReactiveBayes/ExponentialFamilyProjection.jl

[MINOR] User-provided `rng` is force-reseeded; per-iteration Monte Carlo noise is independent of `niterations`

Open
#101 0 comments 0 reactions 0 assignees View on GitHub

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:161
  • src/strategies/bonnet/strategy.jl:117
  • src/strategies/bonnet/gauss_newton.jl:105
Random.seed!(getrng(parameters), getseed(parameters))
Random.rand!(getrng(parameters), current_ef, get_samples(state))

Two consequences:

  1. The documented rng field of ProjectionParameters is effectively ignored. Whatever RNG the user supplies is overwritten with seed on the first prepare_state!. Only seed matters.
  2. 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 niterations does not reduce Monte-Carlo gradient noise at all — only increasing nsamples does. 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

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.