使用下面的代码,我无法在我的数据集中使用sigmoid函数。
但是,如果我在下面的代码中添加了偏移量t = x + 50 -x0
,那么它非常合适。
x0
不应该照顾合适的人吗?
import numpy as np
import pylab
from scipy.optimize import curve_fit
listA = np.array([-110,-105,-100,-95,-90,-85,-80,-75,-70,-65,-60,-55,-50,-45])
listB = np.array([1,1,1,1,0.926470588,0.852941176,0.616803279,0.371212121,
0.191066998,0.088565022,0.06684492,0.019855596,0.015517241,0])
def sigmoid(x,x0,k,y0):
t = x -x0
y = y0-1/(1 + np.exp(-k*t))
return y
popt, pcov = curve_fit(sigmoid, listA, listB)
print popt ,pcov
x = np.linspace(-110,-45,50)
y = sigmoid(x, *popt)
pylab.plot(listA, listB, 'o', label='data')
pylab.plot(x,y, label='fit')
pylab.ylim(-0.05, 1.05)
pylab.legend(loc='best')
pylab.show()
答案 0 :(得分:3)
您正在遇到初始条件敏感度的经典案例。 curve_fit
函数接受关键字参数p0
,可让您为函数的自由参数选择初始“猜测”(在您的情况下为x0
,k
,和y0
)。
如果未提供p0
,则scipy会假定所有参数will start at one。对于你的函数,这意味着sigmoid的分母将非常接近于零,因此函数值会爆炸。这会使解算器混淆并导致解决方案不佳。
不幸的是,这个问题没有一个解决方案,因为它需要了解你想要适应的功能的动态。在您的情况下,提供p0
(-30, 1, 0)
将允许求解器收敛到一个合适的解决方案。
答案 1 :(得分:3)
这是因为问题涉及到大量数字,使曲线拟合算法快速分化。
p0
的(默认)初始猜测curve_fit
是所有1的数组:
p0:无,标量或M长度序列 初步猜测参数。如果是None,那么最初 值将全部为1(如果函数的参数数量 可以使用内省来确定,否则就是ValueError 被提出。)
表示您的问题[1,1,1]
。使用您的第一个x0值-110
,这将导致指数的参数为:-1 * (-110-1)
,从而导致np.exp(111)
巨大数字,远远大于它被添加到的常数1。即使对于x0
的初始猜测的小变化,结果也是与y0
求和的分数几乎为零。这就是为什么你也会看到问题的原因popt
会返回[1, 1, .51]
:算法在x0
中找不到微小的变化,对其产生重大影响结果(y
)。
解决方案确实提供了一个不错的猜测。算法将用于参数的变化也取决于这些参数的大小。提供[-45, 1, 1]
也会产生一个很好的解决方案,-90
的初始猜测x0
也是如此:只需确保水平偏移量至少为"关闭"到独立变量的值(在你的情况下为listA
的值)。