Skip to content

Model Comparison: aic(), bic(), and compare_models()

After fitting one or more HMMs, use information criteria to compare specifications (for example different numbers of hidden states or clusters). Lower AIC or BIC generally indicates a better trade-off between fit and complexity.

aic()

Function Usage

python
aic(model, log_likelihood=None)

seqHMM Mapping

Equivalent to stats::AIC(logLik(model)) in R after fitting a seqHMM object.

Parameters

ParameterRequiredTypeDescription
modelHMM / MHMM / NHMMFitted model.
log_likelihoodfloat / NoneOverride log-likelihood; default uses model.log_likelihood.

Returns

float: AIC = −2 × log-likelihood + 2 × n_parameters.


bic()

Function Usage

python
bic(model, log_likelihood=None)

seqHMM Mapping

Equivalent to stats::BIC(logLik(model)) in R.

Parameters

ParameterRequiredTypeDescription
modelHMM / MHMM / NHMMFitted model.
log_likelihoodfloat / NoneOverride log-likelihood.

Returns

float: BIC = −2 × log-likelihood + log(n_observations) × n_parameters.

BIC penalizes complexity more strongly than AIC when the sample is large.


compare_models()

Function Usage

python
compare_models(models, criterion="BIC")

seqHMM Mapping

No single exported R function; typical workflow compares logLik, AIC, and BIC across fitted models manually.

Parameters

ParameterRequiredTypeDescription
modelslistList of fitted HMM, MHMM, or NHMM objects.
criterionstr"AIC" or "BIC". Default "BIC".

Returns

A dict:

KeyDescription
criterion"AIC" or "BIC"
modelsSorted list of dicts with model, log_likelihood, n_parameters, n_observations, and criterion value
best_modelLabel of the lowest-criterion model ("Model 1", …)

Helper Functions

compute_n_parameters(model)

Counts free parameters (accounting for simplex constraints on probability rows). Used internally by aic() and bic().

compute_n_observations(model)

Counts effective observations. For multichannel HMM, each fully observed time point counts as one observation (channels are pooled per seqHMM convention).


Example: Choose the Number of Hidden States

python
from sequenzo.seqhmm import build_hmm, fit_model, aic, bic, compare_models

models = []
for n in [3, 4, 5, 6]:
    hmm = build_hmm(seq, n_states=n, random_state=42)
    hmm = fit_model(hmm, verbose=False)
    models.append(hmm)

comparison = compare_models(models, criterion="BIC")
print(comparison["best_model"])

for i, m in enumerate(models):
    print(f"n_states={3+i}: AIC={aic(m):.1f}, BIC={bic(m):.1f}")

Notes

  • All models must be fitted before comparison.
  • Compare models fit on the same data and intended for the same question (do not mix HMM and MHMM unless you have a clear reason).
  • BIC is often preferred for choosing the number of states/clusters; AIC can be less conservative.

Authors

Code: Yuqi Liang

Documentation: Yuqi Liang

References

Helske, S., & Helske, J. (2019). Mixture hidden Markov models for sequence data: The seqHMM package in R. Journal of Statistical Software, 88(3), 1–32.