最小二乘函数和4参数物流功能不起作用

时间:2017-10-10 19:52:04

标签: python scipy curve-fitting

相对较新的python,主要用于绘制事物。我目前正在尝试使用4参数logistic(4PL)方程和scipy的曲线拟合来确定最佳拟合线。有一个或两个站点显示4PL如何工作,但无法让它们为我的数据工作。例如,但下面的类似4PL数据:

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
import scipy.optimize as optimization

xdata = [2.3, 2.3, 2, 2, 1.7, 1.7, 1, 1, 0.000001, 0.000001, -1, -1]
ydata = [0.32, 0.3, 0.55, 0.60, 0.88, 0.92, 1.27, 1.21, 1.15, 1.12, 1.1, 1.1]
def fourPL(x, A, B, C, D):
    return ((A-D)/(1.0+((x/C)**(B))) + D)
guess = [0, -0.5, 0.5, 1]
params, params_covariance = optimization.curve_fit(fourPL, xdata, ydata, 
guess)
params

发出警告(在测试数据中也是指数警告,但不是真实的):

OptimizeWarning: Covariance of the parameters could not be estimated
category=OptimizeWarning)

并且params返回我最初的猜测。我尝试了各种初步猜测。

在绘制时绘制最佳拟合线,但不是曲线并且不会低于x = 0(我找不到负面因素会使4PL模型混乱)。 4PL fit plotted

我不确定我是否对方程做了不正确的事,或者曲线拟合函数是如何工作的,或两者兼而有之。我有一个类似的问题使用最小二乘而不是曲线拟合。我已经尝试了一系列基于相似等式的变化以适应等等但已经停留了一段时间,任何帮助指向我正确的方向将非常感激。

1 个答案:

答案 0 :(得分:1)

我很惊讶你没有得到任何警告或没有与我们分享。我无法通过科学手段为您分析这项任务,只是对技术内容的一些评论:

观察

运行代码时,应该发出一些警告:

RuntimeWarning: invalid value encountered in power
  return ((A-D)/(1.0+((x/C)**(B))) + D)

不要忽视这一点!

调试

在函数fourPL中添加一些打印件,可能是函数的所有不同组件,看看发生了什么。

示例:

def fourPL(x, A, B, C, D):
    print('1: ', (A-D))
    print('2: ', (x/C))
    print('3: ', (1.0+((x/C)**(B))))

    return ((A-D)/(1.0+((x/C)**(B))) + D)

...
params, params_covariance = optimization.curve_fit(fourPL, xdata, ydata, guess, maxfev=1)
# maxfev=1 -> let's just check 1 or few it's

输出:

1:  -1.0
2:  [  4.60000000e+00   4.60000000e+00   4.00000000e+00   4.00000000e+00
   3.40000000e+00   3.40000000e+00   2.00000000e+00   2.00000000e+00
   2.00000000e-06   2.00000000e-06  -2.00000000e+00  -2.00000000e+00]
RuntimeWarning: invalid value encountered in power
  print('3: ', (1.0+((x/C)**(B))))
3:  [   1.4662524     1.4662524     1.5           1.5           1.54232614
    1.54232614    1.70710678    1.70710678  708.10678119  708.10678119
           nan           nan]

这足以让我们停下来。 nans和infs很糟糕!

理论

现在是理论的时候了,我不会这样做。但通常你现在应该考虑基础理论以及为什么会出现这些问题。

您在假设方面是否遗漏了一些内容?

修复(不检查理论)

没有查看理论,只是查看30秒内发现的example:嗯,负x值是一个问题吗?

让我们移动x(最小值;硬编码1):

xdata = np.array([2.3, 2.3, 2, 2, 1.7, 1.7, 1, 1, 0.000001, 0.000001, -1, -1]) + 1

完整代码:

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
import scipy.optimize as optimization

xdata = np.array([2.3, 2.3, 2, 2, 1.7, 1.7, 1, 1, 0.000001, 0.000001, -1, -1]) + 1
ydata = np.array([0.32, 0.3, 0.55, 0.60, 0.88, 0.92, 1.27, 1.21, 1.15, 1.12, 1.1, 1.1])

def fourPL(x, A, B, C, D):
    return ((A-D)/(1.0+((x/C)**(B))) + D)

guess = [0, -0.5, 0.5, 1]
params, params_covariance = optimization.curve_fit(fourPL, xdata, ydata, guess)#, maxfev=1)

x_min, x_max = np.amin(xdata), np.amax(xdata)
xs = np.linspace(x_min, x_max, 1000)
plt.scatter(xdata, ydata)
plt.plot(xs, fourPL(xs, *params))
plt.show()

输出:

RuntimeWarning: divide by zero encountered in power
  return ((A-D)/(1.0+((x/C)**(B))) + D)

enter image description here

看起来很不错,但现在是另一个理论会议的时候了:我们的线性转换对我们的结果做了什么?我再次忽略了这一点。

所以只有一个警告和一个漂亮的输出。

如果你想删除最后一个警告,添加一些小epsilon在xdata中没有0:

xdata = np.array([2.3, 2.3, 2, 2, 1.7, 1.7, 1, 1, 0.000001, 0.000001, -1, -1]) + 1 + 1e-10

将达到相同的目的,没有任何警告。