31

我正在尝试将 sigmoid 函数拟合到我拥有的一些数据中,但我不断得到:ValueError: Unable to determine number of fit parameters.

我的数据如下所示:

在此处输入图像描述

我的代码是:

from scipy.optimize import curve_fit

def sigmoid(x):
    return (1/(1+np.exp(-x)))

popt, pcov = curve_fit(sigmoid, xdata, ydata, method='dogbox')

然后我得到:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-5-78540a3a23df> in <module>
      2     return (1/(1+np.exp(-x)))
      3 
----> 4 popt, pcov = curve_fit(sigmoid, xdata, ydata, method='dogbox')

~\Anaconda3\lib\site-packages\scipy\optimize\minpack.py in curve_fit(f, xdata, ydata, p0, sigma, absolute_sigma, check_finite, bounds, method, jac, **kwargs)
    685         args, varargs, varkw, defaults = _getargspec(f)
    686         if len(args) < 2:
--> 687             raise ValueError("Unable to determine number of fit parameters.")
    688         n = len(args) - 1
    689     else:

ValueError: Unable to determine number of fit parameters.

我不确定为什么这不起作用,这似乎是一个微不足道的动作-> 将曲线拟合到某个点。所需的曲线如下所示:

在此处输入图像描述

对不起图形..我是在 PowerPoint 中完成的...

如何找到最佳的 sigmoid(“S”形)曲线?

更新

感谢@Brenlla,我将代码更改为:

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

popt, pcov = curve_fit(sigmoid, xdata, ydata, method='dogbox')

现在我没有收到错误,但曲线并不如预期:

x = np.linspace(0, 1600, 1000)
y = sigmoid(x, *popt)

plt.plot(xdata, ydata, 'o', label='data')
plt.plot(x,y, label='fit')
plt.ylim(0, 1.3)
plt.legend(loc='best')

结果是:

在此处输入图像描述

我该如何改进它以便更好地适应数据?

更新2

现在的代码是:

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

但是结果还是...

在此处输入图像描述

4

2 回答 2

18

在@Brenlla 的大力帮助下,代码被修改为:

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

p0 = [max(ydata), np.median(xdata),1,min(ydata)] # this is an mandatory initial guess

popt, pcov = curve_fit(sigmoid, xdata, ydata,p0, method='dogbox')

优化的参数是L, x0, k, b,它们最初分配在p0,优化开始的点。

  • L负责将输出范围从 [0,1] 缩放到 [0,L]
  • b向输出添加偏差并将其范围从 [0,L] 更改为 [b,L+b]
  • k负责缩放输入,保留在 (-inf,inf)
  • x0是 Sigmoid 中间的点,即 Sigmoid 最初应该输出值的点1/2[因为如果 x=x0,我们得到 1/(1+exp(0)) = 1/2]。

结果:

在此处输入图像描述

于 2020-06-05T12:27:33.697 回答
0

注意 - 早些时候有一些关于初步估计的问题。我的数据特别混乱,上面的解决方案大部分时间都有效,但偶尔会完全错过。通过将方法从更改为'dogbox'来解决这个问题'lm'

p0 = [max(ydata), np.median(xdata),1,min(ydata)] # this is an mandatory initial guess
popt, pcov = curve_fit(sigmoid, xdata, ydata,p0, method='lm') ## Updated method from 'dogbox' to 'lm' 9.30.2021

超过大约 50 条拟合曲线,它根本没有改变运行良好的曲线,而是完全解决了挑战案例。

重点是,在所有情况下,您和您的数据都是一片特殊的雪花,因此不要害怕挖掘并查看您从互联网复制的函数的参数。

于 2021-10-01T06:40:01.780 回答