我正在尝试使用scipy.optimize.curve_fit来拟合我所拥有的一些数据。 我的契合函数是:
def fitfun(x, a):
return np.exp(a*(x - b))
我想要的是将a
定义为拟合参数,将b
定义为根据我想要拟合的数据而变化的参数。这意味着对于一组数据,我希望拟合函数:np.exp(a*(x - 10))
而对于另一组我想要拟合函数np.exp(a*(x - 20))
。原则上,我希望参数b作为任何值传入。
我目前正在调用curve_fit的方式是:
coeffs, coeffs_cov = curve_fit(fitfun, xdata, ydata)
但我想要的是这样的:
b=10
coeffs, coeffs_cov = curve_fit(fitfun(b), xdata, ydata)
b=20
coeffs2, coeffs_cov2 = curve_fit(fitfun(b), xdata, ydata)
因此,我得到两个案例的系数a(b = 10和b = 20)。
我是python的新手所以即使我尝试阅读文档,也无法使其工作。任何帮助将不胜感激。
答案 0 :(得分:3)
我还建议lmfit(http://lmfit.github.io/lmfit-py/)及其针对此类问题的Model类。 Lmfit为曲线拟合和优化问题提供了更高级别的抽象。
使用lmfit,模型中的每个参数都成为一个可以固定,自由变化或给定上下界而不改变拟合函数的对象。此外,您可以定义多个"独立变量"对于任何型号。
这给你两种可能的方法。首先,定义参数并修复b
:
from lmfit import Model
def fitfun(x, a, b):
return np.exp(a*(x - b))
# turn this model function into a Model:
mymodel = Model(fitfun)
# create parameters with initial values. Note that parameters are
# **named** according to the arguments of your model function:
params = mymodel.make_params(a=1, b=10)
# tell the 'b' parameter to not vary during the fit
params['b'].vary = False
# do fit
result = mymodel.fit(ydata, params, x=xdata)
print(result.fit_report())
params
在拟合中没有改变(更新的参数在result.params
中),所以为了适应另一组数据,您可以这样做:
params['b'].value = 20 # Note that vary is still False
result2 = mymodel.fit(ydata2, params, x=xdata2)
另一种方法是将b
定义为一个独立变量:
mymodel = Model(fitfun, independent_vars=['x', 'b'])
params = mymodel.make_params(a=1)
result = model.fit(ydata, params, x=xdata, b=10)
Lmfit还有许多其他很好的曲线拟合功能,包括组合复杂模型和评估置信区间。
答案 1 :(得分:2)
我不知道这是否是“正确的”做事方式,但我通常将我的函数包装在一个类中,以便我可以从self
访问参数。您的示例将如下所示:
class fitClass:
def __init__(self):
pass
def fitfun(self, x, a):
return np.exp(a*(x - self.b))
inst = fitClass()
inst.b = 10
coeffs, coeffs_cov = curve_fit(inst.fitfun, xdata, ydata)
inst.b = 20
coeffs, coeffs_cov = curve_fit(inst.fitfun, xdata, ydata)
这种方法避免使用全局参数,generally considered evil。
答案 2 :(得分:2)
您可以在fit函数中将b
定义为全局变量。
from scipy.optimize import curve_fit
def fitfun(x, a):
global b
return np.exp(a*(x - b))
xdata = np.arange(10)
#first sample data set
ydata = np.exp(2 * (xdata - 10))
b = 10
coeffs, coeffs_cov = curve_fit(fitfun, xdata, ydata)
print(coeffs)
#second sample data set
ydata = np.exp(5 * (xdata - 20))
b = 20
coeffs, coeffs_cov = curve_fit(fitfun, xdata, ydata)
print(coeffs)
输出:
[2.]
[5.]
答案 3 :(得分:1)
更新:
抱歉发布未经测试的代码。正如@ mr-t所指出的,代码确实会引发错误。看来,curve_fit函数的kwargs参数是设置var a = 99.99;
var b = 99.9999;
var precision = 100;
console.log(a, Math.round(a), Math.round(a * precision) / precision);
console.log(b, Math.round(b), Math.round(b * precision) / precision);
和leastsq
函数的关键字参数,而不是fit函数本身的关键字参数。
在这种情况下,除了其他人提出的答案之外,另一种可能的解决方案是重新定义fit函数以返回错误并直接调用允许传递参数的least_squares
函数。
leastsq
答案 4 :(得分:0)
一种非常简单的方法是使用 functools 中的 partial
函数。在这种情况下,您只需执行以下操作。在这种情况下,b
必须定义,否则我相信 scipy.optimize.curvefit
除了 a
from functools import partial
def fitfun(x, a, b):
return np.exp(a*(x - b))
fitfun10 = partial(fitfun, b=10)
coeffs, coeffs_cov = curve_fit(fitfun10, xdata, ydata)
fitfun20 = partial(fitfun, b=20)
coeffs2, coeffs_cov2 = curve_fit(fitfun20, xdata, ydata)