سؤال

I have used numpy in python to fit my data to a sigmoidal curve. How can I find the vaue for X at y=50% point in the curve after the data is fit to the curve

enter code here`import numpy as np
enter code here`import pylab
from scipy.optimize import curve_fit

def sigmoid(x, x0, k):
   y = 1 / (1 + np.exp(-k*(x-x0)))
   return y

xdata = np.array([0.0,   1.0,  3.0, 4.3, 7.0,   8.0,   8.5, 10.0, 12.0])
ydata = np.array([0.01, 0.02, 0.04, 0.11, 0.43,  0.7, 0.89, 0.95, 0.99])

popt, pcov = curve_fit(sigmoid, xdata, ydata)
print popt

x = np.linspace(-1, 15, 50)
y = sigmoid(x, *popt)

pylab.plot(xdata, ydata, 'o', label='data')
pylab.plot(x,y, label='fit')
pylab.ylim(0, 1.05)
pylab.legend(loc='best')
pylab.show()
هل كانت مفيدة؟

المحلول

You just need to solve the function you found for y(x) = 0.50. You can use one of the root finding tools of scipy, though these only solve for zero, so you need to give your function an offset:

def sigmoid(x, x0, k, y0=0):
   y = 1 / (1 + np.exp(-k*(x-x0))) + y0
   return y

Then it's just a matter of calling the root finding method of choice:

from scipy.optimize import brentq

a = np.min(xdata)
b = np.max(xdata)
x0, k = popt
y0 = -0.50

solution = brentq(sigmoid, a, b, args=(x0, k, y0))  # = 7.142

In addition to your comment:

My code above uses the original popt that was calculated with your code. If you do the curve fitting with the updated sigmoid function (with the offset), popt will also contain a fitted parameter for y0.

Probably you don't want this.. you'll want the curve fitted for y0=0. This can be done by supplying a guess for the curve_fit with only two values. This way the default value for y0 of the sigmoid function will be used:

popt, pcov = curve_fit(sigmoid, xdata, ydata, p0 = (1,1))

Alternatively, just declare two seperate sigmmoid functions, one with the offset and one without it.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top