Skip to main content

AIC and AICc wrappers for scipy and lmfit

Project description

fit_aic

PyPI version

AIC and AICc wrappers for scipy and lmfit, making it easy to compute Akaike information criteria for model comparison.

Overview

fit_aic provides convenient wrappers around popular curve fitting libraries that automatically compute AIC (Akaike Information Criterion) and AICc (corrected AIC) values. This makes model comparison straightforward without manual calculations.

Features

  • scipy.optimize.curve_fit wrapper: Drop-in replacement with automatic AIC/AICc computation
  • lmfit.Model wrapper: Drop-in replacement that adds AICc to the existing lmfit result
  • AIC and AICc calculations: Properly formatted and corrected for sample size
  • Seamless integration: Works with your existing scipy and lmfit code
  • Tested for accuracy: Validated against lmfit results

Background

The Akaike Information Criterion (AIC) and its corrected version for small sample sizes (AICc) is a metric for comparing statistical models that balances goodness of fit against model complexity [1, 2, 3]. A model with more parameters will always fit data better, but risks overfitting — AIC penalizes complexity to find the best tradeoff.

Given two models fit to the same data, the one with the lower AIC is preferred. The absolute value of AIC is not meaningful — only differences between models matter.

As an example we simulate data from a bi-exponential decay:

$$y = 3e^{-x/1} + 5e^{-x/10}$$

If we did not know the underlying analytical function of this process we might try fitting the data with different models to get an idea which model fits best. This is where the Akaike Information Criterion comes in. While increasing model complexity will reduce the residuals, there is no penalty for overfitting — AIC does provide this penalty. In our example we fit three models:

$$f_1(x) = a_1 e^{-x/t_1}$$

$$f_2(x) = a_1 e^{-x/t_1} + a_2 e^{-x/t_2}$$

$$f_3(x) = a_1 e^{-x/t_1} + a_2 e^{-x/t_2} + a_3 e^{-x/t_3}$$

The lowest AIC value can be used to select the best model that fits the data. This is illustrated in the figure below. Model 1 is plotted in blue, model 2 in orange, and model 3 in green. It appears model 2 and model 3 are almost identical, but model 2 is better as it has the lower AIC value — which makes sense given that the fits look the same but model 3 has 2 more free parameters.

AIC comparison

AICc is a corrected version of AIC for small sample sizes. As $n \to \infty$, AICc converges to AIC. It is recommended to always use AICc unless $n/k > 40$, where $n$ is the number of data points and $k$ the number of parameters.

A common rule of thumb for interpreting AIC differences ($\Delta AIC$):

  • $\Delta AIC < 2$: models are essentially equivalent
  • $2 < \Delta AIC < 10$: moderate evidence for the better model
  • $\Delta AIC > 10$: strong evidence for the better model

Installation

pip install fit_aic

Or with lmfit integration (optional):

pip install fit_aic[lmfit]

Quick Start

scipy wrapper

import numpy as np
from fit_aic.scipy import curve_fit

# Define your model
def exponential_decay(x, A, tau):
    return A * np.exp(-x / tau)

# Fit with AIC/AICc computation
x = np.linspace(0, 10, 50)
y = exponential_decay(x, 3, 2) + np.random.normal(0, 0.1, size=x.shape)

popt, pcov, infodict, mesg, ier = curve_fit(
    exponential_decay, x, y,
    p0=[3, 2],
    full_output=True
)
print(f"AIC: {infodict['aic']:.2f}")
print(f"AICc: {infodict['aicc']:.2f}")

lmfit wrapper

import numpy as np
from fit_aic.lmfit import Model

def exponential_decay(x, A, tau):
    return A * np.exp(-x / tau)

x = np.linspace(0, 10, 50)
y = exponential_decay(x, 3, 2) + np.random.normal(0, 0.1, size=x.shape)

model = Model(exponential_decay)
result = model.fit(y, x=x, A=3, tau=2)
print(f"AIC: {result.aic:.2f}")
print(f"AICc: {result.aicc:.2f}")

Model Comparison

import numpy as np
from fit_aic.scipy import curve_fit

