How counting observations becomes a complete theory of learning — from coin flips to the tensors that drive active inference
A bridge tutorial preparing you for Scale-Free Active Inference (Friston et al., 2025)
Active inference agents learn by observing the world and updating their beliefs. The mathematics that makes this possible follows a remarkably clean chain of generalization:
Each step is a single, clean generalization of the previous one. By the end, you will understand exactly why incrementing a count is the same as learning, why the Gamma function appears everywhere, and how Dirichlet distributions parameterize the tensors in a POMDP generative model.
This tutorial assumes familiarity with basic probability (random variables, expectation, distributions) as covered in the Probability Theory tutorial. It serves as a bridge to the Scale-Free Active Inference tutorial, where these distributions are composed into a hierarchical generative model.
The simplest possible random experiment: flip a coin. It lands heads (1) or tails (0). Nothing else. This is a Bernoulli trial.
The probability mass function is:
When x = 1: P(X = 1) = p. When x = 0: P(X = 0) = 1 − p. The formula encodes both cases in a single expression.
Now perform n independent Bernoulli trials with the same probability p. The number of successes k follows a Binomial distribution.
This has two distinct parts, and understanding them separately is key to everything that follows:
How many ways can k successes occur in n trials? This counts the number of distinct orderings. It does not depend on p at all — it is pure counting.
How likely is any one specific ordering with k successes and n − k failures? This encodes the physics of the coin — the bias parameter p.
The Binomial answers: “Given that I know p, what is the probability of seeing k successes in n trials?”
But in practice, we have the opposite problem: we observe k successes in n trials and want to learn p. We need to go from data to parameter. This is the inverse problem, and it requires a distribution over p itself — the Beta distribution.
The Binomial treats p as a fixed, known constant. The Beta distribution treats p as a random variable — it represents our uncertainty about the coin's bias.
Immediately notice the structural parallel:
| Part | Binomial | Beta |
|---|---|---|
| Combinatorial / Normalization | C(n, k) = n! / (k!(n−k)!) | 1/B(α,β) = Γ(α+β) / [Γ(α)Γ(β)] |
| Probability / Shape | pk(1−p)n−k | pα−1(1−p)β−1 |
| Variable | k (discrete count) | p (continuous probability) |
| Parameters | n, p | α, β |
The shape part is almost identical: powers of p and (1 − p). The normalization part is where the Gamma function replaces the factorial. We will see exactly why in the Gamma Function section.
The parameters α and β are called concentration parameters (or shape parameters). They encode our prior belief about the coin:
The Hungarian mathematician Pólya (yes, the author of “How to Solve It”) gave a beautiful physical model for the Beta-Binomial process:
The proportion of red balls in the urn = the expected value of p. The total number of balls = the precision (α + β). Each draw adds one ball (one pseudo-count), making the urn composition drift toward the observed color. This IS Bayesian learning — observation by observation, the urn converges on the true bias.
Pólya originally used this to model contagious diseases: observing a sick person (drawing a red ball) increases the probability of the next observation being sick (more red balls in the urn).
Here is the crucial property: after observing k successes and n − k failures, the updated urn contains (α + k) red balls and (β + n − k) blue balls. The posterior is:
Learning is just adding counts. No matrix inversions, no gradient descent, no optimization. Just add. This property has a name.
The Beta distribution is conjugate to the Binomial likelihood. This means:
Without conjugacy, Bayesian updating requires computing:
The denominator P(data) = ∫ P(data | p) P(p) dp is an integral over all possible values of p. For most prior-likelihood combinations, this integral has no closed form — you need numerical methods (MCMC, variational inference, etc.).
With conjugacy, you never need to compute the integral. You already know the posterior's functional form (it's the same family as the prior), so you just update the parameters directly:
| Likelihood | Conjugate Prior | What it learns | Update rule |
|---|---|---|---|
| Bernoulli / Binomial | Beta(α, β) | Probability of success | α += successes, β += failures |
| Categorical / Multinomial | Dirichlet(α1, ..., αK) | Probability of each category | αk += count of category k |
| Poisson | Gamma(a, b) | Event rate | a += events, b += intervals |
| Normal (known variance) | Normal(μ0, σ0) | Mean | Precision-weighted average |
The pattern: every conjugate pair has an update rule that reduces to incrementing counts or accumulating sufficient statistics. The functional form is preserved; only the parameters change.
The factorial n! = n × (n−1) × ... × 2 × 1 is only defined for non-negative integers. But the normalization constants of the Beta and Dirichlet distributions require something more general — a factorial that works for any positive real number.
Property 1: It generalizes the factorial. For positive integers: Γ(n) = (n − 1)!
Note the shift: Γ(n) = (n − 1)!, not n!. This is a historical convention. Some authors define Π(z) = Γ(z + 1) = z! to avoid the off-by-one, but Γ is standard.
Property 2: The recursion relation.
This is the continuous analogue of n! = n × (n − 1)!. It means the Gamma function satisfies the same recursion as the factorial, but for all positive reals, not just integers.
Property 3: It handles half-integers.
The √π appearing here is not a coincidence — it connects the Gamma function to the Gaussian distribution. The normalization constant of the Gaussian involves √(2π), which is 2 · Γ(1/2)2 / 2.
Recall the Binomial's combinatorial component: C(n, k) = n! / (k!(n−k)!). The Beta distribution's normalization constant is:
Compare directly:
Integer factorials. Discrete variable k.
Gamma functions. Continuous parameters α, β.
Before generalizing to K outcomes, let's crystallize the two-part structure we've seen. Every distribution in this chain has the same anatomy:
The normalization constant ensures the distribution integrates (or sums) to 1. It answers: “how many ways?” or “what fraction of the total?” It uses factorials (discrete) or Gamma functions (continuous).
The shape function encodes the probability of each specific outcome. It uses exponentiation: some base raised to a power that depends on the data and parameters.
| Distribution | Normalization | Shape | Domain |
|---|---|---|---|
| Binomial | n! / (k!(n−k)!) | pk(1−p)n−k | k ∈ { 0, ..., n } |
| Beta | Γ(α+β) / [Γ(α)Γ(β)] | pα−1(1−p)β−1 | p ∈ [0, 1] |
| Multinomial | n! / ∏ ki! | ∏ piki | ki ∈ { 0, ..., n }, Σki = n |
| Dirichlet | Γ(Σαk) / ∏Γ(αk) | ∏ pkαk−1 | pk ∈ [0,1], Σpk = 1 |
Read each row left to right: the normalization generalizes via factorial → Gamma. The shape generalizes via products of powers. Reading down: 2 outcomes → K outcomes. This table IS the entire generalization chain.
The Bernoulli has 2 outcomes. The Categorical distribution generalizes to K ≥ 2 outcomes with probabilities p1, p2, ..., pK where Σ pk = 1.
The bracket notation [x = k] equals 1 when x = k and 0 otherwise (the Iverson bracket). So for any particular outcome, exactly one pkis selected.
Perform n independent Categorical trials. Count how many times each outcome occurs: k1, k2, ..., kKwith Σ ki = n.
The multinomial coefficient. How many ways to arrange n objects where k1 are of type 1, k2 of type 2, etc. When K = 2, this reduces to C(n, k).
Product of probabilities raised to their counts. When K = 2 with p1 = p and p2 = 1−p, this reduces to pk(1−p)n−k.
The Dirichlet distribution is a distribution over probability vectors — points on the (K−1)-simplex where all components are non-negative and sum to 1.
Compare directly with the Beta:
Distribution over a single probability p ∈ [0, 1]. Two concentration parameters.
Distribution over a probability vector (p1,...,pK) on the simplex. K concentration parameters.
When K = 2 and p2 = 1 − p1, the Dirichlet reduces exactly to the Beta. The Beta is just a special case.
The urn now contains balls of K different colors. Start with αk balls of color k (for k = 1, ..., K). The same rule applies: draw a ball, note its color, put it back plus one more of the same color.
The proportion of color k in the urn ≈ αk / α0= E[pk]. After many draws, the urn converges on the true distribution of colors. This is the Dirichlet analog of Pólya's original 2-color urn.
In the active inference codebase, the concentration parameters stored in concentrationsA[obsIdx][stateIdx] ARE these ball counts. Incrementing them IS adding a ball to the urn. The normalized distributionlikelihoodModel[obsIdx][stateIdx] is the proportion of balls — the expected categorical distribution.
A tensor is a multi-dimensional array of numbers. That's it. There is no additional mysticism.
| Order | Name | Shape | Example |
|---|---|---|---|
| 0 | Scalar | [] (single number) | Temperature: 72.5 |
| 1 | Vector | [n] | Probability distribution: [0.3, 0.5, 0.2] |
| 2 | Matrix | [m × n] | Likelihood table: P(obs | state) |
| 3 | 3D Tensor | [m × n × p] | Transition model: P(next_state | state, action) |
Tensors come from physics (specifically, differential geometry and general relativity), where they describe quantities that transform in specific ways under coordinate changes. In machine learning and active inference, we use the word more loosely: a tensor is just a multi-dimensional array used to store parameters or data.
Consider a matrix A with shape [3 observations × 4 states]:
Each column of A is a probability distribution (sums to 1). Column j answers: “If I'm in state j, what is the probability of each observation?”
Each column can be independently learned via a Dirichlet distribution. The Dirichlet concentrations for column j are stored in a parallel array concentrationsA[obs][j]. The expected probabilities are concentrationsA[obs][j] / sum_obs(concentrationsA[obs][j]).
A 3D tensor B with shape [states × states × actions] stores a probability distribution per (state, action) pair: “If I'm in state s and take action a, what is the probability of transitioning to each next state?” Each (s, a) slice is a separate distribution, separately learnable.
We now have all the ingredients. A Partially Observable Markov Decision Process (POMDP) describes an agent that:
The generative model specifies how these elements relate. It is encoded as five tensors, each parameterized by Dirichlet distributions:
| Tensor | Name | Shape | What it encodes | Dirichlet concentrations |
|---|---|---|---|---|
| A | Likelihood | [obs × states] | P(observation | state) | Each column is Dir(α)-parameterized |
| B | Transition | [states × states × actions] | P(next_state | state, action) | Each (state, action) slice is Dir(α)-parameterized |
| C | Preferences | [obs] | log P*(observation) — preferred outcomes | Typically fixed, not learned |
| D | Initial state | [states] | P(state at t=0) | Dir(α)-parameterized |
| E | Policy prior | [actions] | P(action) — habitual tendencies | Dir(α)-parameterized or softmax of EFE |
The agent observes the world, infers which state it's in, and updates the relevant Dirichlet concentrations. Here is the complete learning algorithm:
The Scale-Free Active Inference tutorial covers what happens next:
All of these build on the foundation established here: Dirichlet distributions parameterize the tensors, learning is count accumulation, and the Gamma function provides the normalization that makes everything integrate to 1.