ITADN
GarroshIcecream/ChadHMM · 文件
文件最后提交记录最后更新时间
README.md

Chad Hidden Markov Models (ChadHMM)

ChadHMM Logo

chadhmm License: MIT PRs Welcome PyPI Downloads Development Status CI Release

Table of Contents

About

ChadHMM is a PyTorch-based library for Hidden Markov Models (HMM) and Hidden Semi-Markov Models (HSMM). It provides a modular, flexible framework for building and training sequential models with various emission distributions.

Key Features:

  • 🔥 Built on PyTorch for GPU acceleration and automatic differentiation
  • 🎯 Support for both HMM and HSMM with explicit duration modeling
  • 📊 Multiple emission distributions: Gaussian, Gaussian Mixture, Multinomial, Poisson
  • 🎲 Flexible transition types: Ergodic, Left-to-Right, and custom configurations
  • 🧮 Efficient inference algorithms: Viterbi, MAP, Forward-Backward
  • ⚡ Compiled algorithms with training mode control for optimized performance
  • 📈 Model selection tools: AIC, BIC, HQC information criteria

Installation

# Using pip
pip install chadhmm

# Using uv
uv add chadhmm

Option 2: Development Installation

# Clone the repository
git clone https://github.com/GarroshIcecream/ChadHMM.git
cd ChadHMM

# Install with uv
uv sync --dev

Quick Start

Here's a minimal example to get started with a Gaussian HMM:

import torch
from chadhmm import HMM
from chadhmm.distributions import (
    GaussianDistribution,
    TransitionMatrix,
    InitialDistribution
)
from chadhmm.schemas import Transitions, DecodingAlgorithm

device = torch.device("mps" if torch.mps.is_available() else "cpu")

# Create distributions
emission_pdf = GaussianDistribution.sample_distribution(
    n_features=4,      # 4-dimensional observations
    n_components=3     # 3 hidden states
)

transition_matrix = TransitionMatrix.sample_from_dirichlet(
    transition_type=Transitions.ERGODIC,
    prior=1.0,
    target_size=torch.Size([3, 3])
)

initial_distribution = InitialDistribution.sample_from_dirichlet(
    prior=1.0,
    target_size=torch.Size([3])
)

# Create HMM model
hmm = HMM(
    transition_matrix=transition_matrix,
    initial_distribution=initial_distribution,
    emission_pdf=emission_pdf,
    device=device
)

# Generate some sample data
X = torch.randn(100, 4, device=device)  # 100 timesteps, 4 features

# Fit the model
hmm.fit(X)

# Predict hidden states
states = hmm.predict(X, algorithm=DecodingAlgorithm.VITERBI)

Usage Guide

Hidden Markov Models (HMM)

Creating an HMM with Gaussian Emissions

import torch
from chadhmm import HMM
from chadhmm.distributions import (
    GaussianDistribution,
    TransitionMatrix,
    InitialDistribution
)
from chadhmm.schemas import Transitions

# Define model parameters
n_states = 3
n_features = 4
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# Create Gaussian emission distribution
emission_pdf = GaussianDistribution.sample_distribution(
    n_features=n_features,
    n_components=n_states
)

# Create transition matrix (ergodic: all transitions allowed)
transition_matrix = TransitionMatrix.sample_from_dirichlet(
    transition_type=Transitions.ERGODIC,
    prior=1.0,
    target_size=torch.Size([n_states, n_states])
)

# Create initial state distribution
initial_distribution = InitialDistribution.sample_from_dirichlet(
    prior=1.0,
    target_size=torch.Size([n_states])
)

# Build the HMM
hmm = HMM(
    transition_matrix=transition_matrix,
    initial_distribution=initial_distribution,
    emission_pdf=emission_pdf,
    dtype=torch.float32,
    device=device
)

Left-to-Right HMM (for temporal sequences)

# Create a left-to-right topology (useful for speech, time series)
transition_matrix = TransitionMatrix.sample_from_dirichlet(
    transition_type=Transitions.LEFT_TO_RIGHT,
    prior=1.0,
    target_size=torch.Size([n_states, n_states])
)

hmm = HMM(
    transition_matrix=transition_matrix,
    initial_distribution=initial_distribution,
    emission_pdf=emission_pdf
)

Hidden Semi-Markov Models (HSMM)

HSMMs extend HMMs by explicitly modeling state durations.

import torch
from chadhmm import HSMM
from chadhmm.distributions import (
    GaussianDistribution,
    TransitionMatrix,
    InitialDistribution,
    DurationDistribution
)
from chadhmm.schemas import Transitions

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# Create emission distribution
emission_pdf = GaussianDistribution.sample_distribution(
    n_features=4,
    n_components=3
)

# Create transition matrix
transition_matrix = TransitionMatrix.sample_from_dirichlet(
    transition_type=Transitions.ERGODIC,
    prior=1.0,
    target_size=torch.Size([3, 3])
)

# Create initial distribution
initial_distribution = InitialDistribution.sample_from_dirichlet(
    prior=1.0,
    target_size=torch.Size([3])
)

# Create duration distribution (max duration = 6)
duration_distribution = DurationDistribution.sample_from_dirichlet(
    prior=1.0,
    target_size=torch.Size([3, 6])  # [n_states, max_duration]
)

# Build the HSMM
hsmm = HSMM(
    transition_matrix=transition_matrix,
    initial_distribution=initial_distribution,
    duration_distribution=duration_distribution,
    emission_pdf=emission_pdf,
    dtype=torch.float32,
    device=device
)