def model1(x, A1, tau1, A2, tau2):
    return A1 * np.exp(-x / tau1) + A2 * np.exp(-x / tau2)

def model2(x, A1, tau1):
    return A1 * np.exp(-x / tau1)

x = np.linspace(0, 20, 50)
y = model1(x, 3, 1, 5, 10) + np.random.normal(0, 0.25, size=x.shape)

result1 = curve_fit(model1, x, y, p0=[3, 1, 5, 10], full_output=True)
result2 = curve_fit(model2, x, y, p0=[3, 2], full_output=True)

aic1 = result1[2]['aic']
aic2 = result2[2]['aic']
print(f"Model 1 AIC: {aic1:.2f}")
print(f"Model 2 AIC: {aic2:.2f}")
print(f"Best model: {'Model 1' if aic1 < aic2 else 'Model 2'}")

API Reference

fit_aic.scipy.curve_fit

Wrapper around scipy.optimize.curve_fit with AIC/AICc support.

Parameters:

  • All parameters are identical to scipy.optimize.curve_fit
  • full_output: If True, returns 5-tuple with infodict containing aic and aicc (default: False)

Returns:

  • If full_output=False: Returns (popt, pcov) — identical to scipy behavior
  • If full_output=True: Returns (popt, pcov, infodict, mesg, ier) where infodict includes aic and aicc keys

fit_aic.lmfit.Model

Subclass of lmfit.Model with AICc support. All existing lmfit behavior is preserved.

Additional attributes on ModelResult:

  • result.aicc: Corrected AIC value

Usage:

from fit_aic.lmfit import Model

model = Model(my_func)
result = model.fit(y, x=x, A=3, tau=2)
print(f"AIC: {result.aic:.2f}")   # lmfit built-in
print(f"AICc: {result.aicc:.2f}") # added by fit_aic

Information Criteria

AIC:

$$AIC = n \ln(RSS/n) + 2k$$

AICc:

$$AICc = AIC + \frac{2k(k+1)}{n-k-1}$$

Where:

  • $n$ = number of observations
  • $k$ = number of parameters
  • $RSS$ = residual sum of squares

AICc includes a correction for small sample sizes and converges to AIC as $n \to \infty$. It is recommended when $n/k < 40$.

Development

Install with dev dependencies:

pip install -e ".[dev]"

Run tests:

pytest tests/

License

MIT

References

[1] H. Akaike, "A New Look at the Statistical Model Identification," IEEE Trans. Autom. Control 19(6), 716–723 (1974). https://doi.org/10.1109/TAC.1974.1100705

[2] J. E. Cavanaugh, "Unifying the derivations for the Akaike and corrected Akaike information criteria," Stat. & Probab. Lett. 33(2), 201–208 (1997). https://doi.org/10.1016/S0167-7152(96)00128-9

[3] K. P. Burnham & D. R. Anderson, Model Selection and Multimodel Inference: A Practical Information-Theoretic Approach (2nd ed.). Springer, New York (1998).

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fit_aic-0.1.3.tar.gz (10.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fit_aic-0.1.3-py3-none-any.whl (10.6 kB view details)

Uploaded Python 3

File details

Details for the file fit_aic-0.1.3.tar.gz.

File metadata

  • Download URL: fit_aic-0.1.3.tar.gz
  • Upload date:
  • Size: 10.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for fit_aic-0.1.3.tar.gz
Algorithm Hash digest
SHA256 f572f7fd3a827f3c50cfeab9d59550b18de194f4a722c8a424f8f9aca97ebdfe
MD5 dcf90778c7b418612e791eb16475906c
BLAKE2b-256 a6492100ac102645ddac6594bdd9d801a559f3188804d5449b36e6adaef062b3

See more details on using hashes here.

File details

Details for the file fit_aic-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: fit_aic-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 10.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for fit_aic-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 cf7924b8a132c9b0b1c49fff9cd452d18ca59a7f243123fc56ce57623fff4771
MD5 117cbcb6ef2b01817899d1e74509de13
BLAKE2b-256 d1368fba5db4b669da7ec4b623a16a4673330781fdafb7105d0edcd4bf2bd5a4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page