Viterbi Algorithm › The Viterbi Recursion
Language AI HandbookAll chapters Viterbi Algorithm › The Viterbi RecursionOne section · Sections in this chapter3 / 12 ↓
Reading tools Definitions & inline links
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
We've established that greedy decoding fails because local choices can force globally suboptimal sequences, and that exhaustive search is computationally impossible. How can we find the optimal path without examining every possibility? The answer lies in a beautiful insight from dynamic programming: we can build the optimal solution incrementally from smaller optimal solutions.
The Key Insight: Optimal Substructure
Imagine you're at position 3 in a sequence, and you want to know the best path that ends at the tag NOUN. The recurrence relies on this observation: regardless of how that path reached position 2, the best continuation to NOUN at position 3 depends only on:
- What state we're in at position 2 (not how we got there)
- The transition probability to NOUN
- The emission probability of the observed word from NOUN
This property is called optimal substructure. If the best path through the entire sequence passes through state at position 2 and then reaches NOUN at position 3, then the portion of that path from the start to must itself be optimal. Why? If there were a better path to , we could substitute it and get a better overall path, contradicting our assumption that we had the best path.
The best path ending at state at position consists of the best path to some state at position , followed by a transition from to . We can find the globally optimal path by computing locally optimal subpaths.
This principle transforms our approach entirely. Instead of tracking complete paths (exponentially many), we only need to track the best score for reaching each state at each position. At any position, we have just values to maintain, one per possible state, rather than an exponentially growing set of paths.
Building the Recurrence: From Intuition to Formula
Let's formalize this insight. We define as the probability of the most likely path that:
- Ends at state at position
- Generates the observations seen so far
How do we compute ? Consider any path ending at state at position . That path must have come from some predecessor state at position . The probability of this path factors into three terms:
- The probability of the best path to : This is , which we've already computed
- The transition probability from to : This is
- The probability of emitting the current observation from : This is
Since we want the best path to , we take the maximum over all possible predecessor states. This gives us the Viterbi recurrence:
where:
- : the probability of the best path ending at state at position
- : takes the maximum over all possible predecessor states
- : the best score for reaching state at the previous position (already computed)
- : the transition probability from predecessor state to current state
- : the emission probability of observing word from state
Notice that appears inside the maximization but doesn't depend on the predecessor . This is because once we decide to be in state at position , the emission probability is fixed regardless of how we arrived. We could factor it out:
This form is computationally equivalent but makes clear that we're choosing the best predecessor based solely on the accumulated path score and transition, then multiplying by the emission.
The Base Case: Starting the Sequence
The recurrence needs a starting point. At position 1, there is no predecessor to consider. The probability of the best path ending at state after seeing just the first observation is simply:
where:
- : the initial state probability (how likely the sequence starts in state )
- : the emission probability of the first observation from state
This captures both how likely we are to start in state and how well state explains the first observed word.
Complexity: Why This Works
Let's count the operations. At each of the positions (after the first), we compute for each of the states. Computing each requires examining predecessors. Total: operations.
Compare this to the paths we would examine exhaustively:
| Approach | Complexity | 45 tags, 20 words |
|---|---|---|
| Exhaustive | ~ | |
| Viterbi | 40,500 |
The exponential has become polynomial. This is the power of dynamic programming: by recognizing that we can solve the problem incrementally and that we only need to remember the best score per state (not every path), we collapse an intractable problem into an efficient algorithm.
Visualizing the Trellis
It helps to visualize the Viterbi computation as filling a grid called a trellis. The horizontal axis represents positions in the sequence (1 through ), and the vertical axis represents possible states (the tags or labels). Each cell holds the score , the probability of the best path ending at state at position .
Arrows connect cells at adjacent positions. Each arrow from to represents one term in the maximization: "if I came from state , what would my score be?" The algorithm fills this grid column by column, left to right, computing each cell from the cells in the previous column.

In the figure above, gray arrows show all possible transitions between adjacent positions. The red path highlights the optimal sequence discovered by Viterbi: DT → NN → VB → NN for the sentence "The can hold water." Notice that:
- At position 1, DT (determiner) wins because "The" is overwhelmingly a determiner
- At position 2, NN (noun) wins, not because "can" is most often a noun, but because this choice enables better continuations
- The algorithm found this globally optimal path without explicitly enumerating all 81 possible sequences (3 states × 4 positions)
Now we understand how Viterbi computes scores efficiently. But there's a missing piece: at the end of the algorithm, we know the score of the best path, but we haven't recorded the path itself. How do we reconstruct the sequence of states along that path?