Skip to main content

HMM Algorithms: Forward, Backward, Viterbi, Baum-Welch

Source: Unit 3 §13

NumbersThe canonical exam HMM, used on every algorithm below
  • States: S1, S2. Initial: π1=0.2\pi_1 = 0.2, π2=0.8\pi_2 = 0.8.
  • Transitions: a11=0.4a_{11} = 0.4, a12=0.6a_{12} = 0.6, a21=0.3a_{21} = 0.3, a22=0.7a_{22} = 0.7.
  • Emissions: b1(V1)=0.1b_1(V_1) = 0.1, b1(V2)=0.4b_1(V_2) = 0.4, b1(V3)=0.5b_1(V_3) = 0.5; b2(V1)=0.3b_2(V_1) = 0.3, b2(V2)=0.5b_2(V_2) = 0.5, b2(V3)=0.2b_2(V_3) = 0.2.
  • Observation sequence: O = {V1, V3, V2}.

Forward algorithm: problem 1, likelihood

The forward probability αi(t)=P(O1O2Ot,Xt=siλ)\alpha_i(t) = P(O_1 O_2 \dots O_t, X_t = s_i \mid \lambda) is the probability of the observations up to time tt and being in state ii at time tt.

GotchaWhy not brute force

Enumerating all state sequences is exponential in the length of the sequence. The forward algorithm uses dynamic programming - it solves time tt using the result already computed for t1t-1 - which makes it linear in sequence length.

α1(i)=πibi(O1)\alpha_1(i) = \pi_i \cdot b_i(O_1) αt+1(j)=[iαt(i)aij]bj(Ot+1)\alpha_{t+1}(j) = \left[ \sum_i \alpha_t(i) \cdot a_{ij} \right] \cdot b_j(O_{t+1}) P(Oλ)=iαT(i)P(O \mid \lambda) = \sum_i \alpha_T(i)

The three lines are initialisation, recursion and termination. Termination is just "sum the last column".

StepsThe alpha table, computed
  1. Column 1, V1 observed. α1(S1)=π1b1(V1)=0.2×0.1=0.02\alpha_1(S_1) = \pi_1 b_1(V_1) = 0.2 \times 0.1 = \mathbf{0.02} and α1(S2)=π2b2(V1)=0.8×0.3=0.24\alpha_1(S_2) = \pi_2 b_2(V_1) = 0.8 \times 0.3 = \mathbf{0.24}.
  2. Column 2, V3 observed. α2(S1)=(0.02×0.4+0.24×0.3)×0.5=0.08×0.5=0.04\alpha_2(S_1) = (0.02 \times 0.4 + 0.24 \times 0.3) \times 0.5 = 0.08 \times 0.5 = \mathbf{0.04}.
  3. α2(S2)=(0.02×0.6+0.24×0.7)×0.2=0.18×0.2=0.036\alpha_2(S_2) = (0.02 \times 0.6 + 0.24 \times 0.7) \times 0.2 = 0.18 \times 0.2 = \mathbf{0.036}.
  4. Column 3, V2 observed. α3(S1)=(0.04×0.4+0.036×0.3)×0.4=0.0268×0.4=0.01072\alpha_3(S_1) = (0.04 \times 0.4 + 0.036 \times 0.3) \times 0.4 = 0.0268 \times 0.4 = \mathbf{0.01072}.
  5. α3(S2)=(0.04×0.6+0.036×0.7)×0.5=0.0492×0.5=0.0246\alpha_3(S_2) = (0.04 \times 0.6 + 0.036 \times 0.7) \times 0.5 = 0.0492 \times 0.5 = \mathbf{0.0246}.
  6. Terminate: P(Oλ)=0.01072+0.0246=0.03532P(O \mid \lambda) = 0.01072 + 0.0246 = \mathbf{0.03532}.
Alphat=1 (V1)t=2 (V3)t=3 (V2)
S10.020.040.01072
S20.240.0360.0246
t = 1observe V1t = 2observe V3t = 3observe V20.40.60.30.70.40.60.30.7π₁ = 0.2π₂ = 0.8S10.02S20.24S10.04S20.036S10.01072S20.0246P(O | λ) = 0.01072 + 0.0246 = 0.03532edge labels are transition probabilities aᵢⱼ
Every node holds the total probability of all paths that reach it, so each column is computed once and reused. That reuse is what turns an exponential enumeration into a linear scan.

Backward algorithm

The backward probability βi(t)\beta_i(t) is the probability of seeing the observations from time t+1t+1 to the end, given that we are in state ii at time tt.

βT(i)=1for all i\beta_T(i) = 1 \quad \text{for all } i βt(i)=jaijbj(Ot+1)βt+1(j)\beta_t(i) = \sum_j a_{ij} \cdot b_j(O_{t+1}) \cdot \beta_{t+1}(j)
GotchaBeta fills right to left, and its emission index is t+1

