我有以下数据集:
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()
拟合数据如下所示:
很明显合身不好
有人可以告诉我如何拟合接近实际数据的曲线吗?
您可能会发现
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