curve_fit() takes a model function f, which accepts the independent variable plus the parameters to be fit, arrays of observed x and y data, and an optional initial parameter guess p0, then finds the parameter values that minimize the sum of squared differences between the model's predictions and the actual observed data. It returns a tuple of the best-fit parameters and their estimated covariance matrix, from which you can compute standard errors/uncertainty on each fitted parameter.
1Understanding optimize.curve_fit()
curve_fit() takes a model function f, which accepts the independent variable plus the parameters to be fit, arrays of observed x and y data, and an optional initial parameter guess p0, then finds the parameter values that minimize the sum of squared differences between the model's predictions and the actual observed data. It returns a tuple of the best-fit parameters and their estimated covariance matrix, from which you can compute standard errors/uncertainty on each fitted parameter.
Provide a reasonable initial guess via p0 for anything beyond a simple linear model — curve_fit() defaults to starting all parameters at 1, which can cause the fit to fail or converge to a poor result for models where that's a bad starting point, like an exponential decay model.
from scipy import optimize
import numpy as np
def model(x, a, b):
return a * x + b
x_data = np.array([1, 2, 3, 4])
y_data = np.array([2.1, 3.9, 6.2, 7.8])
params, _ = optimize.curve_fit(model, x_data, y_data)
print(np.round(params, 2))2Practical Example
Here is a real-world application of optimize.curve_fit() showing how it is used in production SciPy code.
from scipy import optimize
import numpy as np
def model(x, a, b, c):
return a * np.exp(-b * x) + c
x_data = np.array([0, 1, 2, 3, 4])
y_data = np.array([10, 6, 4, 3, 2.5])
params, _ = optimize.curve_fit(model, x_data, y_data, p0=[8, 0.5, 1])
print(np.round(params, 1))3Best Practices
Follow these guidelines when working with optimize.curve_fit():
1. Provide p0 with a sensible initial guess for the model's parameters, especially for non-linear models, rather than relying on the default starting values
2. Extract parameter uncertainty from the returned covariance matrix, the square root of its diagonal, rather than treating the fitted parameters as exact
3. Visually plot the fitted curve against the actual data points as a sanity check, rather than trusting a numerically successful fit blindly
Tip: Provide a reasonable initial guess via p0 for anything beyond a simple linear model — curve_fit() defaults to starting all parameters at 1, which can cause the fit to fail or converge to a poor result for models where that's a bad starting point, like an exponential decay model.
from scipy import optimize
import numpy as np
def model(x, a, b):
return a * x + b
x_data = np.array([1, 2, 3, 4])
y_data = np.array([2.1, 3.9, 6.2, 7.8])
params, _ = optimize.curve_fit(model, x_data, y_data)
print(np.round(params, 2))