在 python 中,我有一个有很多参数的函数。我想将此函数拟合到数据集,但只使用一个参数,其余参数我想自己提供。这是一个例子:
def func(x,a,b):
return a*x*x + b
for b in xrange(10):
popt,pcov = curve_fit(func,x1,x2)
在此,我希望仅进行拟合,a
并且参数b
采用循环变量的值。如何才能做到这一点?
在 python 中,我有一个有很多参数的函数。我想将此函数拟合到数据集,但只使用一个参数,其余参数我想自己提供。这是一个例子:
def func(x,a,b):
return a*x*x + b
for b in xrange(10):
popt,pcov = curve_fit(func,x1,x2)
在此,我希望仅进行拟合,a
并且参数b
采用循环变量的值。如何才能做到这一点?
您可以包装func
在 lambda 中,如下所示:
def func(x,a,b):
return a*x*x + b
for b in xrange(10):
popt,pcov = curve_fit(lambda x, a: func(x, a, b), x1, x2)
lambda 是一个匿名函数,在 Python 中只能用于简单的单行函数。基本上,它通常用于在不需要为函数分配名称时减少代码量。官方文档中给出了更详细的描述:http: //docs.python.org/tutorial/controlflow.html#lambda-forms
在这种情况下,lambda 用于修复 的参数之一func
。新创建的函数只接受两个参数:x
和a
,而 , 而b
固定为取自局部b
变量的值。curve_fit
然后将这个新函数作为参数传入。
更好的方法是使用lmfit
,它为曲线拟合提供了更高级别的接口。在其他功能中,Lmfit 使拟合参数成为可以具有边界或明确固定(在其他功能中)的一流对象。
使用 lmfit,这个问题可能会被解决为:
from lmfit import Model
def func(x,a,b):
return a*x*x + b
# create model
fmodel = Model(func)
# create parameters -- these are named from the function arguments --
# giving initial values
params = fmodel.make_params(a=1, b=0)
# fix b:
params['b'].vary = False
# fit parameters to data with various *static* values of b:
for b in range(10):
params['b'].value = b
result = fmodel.fit(ydata, params, x=x)
print(": b=%f, a=%f+/-%f, chi-square=%f" % (b, result.params['a'].value,
result.params['a'].stderr,
result.chisqr))
我建议不要使用可能不太直观的 lambda 函数来指定 scikit curve_fit参数bounds
,该参数将强制在自定义边界内搜索您的参数。
您所要做的就是让您的变量a在 -inf 和 +inf 之间移动,并且让您的变量b在 ( b - epsilon) 和 ( b + epsilon)之间移动
在您的示例中:
epsilon = 0.00001
def func(x,a,b):
return a*x*x + b
for b in xrange(10):
popt,pcov = curve_fit(func,x1,x2, bounds=((-np.inf,b-epsilon), (np.inf,b+epsilon))
我有效地使用了 Anton Beloglazov 的解决方案,虽然我喜欢避免使用 lambda 函数来提高可读性,所以我执行以下操作:
def func(x,a,b):
return a*x*x + b
def helper(x,a):
return func(x,a,b)
for b in xrange(10):
popt,pcov = curve_fit(helper, x1, x2)
这最终让人想起 Rick Berg 的回答,但我喜欢有一个专用于问题的“物理”的函数和一个帮助函数来让代码工作。
另一种方法是使用相同的上限和下限 (+ eps) 作为初始值。使用具有初始条件和边界的相同示例:
def func(x,a,b):
return a*x*x + b
# free for a and b
popt,pcov = curve_fit(func, x1, x2,
p0=[1,1],
bounds=[(-inf,-inf),(inf,inf)])
# free for a; fixed for b ;
eps=1/100
popt,pcov = curve_fit(func, x1, x2,
p0=[1,1],
bounds=[(-inf,(1-eps)),(inf,(1+eps))])
记得插入一个epsilon,否则a和b必须相同
如果您愿意/能够编辑原始函数,则有一个更简单的选项。
将您的功能重新定义为:
def func(x,a):
return a*x*x + b
然后,您可以简单地将其放入参数 b 的循环中:
for b in xrange(10):
popt,pcov = curve_fit(func, x1, x2)
警告:该函数需要在调用它的同一脚本中定义才能使其工作。
Scipy 的 curve_fit 采用三个位置参数,func、xdata 和 ydata。因此,另一种方法(使用函数包装器)是通过构建一个包含原始 xdata (x1) 和固定参数 b 的第二列的矩阵,将“b”视为 xdata(即自变量)。
假设 x1 和 x2 是数组:
def func(xdata,a):
x, b = xdata[:,0], xdata[:,1] # Extract your x and b
return a*x*x + b
for b in xrange(10):
xdata = np.zeros((len(x1),2)) # initialize a matrix
xdata[:,0] = x1 # your original x-data
xdata[:,1] = b # your fixed parameter
popt,pcov = curve_fit(func,xdata,x2) # x2 is your y-data