Measured data often follows a known mathematical shape while still carrying noise from sampling, sensors, or simulation. SciPy provides scipy.optimize.curve_fit() for estimating the unknown parameters of that shape, such as an amplitude, decay rate, or baseline value.

The curve_fit() function expects a model callable whose first argument is the independent variable and whose remaining arguments are the fitted parameters. It returns optimized parameter values and an approximate covariance matrix, so one run can report fitted values, parameter standard errors, residual size, and an uncertainty sanity check.

A small exponential-decay data set keeps the fit easy to judge without turning the task into a plotting or data-cleaning workflow. Keep real input arrays as floating-point data, choose starting values on the same scale as the expected parameters, and review residuals before using the fit in later analysis.

Steps to fit a curve to data with SciPy:

  1. Create a Python script that defines the model, data, initial guess, and bounds.
    fit_curve.py
    import numpy as np
    from scipy.optimize import curve_fit
     
     
    def decay_model(x, amplitude, decay, baseline):
        return amplitude * np.exp(-decay * x) + baseline
     
     
    x = np.linspace(0.0, 4.0, 9)
    y = np.array([2.91, 1.77, 1.15, 0.82, 0.62, 0.51, 0.44, 0.41, 0.39])
     
    initial_guess = (2.5, 1.0, 0.3)
    bounds = (0.0, [5.0, 5.0, 2.0])
     
    params, covariance = curve_fit(
        decay_model,
        x,
        y,
        p0=initial_guess,
        bounds=bounds,
    )
     
    stderr = np.sqrt(np.diag(covariance))
    fit = decay_model(x, *params)
    residuals = y - fit
    rmse = np.sqrt(np.mean(residuals**2))
    condition_number = np.linalg.cond(covariance)
     
    print(f"parameters: amplitude={params[0]:.3f}, decay={params[1]:.3f}, baseline={params[2]:.3f}")
    print(f"std_error: amplitude={stderr[0]:.3f}, decay={stderr[1]:.3f}, baseline={stderr[2]:.3f}")
    print(f"rmse: {rmse:.3f}")
    print(f"covariance_condition: {condition_number:.1f}")

    p0 supplies the starting parameter values. The bounds setting keeps the fitted amplitude, decay rate, and baseline positive for this decay model.

  2. Run the fit script.
    $ python fit_curve.py
    parameters: amplitude=2.534, decay=1.174, baseline=0.371
    std_error: amplitude=0.009, decay=0.011, baseline=0.006
    rmse: 0.007
    covariance_condition: 19.9

    The fitted parameters are returned in the same order as the model function parameters after x.

  3. Check the parameter standard errors before reporting the fit.

    The diagonal of the covariance matrix gives approximate parameter variances. Taking the square root produces one-standard-deviation errors when the model is well behaved near the optimum.

  4. Use the residual error as the fit-quality check.

    An rmse of 0.007 is small against response values that range from about 0.39 to 2.91, so the fitted curve follows this sample data closely.

  5. Rework the model if the covariance condition number is extreme.

    A very large covariance_condition can indicate redundant parameters, mismatched parameter scales, or unstable uncertainty estimates. Simplify the model, rescale parameters, or choose better starting values before trusting the standard errors.