Search code examples
pythonscipycurve-fittingdata-fittingscipy-optimize

scipy.curve_fit not fitting when the exponent of an exp has an exponent itself (constant)


I'm trying to fit this curve:

def logistic2_model(x, a, b, dtau, tau):
    return a/(1+b*np.exp(-np.power((x-dtau)/tau, 0.9)))

using curve_fit

x = [54L, 55L, 56L, 57L, 58L, 59L, 60L, 61L, 62L, 63L, 64L, 65L, 66L, 67L, 68L, 69L, 70L, 71L, 72L, 73L, 74L, 75L, 76L, 77L, 78L, 79L, 80L, 81L, 82L, 83L, 84L, 85L, 86L, 87L, 88L, 89L, 90L, 91L, 92L, 93L, 94L, 95L, 96L, 97L, 98L, 99L]
y = [229.0, 322.0, 400.0, 650.0, 888.0, 1128.0, 1694.0, 2036.0, 2502.0, 3089.0, 3858.0, 4636.0, 5883.0, 7375.0, 9172.0, 10149.0, 12462.0, 15113.0, 17660.0, 21157.0, 24747.0, 27980.0, 31506.0, 35713.0, 41035.0, 47021.0, 53578.0, 59138.0, 63927.0, 69176.0, 74386.0, 80539.0, 86498.0, 92472.0, 97689.0, 101739.0, 105792.0, 110574.0, 115242.0, 119827.0, 124632.0, 128948.0, 132547.0, 135586.0, 139422.0, 143626.0]

p0 = [1.52646450e+05, 1.56215676e-01, 9.59401246e+01, 6.23161909e+00]
fit = curve_fit(logistic2_model, x, y, maxfev=100000, p0=p0)

It only works if I use 1.0. If I use any other float, even close, it simply reaches maxfev with no success. With 2.0 it works in principle but the curve fitted doesn't make any sense.

p0 is the fit obtained with that exponent equal to 1.0: enter image description here

My original goal was to add that exponent to the parameters to fit but if it doesn't work even like that, no hope.

Any hint?


Solution

  • Please add the complete code, incl. plotting.

    For testing, please use the converged solution for 1.0 and add the points for say, 0.95 and 1.05 to the plot. This should give us and you an idea how sensitive your equation is regarding that parameter. Could be that the equation turns shit crazy.

    For the solution you posted (0.9) the covariance matrix returned is only np.inf.

    The docs state on this:

    If the Jacobian matrix at the solution doesn’t have a full rank, then ‘lm’ method returns a matrix filled with np.inf, on the other hand ‘trf’ and ‘dogbox’ methods use Moore-Penrose pseudoinverse to compute the covariance matrix.

    You could try any of the other methods using method='trf' or method='dogbox' to see if that somehow works out.

    But it could be that at least two of your variable tune the same thing and are not independent.