AIC and AICc wrappers for scipy and lmfit
Project description
fit_aic
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.
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: IfTrue, returns 5-tuple with infodict containingaicandaicc(default:False)
Returns:
- If
full_output=False: Returns(popt, pcov)— identical to scipy behavior - If
full_output=True: Returns(popt, pcov, infodict, mesg, ier)whereinfodictincludesaicandaicckeys
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f572f7fd3a827f3c50cfeab9d59550b18de194f4a722c8a424f8f9aca97ebdfe
|
|
| MD5 |
dcf90778c7b418612e791eb16475906c
|
|
| BLAKE2b-256 |
a6492100ac102645ddac6594bdd9d801a559f3188804d5449b36e6adaef062b3
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cf7924b8a132c9b0b1c49fff9cd452d18ca59a7f243123fc56ce57623fff4771
|
|
| MD5 |
117cbcb6ef2b01817899d1e74509de13
|
|
| BLAKE2b-256 |
d1368fba5db4b669da7ec4b623a16a4673330781fdafb7105d0edcd4bf2bd5a4
|