Source code for lossmodels.estimation.frequency_selection

import numpy as np

from .diagnostics import aic, bic
from .mle import fit_poisson, fit_negbinomial
from .moments import fit_poisson_moments, fit_negbinomial_moments


FREQUENCY_MLE_FITTERS = {
    "poisson": (fit_poisson, 1),
    "negbinomial": (fit_negbinomial, 2),
}

FREQUENCY_MOMENT_FITTERS = {
    "poisson": (fit_poisson_moments, 1),
    "negbinomial": (fit_negbinomial_moments, 2),
}


[docs] def fit_best_frequency(data, candidates=None, method="mle", criterion="aic"): """ Fit a set of frequency models and return the best one by AIC or BIC. """ data = np.asarray(data) if data.size == 0: raise ValueError("data must not be empty.") if np.any(data < 0): raise ValueError("frequency data must be nonnegative.") if method not in {"mle", "moments"}: raise ValueError("method must be 'mle' or 'moments'.") if criterion not in {"aic", "bic"}: raise ValueError("criterion must be 'aic' or 'bic'.") fitters = ( FREQUENCY_MLE_FITTERS if method == "mle" else FREQUENCY_MOMENT_FITTERS ) if candidates is None: candidates = list(fitters.keys()) results = [] for name in candidates: if name not in fitters: raise ValueError(f"Unsupported candidate: {name}") fitter, k = fitters[name] try: model = fitter(data) score = aic(model, data, k=k) if criterion == "aic" else bic(model, data, k=k) results.append({ "name": name, "model": model, "k": k, "score": float(score), }) except Exception as exc: results.append({ "name": name, "model": None, "k": k, "score": float("inf"), "error": str(exc), }) valid = [r for r in results if np.isfinite(r["score"])] if not valid: raise RuntimeError("No candidate frequency models could be fit successfully.") best = min(valid, key=lambda r: r["score"]) return { "best_name": best["name"], "best_model": best["model"], "criterion": criterion, "method": method, "results": results, }