繁体   English   中英

如何在python的scipy.optimize.curve_fit中设置变量参数?

[英]How to set variable arguments in scipy.optimize.curve_fit in Python?

我正在使用scioy.optimize.curve_fit在Python中进行优化问题。 curve_fit函数将输入作为curve_fit(f,xdata,ydata,...),其中可调用的f是模型函数f(x,...)。 它必须将自变量作为第一个参数,并将参数作为单独的剩余参数来容纳。

但是,就我而言,其余参数是可变的。 例如,f可以是f = fun(indepent_var,a,b,c,d)或f = fun(indepent_var,a,c,d)。

f的实际参数由用户在解决优化问题时定义。 例如,一个用户可能想要使用a,b,c,d作为参数,而另一个用户想要使用a,c,d,而第三位用户则可能使用b,c。 然后,我的问题是如何在f设置变量参数,然后用户可以配置自己的参数?

def func(data, a, b, c, d):
    return a * np.exp(-b * data) + c        

#def func(data, a, c, d):
#    return a * np.exp(-c * x)

popt, pcov = curve_fit(func, xdata, ydata)

"config_1.ini"
params_to_be_optimized = a, b, c, d

"config_2.ini"
params_to_be_optimized = a, c, d

我正在尝试做这样的事情:

def func(data, **kwards):
    a = kwargs['a'] if a in kwargs else 0
    ...
    return ...

popt, pcov = curve_fit(lambda(...), xdata, ydata)

但是我不知道该怎么解决这个问题。 我想lambda函数可能起作用,但是有人可以给我一个例子吗?

curve_fit文档中的示例为例:

In [260]: def func(x, a, b, c):
     ...:     return a * np.exp(-b * x) + c
     ...: 
In [261]: xdata = np.linspace(0, 4, 50)
     ...: y = func(xdata, 2.5, 1.3, 0.5)
     ...: np.random.seed(1729)
     ...: y_noise = 0.2 * np.random.normal(size=xdata.size)
     ...: ydata = y + y_noise

如果没有p0参数,则拟合参数的数量是通过内省确定的,即检查func代码和属性

p0 : None, scalar, or N-length sequence, optional

Initial guess for the parameters. If None, then the initial values will all be 1 (if the number of parameters for the function can be determined using introspection, otherwise a ValueError is raised).

在这种情况下,它将标识3个参数:

In [263]: optimize.curve_fit(func, xdata, ydata)
Out[263]: 
(array([ 2.55423706,  1.35190947,  0.47450618]),
 array([[ 0.0158905 ,  0.00681778, -0.0007614 ],
        [ 0.00681778,  0.02019919,  0.00541905],
        [-0.0007614 ,  0.00541905,  0.00282595]]))

我可以使用*args定义一个等效函数:

In [264]: def f1(x, *args):
     ...:     return func(x, *args)
     ...: 

但是,如果我尝试适应它,则会出现错误:

In [266]: optimize.curve_fit(f1, xdata, ydata)
ValueError: Unable to determine number of fit parameters.

但是我可以指定一个p0

In [268]: optimize.curve_fit(f1, xdata, ydata, p0=np.ones(3))
Out[268]: 
(array([ 2.55423706,  1.35190947,  0.47450618]),
 ....)

如果我给出其他p0大小,则在f1将其参数传递给func会出错。 我可以定义f1这样它可以容忍其他args数,但是我可能会得到OptimizeWarning

这可能不是一个完整的答案,但是对于评论来说太长了。 当然,提供一个您想要做的事的更具体的例子肯定会帮助您弄清楚问题并得到更好的答案。

这并不完全清楚,我你的函数的签名是什么,但它可能是基本的问题是如何让用户选择,同时具有其他参数不会成为变量,无论是在剩下的这些函数的参数成为变量拟合一些固定值或被用作实际使用的功能形式的开关(这似乎是您的澄清性评论试图说的)。

无论哪种情况,您都可以找到lmfit( https://lmfit.github.io/lmfit-py/ )有用。 它具有一个Model类,该类支持基于scipy.optimize的曲线拟合,但与curve_fit分开(并在某些程度上高于curve_fit lmfit.Model可以将任何“模型函数”转换为可用于拟合数据的模型,并使用检查将函数参数转换为拟合中使用的参数。 任何参数都可以是可变的或固定的(或具有界限或由简单的约束表达式设置),这可能就是您要寻找的:用户可以确定某些函数参数将不是适合的变量。

同样,如果模型函数具有不带数字默认值的关键字参数,则它们不会成为拟合变量,但可以用作可选开关,也许可以控制使用的函数形式。 也就是说,如果您具有模型功能,例如

def func(x, a=1, b=2, c=3, d=0, option=True):
     if option:
         return a * np.exp(-b*x) + c + d*x
     else:
         return a * np.exp(-b*x**2) + c + d*x

然后,您可以使用以下命令创建拟合模型和参数

from lmfit impor Model
mymodel = Model(func)
params = mymodel.make_params(a=100, b=-1, c=0, d=0)

然后(例如)将d固定为0:

params['d'].value = 0
params['d'].vary = False

或应用其他起始值,界限等。

要更改option参数的值,可以将其视为另一个自变量,将其作为关键字参数传递给mymodel.fit()mymodel.eval() ,如下所示:

xdata = <array of data>
ydata = <array of data>

result = mymodel.fit(ydata, params, x=xdata, option=False)
print(result.fit_report())

这将允许用户选择模型功能中使用的选项。

希望能为您指明正确的方向。

更新问题后:

通常,支持**kws会非常困难:用户可以将任何内容传递给此dict,并且在函数中如何使用它尚不清楚。 例如,拟合变量必须是浮点数。 但是,您可能也认识到

def func(data, **kwargs):
    a = kwargs['a'] if a in kwargs else 0
    ...

可以重述为

def func(data, a=0, **kwargs):
    ...

受支持的。 这意味着您将必须为所有可能是变量的数量显式地创建函数参数,但这并不难。 一旦完成,用户就可以决定其中的哪些实际上以特定的方式变化。

您绝对可以使用类似

def func(x, a=1, b=2, c=3, d=0):
     ...

# read from "config_1.ini"
params_to_be_optimized = 'a', 'b', 'c', 'd'

# read from "config_2.ini"
params_to_be_optimized = 'a', 'c', 'd'

和类似的东西

mymodel = Model(func)
params = mymodel.make_params()   

for parname, param in params.items():
    param.vary = parname in params_to_be_optimized

控制哪些参数将被优化,哪些将被固定。

暂无
暂无

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

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