Overview
The Viterbi algorithm finds the most likely sequence of hidden states (POS tags) given observed emissions (words). It uses dynamic programming with beam search, running in O(N × B² × T) time where N is the sequence length, B is the beam width, and T is the tagset size.Requirements
The Viterbi POS tagger requires probability tables in the database to function effectively:Building Database with POS Probabilities
POS probability tables are populated when you build a database with a POS tagger:Checking Database for POS Tables
Fallback Behavior
If POS probability tables are empty or missing:- Viterbi falls back to morphological analysis for tag prediction
- Accuracy drops from ~85% to ~70% (similar to rule-based tagger)
- A warning is logged: “Provider does not support bigram probabilities”
How It Works
Trigram Hidden Markov Model
The implementation uses a trigram HMM with deleted interpolation smoothing:Algorithm Steps
- Initialization: Set probabilities for first position
- Recursion: For each position, compute best path using trigram transitions with beam pruning
- Termination: Find best final state
- Backtracking: Reconstruct optimal path
Implementation
Python Wrapper
Cython Acceleration
The library includes a Cython implementation for 2-5x speedup:Configuration
Note: Unknown word handling is controlled via themin_prob(default:1e-10) andunknown_word_tag(default:"UNK") parameters on theViterbiTaggerconstructor, not via a separate penalty parameter.
Config resolution: When both constructor arguments and aPOSTaggerConfigare provided, explicit constructor arguments always take precedence, even if they match the default value. This meansViterbiTagger(beam_width=10, config=config)uses10regardless of whatconfig.viterbi_beam_widthsays. Omitted parameters fall back to the config, then to built-in defaults.
POSTaggerConfig Viterbi Fields
ThePOSTaggerConfig class exposes Viterbi-specific tuning parameters. These are separate from the constructor parameters on ViterbiTagger — they control the config-driven pipeline integration.
The
lambda_* weights control deleted interpolation smoothing and must sum to 1.0. Higher lambda_trigram gives more weight to trigram context (better for well-trained models), while higher lambda_unigram adds robustness when training data is sparse.
Beam Search
Beam search prunes unlikely paths for efficiency:Joint Segmentation + Tagging
The Viterbi algorithm can jointly segment and tag text:Emission Score Logic
For the first token (t=1), emission scores are handled specially:Performance
Integration
See Also
- POS Tagging - Feature documentation
- Joint Segment Tagger - Combined segmentation + tagging
- Transformer POS - Neural POS tagger