The Learning Library
Contents

Module 08 — Beyond hmmlearn: pomegranate v1 and dynamax

Part II · Tooling & Evaluation · Status: Draft v0.1 Scope: When and how to use pomegranate v1 or dynamax instead · Prerequisites: Modules 03, 07

Overview

hmmlearn carries you far on a CPU with a few thousand bars. Two situations outgrow it: you want GPU acceleration or modern gradient-based training, or you want the composable probability machinery of the JAX ecosystem.

This module introduces the two serious alternatives. pomegranate v1 is a PyTorch rewrite with GPU-capable dense and sparse HMMs. dynamax is a JAX library from the probml organization with EM, gradient, and sampling-based inference. You learn what each changes, what breaks from older tutorials, and how to choose between the three.

How It Works

All three libraries fit the same hidden machinery: a start vector, a transition matrix, and per-state emissions. What differs is the computation engine and the training algorithm menu.

hmmlearn runs NumPy/Cython EM on the CPU. pomegranate v1 runs PyTorch modules on CPU or GPU, so the same model can train with EM or gradient steps on a device you choose.

dynamax runs JAX transformations, so one model definition compiles, batches over many sequences with vmap, and differentiates for gradient-based or sampling-based inference.

flowchart TD
    A[Your data and K] --> B{What constrains you?}
    B --> C[Small CPU fit]
    C --> D[hmmlearn EM]
    B --> E[GPU or gradients]
    E --> F[pomegranate v1]
    B --> G[JAX batching or MCMC]
    G --> H[dynamax]
    D --> I[Compare sorted spreads]
    F --> I
    H --> I

How to read this: start at the top diamond and follow the branch matching your constraint. All three branches rejoin at the same check: sorted fitted spreads near 0.005 and 0.02 on the shared series.

pomegranate v1: PyTorch Dense and Sparse HMMs

pomegranate version 1.x is a from-scratch PyTorch rewrite, released under the MIT license, with GPU support and two HMM flavors: DenseHMM for small fully-connected state graphs and SparseHMM for large structured ones. Emissions are multivariate by default, so a single state can jointly model returns plus a second feature such as a volume z-score.

The breaking-change warning is the point of this section. pomegranate 0.x tutorials are traps: class names, import paths, and fitting idioms changed in v1, and pasting 0.x code into a v1 install fails.

Work only from v1 documentation matched to your installed version.

# Sketch: verify install, device, and API generation first.
# PLACEHOLDER — verify exact 1.1.x release date on PyPI
# before print; 1.1.2 is the latest version observed.
import pomegranate  # v1.x PyTorch rewrite, MIT license

print("version:", pomegranate.__version__)
# Expect DenseHMM and SparseHMM at top level in v1.
print("has dense:", hasattr(pomegranate, "DenseHMM"))
print("has sparse:", hasattr(pomegranate, "SparseHMM"))
try:
    import torch  # GPU path; falls back to CPU when absent
    print("cuda available:", torch.cuda.is_available())
except ImportError:
    print("torch missing: install the PyTorch extra")

Why this sketch instead of a full fit: pomegranate v1 APIs move faster than hmmlearn’s, so the durable skill is version-first verification, not memorizing one call signature. Pin pomegranate==1.1.2 (or your installed exact build), confirm the class exists, confirm the device, and only then adapt the v1 DenseHMM example from the matching docs to the shared series.

[!WARNING] Never paste pomegranate 0.x HiddenMarkovModel code into a v1 project. The rewrite renamed and restructured the API, and 0.x tutorials fail loudly or, worse, import a stale 0.x install alongside v1.

dynamax: JAX HMMs with EM, Gradients, and Sampling

dynamax is a JAX state-space library maintained under the probml organization. For HMMs it offers classical EM alongside gradient-based (SGD-style) optimization and MCMC sampling over parameters. That menu matters when point estimates are not enough and you want posterior uncertainty over transitions or emissions.

The JAX payoff is composition. You write one transition-and-emission model, then batch it over hundreds of sequences with vmap, compile it just in time, and differentiate through it, all without rewriting the math. The price is ecosystem lock-in: your team must already live in JAX, Flax/Optax, and functional random keys to use it comfortably.

# Sketch: confirm the JAX stack before touching dynamax.
# PLACEHOLDER — verify dynamax release number on GitHub
# releases before print; version UNPINNED at retrieval.
import jax

print("jax devices:", jax.devices())
print("jax key demo:", jax.random.split(jax.random.PRNGKey(42)))
# Next step in the dynamax docs: pick the discrete-HMM
# module, match its release tag, and fit the shared series.

Treat dynamax as the choice for batch-heavy or uncertainty-aware work: many short sequences at once, gradient fine-tuning after EM, or sampled posteriors over the transition matrix.

For one 2000-bar CPU fit, it adds machinery without adding insight, and hmmlearn stays the honest default.

[!NOTE] JAX randomness is explicit: every stochastic call consumes a split key. Seed 42 here means PRNGKey(42) split per run, and you record the key alongside the dynamax version.

