mixle.stats.latent.chained_attention module¶
Chained (multi-hop) attention: an L-hop stack of responsibility-attention, EM-able via forward-backward.
A single attention head answers one content lookup. Chaining L of them answers a multi-step lookup –
“find b that a points to, then find c that b points to” – which one hop provably cannot do. Each
position in the context carries a (key_symbol, value_symbol) pair. The initial query is the one-hot
of the query symbol; at hop l it attends over positions by matching the current query to the hop’s
key table K^(l), and the attended position’s value (as a one-hot) becomes the query for hop
l+1. After L hops the target is emitted from the final attended value.
The hop latents z_1..z_L (which position each hop lands on) form a time-inhomogeneous chain over
the N context positions – a content-addressed HMM with an emission only at the last hop – so
forward-backward gives exact responsibilities in O(L N^2) and every M-step stays closed-form
and additively mergeable. Crucially the queries are one-hot (observed symbols / retrieved values), so
they anchor the key tables and the closed-form M-step does not collapse (unlike a tied latent
embedding, which needs the variational treatment).
Observation: (context_keys, context_values, query_symbol, target). n_hops = 1 recovers a single
responsibility-attention head; n_hops = 2 does transitive (a->b->c) lookup. The gate variance
sigma2 is the attention temperature – keep it small (the one-hot query/key separation is only 2,
so a large sigma2 blurs the chained prediction).
References: multi-hop content-addressed attention is the End-to-End Memory Network (Sukhbaatar, Szlam, Weston & Fergus 2015); the transitive lookup is a bAbI-style reasoning task and the 2-hop copy is the induction-head circuit (Olsson et al. 2022). Exact forward-backward over the alignment chain mirrors HMM-based word alignment (Vogel & Ney 1996), which – like here – keeps the marginal likelihood exact.
- class ChainedAttentionDistribution(keys, emission, sigma2=0.1, name=None)[source]
Bases:
SequenceEncodableProbabilityDistributionAn L-hop stack of responsibility-attention heads (chained, content-addressed).
- density(x)[source]
Return the probability density or mass at a single observation.
Concrete default: exponentiate
log_density(the abstract method subclasses must provide). Leaves with a cheaper closed form may override this.
- log_density(x)[source]
Return the log-density or log-mass at a single observation.
- seq_log_density(x)[source]
Return vectorized log-density values for sequence-encoded observations.
- Return type:
- predict_proba(context_keys, context_values, query)[source]
Predictive target distribution (target marginalized);
(T,)or(n, T).
- sampler(seed=None)[source]
Return a sampler for drawing observations from this distribution.
- Parameters:
seed (int | None)
- Return type:
ChainedAttentionSampler
- estimator(pseudo_count=None)[source]
Return an estimator for fitting this distribution from data.
- Parameters:
pseudo_count (float | None)
- Return type:
ChainedAttentionEstimator
- dist_to_encoder()[source]
Return the data encoder used by this distribution for vectorized methods.
- Return type:
ChainedAttentionDataEncoder
- class ChainedAttentionSampler(dist, seed=None)[source]
Bases:
DistributionSamplerGenerative sampler (uniform context + the chained gate).
- Parameters:
dist (ChainedAttentionDistribution)
seed (int | None)
- sample(size=None, *, batched=True)[source]
Draw observations.
Combinator samplers (mixture/sequence/…) accept
batched. Withbatched=True(the default) each child stream is drawn in one vectorized call instead of a per-draw Python loop – far faster. Because every child sampler owns an independentRandomState, batching consumes each stream in the same order as the loop, so the draws are identical to the legacy path.batched=Falseforces that legacy per-draw loop as a guaranteed- stable reference. Leaf samplers are already vectorized and ignore the flag.
- class ChainedAttentionAccumulator(n_hops, num_symbols, num_targets, keys=None, name=None)[source]
Bases:
SequenceEncodableStatisticAccumulatorForward-backward sufficient statistics (additive): per-hop key numerators + emission counts.
- seq_update(x, weights, estimate)[source]
- Parameters:
estimate (ChainedAttentionDistribution)
- Return type:
None
- seq_initialize(x, weights, rng)[source]
- Parameters:
rng (RandomState)
- Return type:
None
- initialize(x, weight, rng)[source]
- Parameters:
weight (float)
rng (RandomState)
- Return type:
None
- combine(suff_stat)[source]
- Return type:
ChainedAttentionAccumulator
- value()[source]
- from_value(x)[source]
- Return type:
ChainedAttentionAccumulator
- key_merge(stats_dict)[source]
Pool this accumulator’s statistics into
stats_dictunder its merge key.The structural default implements the common single-key pattern: store the accumulator under
self.keysthe first time the key is seen, elsecombineinto the one already there. Accumulators with several named keys (e.g. an HMM’s init/trans/state keys) or a non-accumulator stats payload override this. AkeysofNone(the default) is a no-op.
- key_replace(stats_dict)[source]
Replace this accumulator’s statistics from the pooled
stats_dictentry (see key_merge).
- acc_to_encoder()[source]
- Return type:
ChainedAttentionDataEncoder
- class ChainedAttentionAccumulatorFactory(n_hops, num_symbols, num_targets, keys=None, name=None)[source]
Bases:
StatisticAccumulatorFactory- make()[source]
- Return type:
ChainedAttentionAccumulator
- class ChainedAttentionEstimator(n_hops, num_symbols, num_targets, *, sigma2=0.1, emission_smoothing=1e-4, pseudo_count=None, name=None, keys=None)[source]
Bases:
ParameterEstimatorClosed-form EM estimator: per-hop key tables (GMM means of one-hot queries) + emission counts.
- Parameters:
- accumulator_factory()[source]
- Return type:
ChainedAttentionAccumulatorFactory
- class ChainedAttentionDataEncoder[source]
Bases:
DataSequenceEncoderEncodes
(context_keys, context_values, query_symbol, target)into stacked integer arrays.