The last column is all 1s, not all 0s - there are no remaining observations to explain, and an empty product is 1. Note also that β\beta uses bj(Ot+1)b_j(O_{t+1}), the next observation, whereas α\alpha uses the current one. Getting that index wrong is the usual source of a wrong beta table.

StepsThe beta table, computed right to left
  1. Column 3, initialisation. β3(S1)=1\beta_3(S_1) = 1 and β3(S2)=1\beta_3(S_2) = 1.
  2. Column 2, with V2 as O3O_3. β2(S1)=0.4×0.4+0.6×0.5=0.16+0.30=0.46\beta_2(S_1) = 0.4 \times 0.4 + 0.6 \times 0.5 = 0.16 + 0.30 = \mathbf{0.46}.
  3. β2(S2)=0.3×0.4+0.7×0.5=0.12+0.35=0.47\beta_2(S_2) = 0.3 \times 0.4 + 0.7 \times 0.5 = 0.12 + 0.35 = \mathbf{0.47}.
  4. Column 1, with V3 as O2O_2. β1(S1)=0.4×0.5×0.46+0.6×0.2×0.47=0.092+0.0564=0.1484\beta_1(S_1) = 0.4 \times 0.5 \times 0.46 + 0.6 \times 0.2 \times 0.47 = 0.092 + 0.0564 = \mathbf{0.1484}.
  5. β1(S2)=0.3×0.5×0.46+0.7×0.2×0.47=0.069+0.0658=0.1348\beta_1(S_2) = 0.3 \times 0.5 \times 0.46 + 0.7 \times 0.2 \times 0.47 = 0.069 + 0.0658 = \mathbf{0.1348}.
Betat=1 (V1)t=2 (V3)t=3 (V2)
S10.14840.461
S20.13480.471

Combining alpha and beta

P(Oλ)P(O \mid \lambda) can be recovered from any column as the dot product of that column's α\alpha and β\beta values, and every column gives the same answer. That is the standard way to check your arithmetic.

StepsThree columns, one answer
  1. Column 1: 0.02×0.1484+0.24×0.1348=0.035320.02 \times 0.1484 + 0.24 \times 0.1348 = 0.03532.
  2. Column 2: 0.04×0.46+0.036×0.47=0.035320.04 \times 0.46 + 0.036 \times 0.47 = 0.03532.
  3. Column 3: 0.01072×1+0.0246×1=0.035320.01072 \times 1 + 0.0246 \times 1 = 0.03532.

The occupation or gamma probability is the probability of being in state ii at time tt given all the observations, past and future:

γt(i)=αt(i)βt(i)P(Oλ)\gamma_t(i) = \frac{\alpha_t(i) \cdot \beta_t(i)}{P(O \mid \lambda)}
StepsThe gamma table, dividing through by 0.03532
  1. γ1(S1)=0.02×0.1484/0.03532=0.08403\gamma_1(S_1) = 0.02 \times 0.1484 / 0.03532 = \mathbf{0.08403} and γ1(S2)=0.24×0.1348/0.03532=0.91596\gamma_1(S_2) = 0.24 \times 0.1348 / 0.03532 = \mathbf{0.91596}.
  2. γ2(S1)=0.04×0.46/0.03532=0.52095\gamma_2(S_1) = 0.04 \times 0.46 / 0.03532 = \mathbf{0.52095} and γ2(S2)=0.036×0.47/0.03532=0.47904\gamma_2(S_2) = 0.036 \times 0.47 / 0.03532 = \mathbf{0.47904}.
  3. γ3(S1)=0.01072×1/0.03532=0.30351\gamma_3(S_1) = 0.01072 \times 1 / 0.03532 = \mathbf{0.30351} and γ3(S2)=0.0246×1/0.03532=0.69648\gamma_3(S_2) = 0.0246 \times 1 / 0.03532 = \mathbf{0.69648}.
Gammat=1t=2t=3
S10.084030.520950.30351
S20.915960.479040.69648
Exam cueEach gamma column sums to 1

It has to: at any time tt the chain is in exactly one state, so the probabilities over states must total 1. Picking the highest-gamma state at each time is called posterior decoding, and it is a different answer from Viterbi.

Viterbi algorithm: problem 2, decoding

Decoding means finding the single most likely hidden state sequence given the observations.

Viterbi is almost identical to the forward algorithm, with the sum replaced by a max:

vt(j)=maxi[vt1(i)aij]bj(Ot)v_t(j) = \max_i \left[ v_{t-1}(i) \cdot a_{ij} \right] \cdot b_j(O_t)
CompareThe one-operator difference
Forwardαₜ(j) = [ Σᵢ αₜ₋₁(i)·aᵢⱼ ] · bⱼ(Oₜ). Sums over all paths into the node, so each node holds a TOTAL probability. Answers "how likely is this observation sequence".
Viterbivₜ(j) = [ maxᵢ vₜ₋₁(i)·aᵢⱼ ] · bⱼ(Oₜ). Keeps only the most likely path into the node, and records a BACKPOINTER to the max-giving predecessor. Answers "which states produced it".

