繁体   English   中英

在python中只拟合具有多个参数的函数的一个参数

[英]Fitting only one parameter of a function with many parameters in python

在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的参数之一。 新创建的函数只接受两个参数: xa ,而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 的答案,但我喜欢有一个专门用于问题“物理”的函数和一个使代码工作的辅助函数。

如果您愿意/能够编辑原始函数,还有一个更简单的选择。

将您的功能重新定义为:

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

另一种方法是使用相同的上限和下限 (+ 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必须相同

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM