mixle.inference.block_gibbs module

Block-coordinate Gibbs with per-block inference dispatch – a different update method per parameter.

Real models are heterogeneous: some parameters have a conjugate full conditional (sample it in closed form, exactly, no tuning), others do not (fall back to Metropolis), others are best marginalized or optimized. A single global how= wastes the structure. BlockGibbs cycles the blocks and lets each one declare its own conditional update – a closed-form draw where the conditional is conjugate, a Metropolis step where it is not – so the cheap exact updates run exactly and only the hard blocks pay for sampling. The composition-expressiveness piece: mixed inference across one model.

class BlockGibbs(blocks, init)[source]

Bases: object

Block-coordinate sampler that dispatches each block’s own conditional update each sweep.

Parameters:
run(n_samples=2000, *, burn=500, seed=None)[source]

Run the chain; returns {block_name: array of post-burn-in samples}.

Parameters:
  • n_samples (int)

  • burn (int)

  • seed (int | None)

Return type:

dict[str, ndarray]

class ConjugateBlock(name, draw)[source]

Bases: object

A block whose full conditional is conjugate: draw(state, rng) returns an exact closed-form sample.

Parameters:
  • name (str)

  • draw (Callable[[dict, np.random.RandomState], Any])

update(state, rng)[source]
Parameters:
Return type:

Any

class MetropolisBlock(name, log_conditional, scale=0.5)[source]

Bases: object

A non-conjugate block updated by a random-walk Metropolis step on its log full-conditional.

log_conditional(value, state) returns the unnormalized log density of this block’s value given the rest of the state; scale sets the proposal width (adapted lightly toward a ~0.4 acceptance rate).

Parameters:
update(state, rng)[source]
Parameters:
Return type:

Any

property acceptance_rate: float