Source code for mrv.models.gmm

"""mrv.models.gmm -- Gaussian Mixture Model."""

from __future__ import annotations

import logging
from typing import Optional

import numpy as np
import pandas as pd

# Default RNG seed for reproducible model fitting.
_DEFAULT_SEED = 1

logger = logging.getLogger(__name__)

__all__ = ["fit_gmm"]


[docs] def fit_gmm(features: pd.DataFrame, K: int = 3, **kwargs) -> Optional[np.ndarray]: """Fit a Gaussian Mixture Model and return hard regime labels. Parameters ---------- features : pd.DataFrame Normalised feature matrix. Rows with NaN are dropped before fitting. K : int, default 3 Number of mixture components (regime states). **kwargs ``random_state`` (default 1) and ``n_init`` (default 10) are forwarded to ``sklearn.mixture.GaussianMixture``. Returns ------- np.ndarray or None Integer label array of shape ``(n_obs,)`` where ``n_obs = len(features.dropna())``, or ``None`` when the input is too short to fit (fewer than ``max(K * 5, 20)`` rows after NaN removal). """ from sklearn.mixture import GaussianMixture X = features.dropna().values if len(X) < max(K * 5, 20): logger.warning("GMM: insufficient data (%d rows)", len(X)) return None gmm = GaussianMixture( n_components=K, random_state=kwargs.get("random_state", _DEFAULT_SEED), n_init=kwargs.get("n_init", 10), ) return gmm.fit_predict(X)