Model Training

Basic Training

# Single sequence
X = torch.randn(100, 4)  # 100 timesteps, 4 features
hmm.fit(X)

Training with Multiple Sequences

# Concatenate multiple sequences
X = torch.randn(500, 4)  # Total length = 500
lengths = [100, 150, 250]  # Three sequences

hmm.fit(X, lengths=lengths)

Training with Custom Parameters

hmm.fit(
    X,
    lengths=[100, 150, 250],
    max_iter=100,           # Maximum EM iterations
    n_init=5,               # Number of random initializations
    tol=1e-4,               # Convergence tolerance
    verbose=True            # Print progress
)

Training Mode and Compilation

ChadHMM models inherit from torch.nn.Module and support training mode control similar to PyTorch. The models use compiled forward/backward algorithms during training for maximum performance, and automatically switch to non-compiled versions during inference to avoid compilation overhead.

# Training mode (uses compiled algorithms for speed)
hmm.train()
hmm.fit(X, max_iter=20)

# Evaluation mode (uses non-compiled algorithms to avoid overhead)
hmm.eval()
predictions = hmm.predict(X_test, algorithm=DecodingAlgorithm.VITERBI)
log_likelihood = hmm.score(X_test)

Inference and Decoding

Viterbi Algorithm (Most Likely Path)

from chadhmm.schemas import DecodingAlgorithm

# Find the most likely sequence of states
states = hmm.predict(X, algorithm=DecodingAlgorithm.VITERBI)
print(states)  # tensor([0, 0, 1, 1, 2, 2, ...])

MAP Decoding (Maximum A Posteriori)

# Find most likely state at each timestep
states = hmm.predict(X, algorithm=DecodingAlgorithm.MAP)

Decoding Multiple Sequences

X = torch.randn(500, 4)
lengths = [100, 150, 250]

states = hmm.predict(
    X,
    lengths=lengths,
    algorithm=DecodingAlgorithm.VITERBI
)

Model Evaluation

Computing Log-Likelihood

# Total log-likelihood
total_log_likelihood = hmm.score(X)

# Log-likelihood per sequence
log_likelihoods = hmm.score(
    X,
    lengths=[100, 150, 250],
    by_sample=True
)
print(log_likelihoods)  # [tensor(-234.5), tensor(-456.7), tensor(-678.9)]

Information Criteria for Model Selection

from chadhmm.schemas import InformCriteria

# Akaike Information Criterion
aic = hmm.ic(X, criterion=InformCriteria.AIC)

# Bayesian Information Criterion
bic = hmm.ic(X, criterion=InformCriteria.BIC)

# Hannan-Quinn Criterion
hqc = hmm.ic(X, criterion=InformCriteria.HQC)

# For multiple sequences
ics = hmm.ic(
    X,
    lengths=[100, 150, 250],
    criterion=InformCriteria.BIC
)

Generating Samples

# Generate synthetic data from the model
samples, states = hmm.sample(n_samples=100)
print(samples.shape)  # torch.Size([100, n_features])
print(states.shape)   # torch.Size([100])

Available Distributions

Emission Distributions

DistributionUse CaseExample
GaussianDistributionContinuous data, single mode per stateTemperature, stock prices
GaussianMixtureDistributionContinuous data, multiple modes per stateComplex time series
MultinomialDistributionCount data, discrete observationsWord counts, histograms
PoissonDistributionCount data, rare eventsNumber of events per interval

State Distributions

DistributionPurpose
InitialDistributionStarting state probabilities
TransitionMatrixState transition probabilities
DurationDistributionState duration probabilities (HSMM only)

Transition Types

  • Transitions.ERGODIC: All state transitions allowed
  • Transitions.LEFT_TO_RIGHT: Only forward transitions (+ self-loops)
  • Custom: Define your own transition matrix

Covariance Types (for Gaussian models)

  • CovarianceType.FULL: Full covariance matrix
  • CovarianceType.DIAG: Diagonal covariance matrix
  • CovarianceType.SPHERICAL: Spherical (single variance) covariance

Roadmap

Planned Features

  • Contextual Models

    • Time-dependent contextual variables
    • Contextual variables for covariances using GEM (Generalized Expectation Maximization)
    • Contextual variables for multinomial emissions
    • Parametric/Conditional HMM support
  • Model Enhancements

    • Auto-regressive HMM/HSMM
    • Online/streaming learning support
    • Variational inference methods
  • Documentation & Examples

    • Comprehensive tutorials for each distribution type
    • Financial time series analysis examples
    • Speech recognition example
    • Biological sequence analysis examples
  • Performance & Scalability

    • Distributed training support
    • Memory-efficient implementations for very long sequences
    • Mixed precision training

See the open issues for a full list of proposed features and known issues.

Unit Tests

To run the test suite:

# Run all tests
uv run pytest

# Run with coverage
uv run pytest --cov=chadhmm

# Run specific test file
uv run pytest tests/test_hmm.py

Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

See CONTRIBUTING.md for more details.

License

This project is licensed under the MIT License - see the LICENSE file for details.

References

This implementation is based on the following research:

Hidden Markov Models (HMM)

Hidden Semi-Markov Models (HSMM)

Contextual HMM

Citation

If you use ChadHMM in your research, please consider citing:

@software{chadhmm2024,
  author = {GarroshIcecream},
  title = {ChadHMM: Hidden Markov Models in PyTorch},
  year = {2024},
  url = {https://github.com/GarroshIcecream/ChadHMM}
}

Acknowledgments