Python 中 sigmoid 函数的曲线拟合和外推

问题描述 投票:0回答:2

我有以下数据集:

import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt

## Given datapoints
xdata = np.array([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26])
ydata = np.array([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.99330715, 0.98201379, 0.95257413, 0.88079708, 0.73105858, 0.5])


## Plot the data
plt.plot(xdata, ydata)
plt.xlabel('x')
plt.ylabel('sigmoid(x)')
plt.xlim([-1,31])
plt.ylim(0, 1.05)
plt.show()

上面的数据看起来是这样的:

需要使用 python 中的 curve_fit 校准和外推 y 从 1 到 0 的曲线。

我正在尝试使用 sigmoid 函数,前提是给出了“y”并且需要找到“x”。

拟合 'x' 的 sigmoid 函数定义如下:

## Define sigmoid function to fit xdata
def sigmoid(y, x0, k):
    x = x0 + ((1/k)*(np.log((1/y)-1)))
    return x

## Initial guess
p0 = [np.median(xdata),       # x0
      0.1]                    # k

## Initialize curve fit
popt, pcov = curve_fit(sigmoid,
                       ydata,
                       xdata)


## Define values for y
y = np.arange(1,0,-0.001)

## Evaluate values for x
x = sigmoid(y, *popt)

## Plot tbe actual and fit data
plt.plot(xdata, ydata, 'o', label='data')
plt.plot(x,y, label='fit')
plt.xlim([-10,31])
plt.ylim(0, 1.05)
plt.legend(loc='best')
plt.show()

拟合数据如下所示:

很明显合身不好

有人可以告诉我如何拟合接近实际数据的曲线吗?

python-3.x curve-fitting scipy-optimize data-fitting sigmoid
2个回答
2
投票

难点在于,在要拟合的方程中有 ln((1/y)-1) 对于 y=1 是无限的。不得考虑 y=1 的点。然后装修很好:

对于y趋于1(但小于1)则x趋于-无穷大,这与数据和曲线的形状一致。


1
投票

您可能会发现

lmfit
对此很有用(免责声明:我是主要作者),因为它内置了 S 形步进函数,可以很容易地进行拟合并使用这些结果进行内插或外推。它还提供了比
curve_fit
更有用的结果报告,变量参数具有有意义的名称和不确定性以及正确计算、排序和分配的相关性。

您的示例可能如下所示:

import numpy as np
import matplotlib.pyplot as plt

from lmfit.models import StepModel, ConstantModel

#
xdata = np.array([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26])
ydata = np.array([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.99330715, 0.98201379, 0.95257413, 0.88079708, 0.73105858, 0.5])

# create a logistic step function + an offset constant
model = StepModel(form='logistic') + ConstantModel()

# make a set of parameters with initial values
params = model.make_params(c=1, amplitude=-1, center=25, sigma=2.5)

# fit the data with the parameters and `x` independent variable
result = model.fit(ydata, params, x=xdata)

# print results
print(result.fit_report())

# evaluate the model with best-fit parameters to 
# interpolate and extrapolate to higher x values
xnew = np.linspace(15, 45, 121)
ynew = model.eval(result.params, x=xnew)


## Plot the data, best-fit result, and extrapolated data
plt.plot(xdata, ydata, 'o', label='data')
plt.plot(xdata, result.best_fit, '-', label='best fit')
plt.plot(xnew,  ynew, '+', label='exptrapolated')
plt.xlabel('x')
plt.ylabel('sigmoid(x)')
plt.xlim([-1,41])
plt.ylim(0, 1.05)
plt.legend()
plt.show()

这将打印一份报告

[[Model]]
    (Model(step, form='logistic') + Model(constant))
[[Fit Statistics]]
    # fitting method   = leastsq
    # function evals   = 82
    # data points      = 27
    # variables        = 4
    chi-square         = 6.4177e-06
    reduced chi-square = 2.7903e-07
    Akaike info crit   = -403.811763
    Bayesian info crit = -398.628416
    R-squared          = 0.99997896
[[Variables]]
    amplitude: -0.99669011 +/- 0.01320863 (1.33%) (init = -1)
    center:     25.9928183 +/- 0.02578216 (0.10%) (init = 25)
    sigma:      0.99867632 +/- 0.00629747 (0.63%) (init = 2.5)
    c:          1.00015992 +/- 1.1486e-04 (0.01%) (init = 1)
[[Correlations]] (unreported correlations are < 0.100)
    C(amplitude, center) = -0.997
    C(center, sigma)     = 0.954
    C(amplitude, sigma)  = -0.943
    C(sigma, c)          = 0.287
    C(amplitude, c)      = -0.223

并绘制如下图:

© www.soinside.com 2019 - 2024. All rights reserved.