【问题标题】:Python lmfit custom models: set fixed parameter and assigning prefixPython lmfit 自定义模型:设置固定参数并分配前缀
【发布时间】:2017-04-13 00:32:37
【问题描述】:

我有 2 个关于 lmfit 包中的参数的问题。

1.

有没有办法为自定义模型预设参数值?

例如。

def my_cust(x,A,b):
    return A*x + b

def gaussian(x, amp, cen, wid):
    return (1.2345*amp/(sqrt(2*pi)*wid)) * exp(-(x-cen)**2 /wid)

mod = Model(my_cust) + Model(gaussian)
pars = mod.make_params(A=11.78,b=25,amp=2000,cen=109.5,wid=17) #initialize all the parameters
results = mod.fit(y,pars,x=x)

例如倒数第二行,amp=2000 初始化参数amp。如果我想在内置模型中修复这个参数(例如this one):

params = model.make_params()
params['g1_amplitude'].set(2000, vary=False)

问题 1

是否可以修复参数amp 的值在mod.fit() 行或自定义 模型的其他位置中的2000?

2.

我正在尝试为自定义复合模型分配前缀,如下所示:

cust_combination_mod = Model(my_cust, prefix='lin_') + Model(gaussian, prefix='g1_')

当我尝试上述行时,我得到了:

  File "build\bdist.win-amd64\egg\lmfit\model.py", line 541, in fit
  File "build\bdist.win-amd64\egg\lmfit\model.py", line 747, in fit
  File "build\bdist.win-amd64\egg\lmfit\minimizer.py", line 1242, in minimize
  File "build\bdist.win-amd64\egg\lmfit\minimizer.py", line 1072, in leastsq
  File "C:\Python27\lib\site-packages\scipy\optimize\minpack.py", line 377, in leastsq
    shape, dtype = _check_func('leastsq', 'func', func, x0, args, n)
  File "C:\Python27\lib\site-packages\scipy\optimize\minpack.py", line 26, in _check_func
    res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
  File "build\bdist.win-amd64\egg\lmfit\minimizer.py", line 371, in __residual
  File "build\bdist.win-amd64\egg\lmfit\minimizer.py", line 1432, in _nan_policy
ValueError: The input contains nan values

如果有很多自定义模型,那么初始化mod.make_params() 中的所有参数(就像我在上面的 1. 中展示的那样)可能会很乏味。这个问题似乎在这里讨论(1,2) 但它们并没有真正说明如何为复合模型的单独组件实际分配前缀。

问题 2

是否可以为lmfit 中的复合自定义模型分配前缀?

【问题讨论】:

    标签: python-2.7 curve-fitting lmfit


    【解决方案1】:

    Q1:定义模型时可以为自定义模型设置默认值:

    >>> def my_cust(x, a=1.0, b=2.0):
    ...    return a*x + b
    
    >>> lmodel = Model(my_cust)
    >>> params = lmodel.make_params()
    >>> params 
    Parameters([('a', <Parameter 'a', 1.0, bounds=[-inf:inf]>), ('b', <Parameter 'b', 2.0, bounds=[-inf:inf]>)])
    

    您可以在创建参数后对其进行修复:

    >>> params['a].vary = False
    

    您还可以在模型上设置“参数提示”,以告诉属性在创建参数时分配:

    >>> lmodel.set_param_hint('a', vary=False)
    >>> lmodel.set_param_hint('b', min=0)
    >>> params = lmodel.make_params()
    >>> params
    Parameters([('a', <Parameter 'a', value=1.0 (fixed), bounds=[-inf:inf]>), ('b', <Parameter 'b', 2.0, bounds=[0:inf]>)])
    

    Q2:做

    >>> comp_model = Model(my_cust, prefix='lin_') + Model(gaussian, prefix='g1_')
    

    应该有效(而且,它对我有用)。为此生成的参数将具有正确的前缀,并且应该在Model.make_params:

    中引用 with prefix
    >>> params = comp_model.make_params(g1_amp=9, g1_cen=2.0, g1_wid=0.5)
    >>> for name, par in params.items():
    ...    print(name, par)
    ...
    ('lin_a', <Parameter 'lin_a', 1.0, bounds=[-inf:inf]>)
    ('lin_b', <Parameter 'lin_b', 2.0, bounds=[-inf:inf]>)
    ('g1_amp', <Parameter 'g1_amp', 9, bounds=[-inf:inf]>)
    ('g1_cen', <Parameter 'g1_cen', 2.0, bounds=[-inf:inf]>)
    ('g1_wid', <Parameter 'g1_wid', 0.5, bounds=[-inf:inf]>)
    

    如果你想保留上面设置的参数提示,你应该制作带有前缀的自定义模型,设置参数提示,然后制作自定义模型:

    >>> lmodel = Model(my_cust, prefix='lin_')
    >>> lmodel.set_param_hint('a', vary=False)
    >>> lmodel.set_param_hint('b', min=0)
    >>> comp = lmodel + Model(gauss, prefix='g1_')
    >>> params = comp.make_params(g1_amp=9.0, g1_cen=2.0, g1_wid=0.5)
    >>> for name, par in params.items(): 
    ...    print(name, par)
    ... 
    ('lin_a', <Parameter 'lin_a', value=1.0 (fixed), bounds=[-inf:inf]>)
    ('lin_b', <Parameter 'lin_b', 2.0, bounds=[0:inf]>)
    ('g1_amp', <Parameter 'g1_amp', 9.0, bounds=[-inf:inf]>)
    ('g1_cen', <Parameter 'g1_cen', 2.0, bounds=[-inf:inf]>)
    ('g1_wid', <Parameter 'g1_wid', 0.5, bounds=[-inf:inf]>)
    

    我不确定 NaN 的异常是从哪里来的。可能是因为没有给出参数的初始值(这可能会导致默认为 -inf),或者是因为正在建模的数据中有 NaN?

    【讨论】:

    • 第一次尝试时,我使用了mod = Model(my_cust) + Model(gaussian),然后包含了pars = mod.make_params(A=11.78,b=25,amp=2000,cen=109.5,wid=17)。第二行是问题并导致了 NaN 异常 - 正如您所指出的,我需要通过前缀引用它们。前缀有效。我的两个问题都得到了解答。谢谢!!!
    • 对不起,在我的评论中,第一句话应该是:“...我使用了mod = Model(my_cust, prefix='lin_') + Model(gaussian, prefix='g_') 然后...”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-19
    • 2022-01-15
    • 1970-01-01
    • 2017-06-28
    • 1970-01-01
    • 2021-07-19
    • 2016-12-17
    相关资源
    最近更新 更多