Viterbi also records the back-pointer - the predecessor that gave the max - at every node, and backtracks from the best final node at the end to recover the optimal state sequence.

StepsViterbi on the canonical HMM
  1. t = 1, V1. v1(S1)=0.2×0.1=0.02v_1(S_1) = 0.2 \times 0.1 = \mathbf{0.02}, v1(S2)=0.8×0.3=0.24v_1(S_2) = 0.8 \times 0.3 = \mathbf{0.24}. No backpointers yet.
  2. t = 2 into S1, V3. Candidates 0.02×0.4=0.0080.02 \times 0.4 = 0.008 and 0.24×0.3=0.0720.24 \times 0.3 = 0.072. Max is 0.072 from S2, so v2(S1)=0.072×0.5=0.036v_2(S_1) = 0.072 \times 0.5 = \mathbf{0.036}.
  3. t = 2 into S2. Candidates 0.02×0.6=0.0120.02 \times 0.6 = 0.012 and 0.24×0.7=0.1680.24 \times 0.7 = 0.168. Max is 0.168 from S2, so v2(S2)=0.168×0.2=0.0336v_2(S_2) = 0.168 \times 0.2 = \mathbf{0.0336}.
  4. t = 3 into S1, V2. Candidates 0.036×0.4=0.01440.036 \times 0.4 = 0.0144 and 0.0336×0.3=0.010080.0336 \times 0.3 = 0.01008. Max is 0.0144 from S1, so v3(S1)=0.0144×0.4=0.00576v_3(S_1) = 0.0144 \times 0.4 = \mathbf{0.00576}.
  5. t = 3 into S2. Candidates 0.036×0.6=0.02160.036 \times 0.6 = 0.0216 and 0.0336×0.7=0.023520.0336 \times 0.7 = 0.02352. Max is 0.02352 from S2, so v3(S2)=0.02352×0.5=0.01176v_3(S_2) = 0.02352 \times 0.5 = \mathbf{0.01176}.
  6. Terminate and backtrack. The larger final value is 0.011760.01176 at S2; its backpointer is S2 at t=2, whose backpointer is S2 at t=1. The best sequence is S2 → S2 → S2.
t = 1observe V1t = 2observe V3t = 3observe V20.40.60.30.70.40.60.30.7π₁ = 0.2π₂ = 0.8S10.02S20.24S10.036S20.0336S10.00576S20.01176best path probability = 0.01176 · recovered sequence S2 → S2 → S2dashed = the losing edge into a node · bold blue = the max-giving predecessor
Same trellis, one operator changed. Only the winning edge into each node survives, and following the bold edges back from the best final node recovers the optimal state sequence S2, S2, S2.
CompareLikelihood versus Viterbi, the dishonest-casino intuition
Likelihood (γ)At each time, sum over sequences to get the state distribution at time t. It fluctuates a lot from one step to the next - a narrow, local view.
ViterbiThe single most likely path through the whole trellis. Smoother, and it reflects the transition probabilities properly - a global view.

Baum-Welch algorithm: problem 3, learning

Baum-Welch learns the HMM parameters λ=(A,B,π)\lambda = (A, B, \pi) from observations alone. It is EM applied to HMMs.

FactsThe chicken and egg, and the extra quantity it needs
  • If we knew the state-occupation probability γ\gamma, we could derive the emission and transition probabilities. If we knew those, we could derive γ\gamma. Neither is available first.
  • ξ\xi (xi) is the probability of transitioning from state ii to state jj after time tt, given all the observations. Like γ\gamma, it is computed from α\alpha and β\beta.
StepsThe EM loop for an HMM
  1. E-step: with the current model, run forward-backward to compute γ\gamma and ξ\xi - that is, establish p(γ,ξx,a,b)p(\gamma, \xi \mid x, a, b).
  2. M-step: re-estimate the best transition aa and emission bb as point estimates that maximise the objective.
  3. Repeat: fix one set of parameters to improve the other, until convergence.
E-stepfix λ, run forward-backwardcompute γ and ξwhere is the chain, and what did it do nextM-stepfix γ and ξ, re-estimatenew a, b (and π)point estimates that maximise the objectiverepeat until convergencethe chicken and egg: γ needs a model, the model needs γ - so fix one and improve the other
Baum-Welch is EM wearing HMM notation. Forward-backward supplies the soft counts, and the soft counts supply the next model.
FactsApplications of HMMs
  • Speech recognition.
  • DNA and base-pair analysis.
  • Part-of-speech tagging.
  • The dishonest casino - inferring which die, fair or biased, is being used from the observed rolls.