2015-01-26 135 views
1

使用下面的代码我无法将sigmoid函数拟合到我的数据集中。 但是,如果我在下面的代码中添加一个偏移量t = x + 50 -x0,它很合适。为什么我无法使用scipy.optimize.curve_fit将sigmoid函数适用于此数据?

不应该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() 

回答

3

您正在运行到初始条件敏感性的经典案例。 curve_fit函数接受关键字参数p0,它允许您为函数的自由参数(在您的情况下为x0ky0)选择初始“猜测”。

当没有提供p0时,scipy假定所有参数为will start at one。对于你的函数来说,这意味着sigmoid的分母将非常接近于零,所以函数值会爆炸。这混淆了求解器,并导致了一个糟糕的解决方案。

不幸的是,这个问题没有解决方案,因为它需要了解您正在尝试适配的功能的动态。在你的情况下,提供一个p0(-30, 1, 0)将允许解算器收敛到一个体面的解决方案。

+0

感谢perimosocordiae ......有道理..是否有R-square或回归scoe输出,我可以从curve_fit得到这将帮助我猜这样的问题.... – vivekbecks 2015-01-27 00:14:38

+0

虽然'p0'的假设不正确,但会导致错误分析。但是,您的陈述“初始条件敏感性的经典案例”为真,以及您的最后一段。 – 2015-01-27 00:18:19

+0

@vivekbecks是的,总是检查'pcov'的值。如果它是'inf',则出现问题。 – 2015-01-27 00:19:51

3

这是因为问题处理的数量很大,使得曲线拟合算法很快发生分歧。

(默认的)初始猜测,p0,对于curve_fit都是一数组:

P0:无,标量,或者M-长度序列 的参数的初始猜测。如果没有,那么最初的 值将全部为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也是如此:只要确保水平偏移量至少与独立变量的值“接近”(在您的情况下为listA的值)即可。

相关问题