Rye
Rye

Reputation: 177

Curve fit error: "Covariance of the parameters could not be estimated" to logistic model

I am trying to use curve_fit to fit the following data to a logistic function, as seen bellow. My code for this is very simple:

X=[0,15,30,45,60,75,90,105,120,135,150,165,180]
Y=[0.037812, 0.037735, 0.037721, 0.037634, 0.037373, 0.037173, 0.036373, 0.035833, 0.035741, 0.035727, 0.035668, 0.035674, 0.035652]

def logistic(x,a,b,c,d):
    return a / (1.0 + np.exp(-c * (x - d))) + b

popt, pcov = fit(logistic, X, Y)

plt.plot(X,Y, 'o',label='Data')
lin=np.linspace(0,180,1000)
plt.plot(lin,logistic(lin,*pop), '--')

But when I run it I get this error:

OptimizeWarning: Covariance of the parameters could not be estimated

and the plotted curve looks nothing like it should. Can anyone see why Python can't fit my data to a logistic curve? LogFit

Upvotes: 1

Views: 2732

Answers (1)

mCoding
mCoding

Reputation: 4839

If your fit is bad, the most common fix is to specify reasonable starting points for the optimization via the p0 parameter (which defaults to all ones): https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.curve_fit.html. The fit in your picture actually looks like a local minimum (quickly become constant equal to the average value of the data), so better initial guesses for the parameters will probably help.

import numpy as np
from matplotlib import pyplot as plt
from scipy.optimize import curve_fit as fit


def logistic(x, a, b, c, d):
    return a / (1.0 + np.exp(-c * (x - d))) + b


def main():
    X = [0, 15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165, 180]
    Y = [0.037812, 0.037735, 0.037721, 0.037634, 0.037373, 0.037173, 0.036373, 0.035833, 0.035741, 0.035727, 0.035668, 0.035674, 0.035652]

    p0 = (1., 1., 1./100, 75.)
    popt, pcov = fit(logistic, X, Y, p0=p0)

    plt.figure()
    plt.plot(X, Y, 'o', label='Data')
    lin = np.linspace(0, 180, 1000)
    plt.plot(lin, logistic(lin, *popt), '--')
    plt.show()
    plt.close()


if __name__ == '__main__':
    main()

Indeed, here's the fit I got just by changing the p0 parameter:

logistic fit

Upvotes: 1

Related Questions