Choosing a Library

Use the table as a decision procedure, not a ranking. Match your row first: data size, hardware, and ecosystem. Then confirm the maintenance story from the project’s own release channel before you commit teaching or production code to it.

Question hmmlearn pomegranate v1 dynamax
Data size Thousands of bars, CPU Large or multivariate, GPU Many sequences, batched
Ecosystem scikit-learn, NumPy PyTorch JAX, probml stack
Training menu EM only EM plus gradients EM, SGD, MCMC
API stability High, limited maintenance Moving, pin exact v1 Moving, pin release tag
Start here when Default choice GPU or sparse graphs Batching or posteriors

A practical rule follows. Prototype every new idea in hmmlearn first, because its stability makes failures interpretable. Move to pomegranate v1 when the profiler says the CPU is the bottleneck or you need sparse structure. Move to dynamax when the workload is many-sequence batching or you need sampled uncertainty rather than a point fit.

Cost enters the decision too. A GPU port that trains ten times faster but takes a week of dependency wrangling loses to the CPU baseline on any deadline shorter than a quarter. Count engineering days alongside wall-clock minutes, and document both in the decision paragraph your Hands-On project produces.

[!TIP] Refit the shared series in each candidate library and compare sorted spreads before porting real work. If the three disagree beyond a few basis points, the port is wrong, not the data.

Testing It Honestly

Pin everything you touch. That means pomegranate with its exact 1.1.x build plus the torch build, or dynamax with its exact release tag plus the jax and jaxlib builds. Unpinned GPU-stack fits are not reproducible, because kernels and autograd behavior drift across releases.

Verify the same three outputs in every library: the data hash of the shared series (seed 42, 2000 bars), the sorted fitted spreads near 0.005 and 0.02, and the device actually used (CPU versus named GPU). A fit that silently fell back to CPU while you claimed GPU speedups is a reporting defect.

Your reproduction card gains one line per library beyond the Module 07 card: exact version, device, and the v1-versus-0.x or release-tag confirmation. Anything dated but unverified carries the explicit mark PLACEHOLDER so print review catches it.

Keep the porting order strict: hmmlearn first for the reference numbers, one alternative second, never both alternatives at once. When two things change simultaneously, engine plus model, a mismatch teaches you nothing about which move broke the comparison.

Worked-number anchor for every port: the reference spreads are 0.005 and 0.02, a factor of four apart. Agreement within a few basis points (say 0.0045 versus 0.0052 on the calm state) is success. A port reporting 0.011 and 0.013 has collapsed the two regimes into the average and must be debugged, not averaged with the reference.

Hands-On Project

Run the same series through two engines and document the comparison.

  1. Fit the shared series in hmmlearn (Module 07) and record spreads and runtime.
  2. Install the pinned pomegranate v1 build, run the sketch, and adapt the matching-docs DenseHMM example to the same series.
  3. If your team uses JAX, run the dynamax sketch and fit the discrete-HMM example at the pinned tag.
  4. Compare sorted spreads across engines; investigate any gap above a few basis points.
  5. Write one decision paragraph: which library your next module uses, and which row of the table forced the choice.

Keep both reproduction cards. When a later result looks different under a new library, the cards tell you whether the engine, the version, or the model actually changed.

Key Takeaways

  • pomegranate v1 is a PyTorch rewrite (DenseHMM, SparseHMM, GPU, multivariate emissions); 0.x tutorials do not transfer.
  • dynamax brings JAX batching plus EM, gradient, and MCMC inference for discrete HMMs.
  • Prototype in hmmlearn, scale to pomegranate on GPU, batch or sample with dynamax.
  • Pin exact versions and devices; unpinned accelerator fits are not reproducible.
  • The shared-series spread check arbitrates every port between libraries.
  • pomegranate 1.1.x exact date and dynamax release number stay placeholders until verified.
  • Ecosystem fit (sklearn versus PyTorch versus JAX) decides more often than raw speed.

References

  • pomegranate developers. pomegranate v1 documentation (DenseHMM, SparseHMM, PyTorch backend). https://pomegranate.readthedocs.io/ — role: Mechanics. Retrieved 2026-09-17.
  • pomegranate developers. pomegranate releases on PyPI (1.1.2 latest observed; exact 1.1.x date PLACEHOLDER — verify before print). https://pypi.org/project/pomegranate/ — role: Mechanics. Retrieved 2026-09-17.
  • probml developers. dynamax repository and documentation (JAX HMM inference: EM, SGD, MCMC). https://github.com/probml/dynamax — role: Mechanics. Retrieved 2026-09-17.
  • Murphy, K. P. (2023). Probabilistic Machine Learning: Advanced Topics. MIT Press. https://probml.github.io/book2/ — role: Background. Retrieved 2026-09-17.
  • Exclusion: auto-generated DeepWiki summaries of the pomegranate and dynamax repos — rejected as secondary inference; project docs and release channels govern.