【问题标题】:How to do a fit with a Split Pearson 7 function in Python?如何在 Python 中使用 Split Pearson 7 函数?
【发布时间】:2020-08-27 05:33:56
【问题描述】:

我有一个不对称峰,我想使用带有 lmfit 的拆分 Pearson 7 (SP7) 函数来拟合它。 首先定义了SP7函数,然后我用lmfit重新调用了它,但最后出现了这个错误:ValueError: varargs '*p' is not supported。为什么?

def polynomial(x, *p):
    poly = Polynomial(p)
    y = poly(x)
    return y

def pearson7(x, *p):
    x0, IM, H, m = p
    y = IM / (1+4*(2**(1/m)-1)*(x-x0)**2/H**2)**m
    return y

def splitpearson7(x, *p):
    x0, IM, Hl, ml, Hr, mr = p
    pl = [x0, IM, Hl, ml]
    pr = [x0, IM, Hr, mr]
    y = pearson7(x, *pl)*np.heaviside(x-x0, 0.5) + pearson7(x, *pr)*np.heaviside(x0-x, 0.5)
    return y

def splitpearson7_backg(x, *p):
    """
    Split PearsonVII distribution with linear background (8 parameters)
    * background y = A + Bx
    """
    y = splitpearson7(x, *p[0:6]) + polynomial(x, *p[6:8])
    return y ```

first_params_fit=[0, np.max(y), 0.05, 0.5, 0.05, 0.5, 10, 0.3]
mod = Model(splitpearson7_backg)
pars = mod.make_params(first_params_fit)
result = mod.fit(y, pars, x=x)
print(result.fit_report()) ```

【问题讨论】:

    标签: python model-fitting lmfit


    【解决方案1】:
    ValueError: varargs '*p' is not supported.
    

    确实。

    Why?

    好吧,部分原因是定义函数的方式很糟糕,部分原因是它打破了lmfit.Model 的概念,能够确定和名称参数为您的模型功能。简而言之:可读性很重要。帮阅读您代码的人(包括您未来的自己)编写可读代码。

    使用您的splitpearson7,函数参数的含义和顺序将丢失。当然,顺序仍然很关键,但没有以任何方式描述。它甚至没有说有多少参数。相反,如果您使用了

    def splitpearson7(x, x0, IM, Hl, ml, Hr, mr):
        pl = [x0, IM, Hl, ml]
        pr = [x0, IM, Hr, mr]
        y = pearson7(x, *pl)*np.heaviside(x-x0, 0.5) + pearson7(x, *pr)*np.heaviside(x0-x, 0.5)
        return y
    

    那么你可以用

    创建一个lmfit.Model
     sp7_model = lmfit.Model(splitpearson7)
    

    并有命名参数:

     params = sp7_model.make_params(x0=0, IM=1, Hl=2, ml=3.3, Hr=2.1, mr=5)
    

    确实,您的pearson7 函数也可以使用命名参数。或者,您可以使用lmfit 的内置版本:

    from lmfit.lineshapes import pearson7
    def splitpearson7(x, center, amplitude, sigma_left, m_left, sigma_right, m_right):
          left = heaviside(x-center, 0.5)*pearson7(x, amplitude, center, sigma_left, m_left) 
          right = heaviside(center-x, 0.5)*pearson7(x, amplitude, center, sigma_right, m_right) 
          return left+right
    

    另外,一般是“lmfit Model方式”,不建一个有背景的添加功能的模型,而是做一个复合的模型,跟这样

    from numpy import heaviside
    from lmfit.lineshapes import pearson7
    from lmfit.model import Model
    from lmfit.models import PolynomialModel
    
    def splitpearson7(x, center, amplitude, sigma_left, m_left, sigma_right, m_right):
        left = heaviside(x-center, 0.5)*pearson7(x, amplitude, center, sigma_left, m_left) 
        right = heaviside(center-x, 0.5)*pearson7(x, amplitude, center, sigma_right, m_right) 
        return left+right
    
    # Note that PolynomialModel(2) will be quadratic with parameters 
    # c0, c1, c2, and a form = c0 + c1*x + c2*x*x
    mod = Model(splitpearson7) + PolynomialModel(2)
    params = mod.make_params(center=0, amplitude=200, 
                             sigma_left=2, m_left=1, 
                             sigma_right=2.2, m_right=1.1, 
                             c0=10, c1=0, c2=0)
    

    这将使更改背景模型变得更加容易。

    【讨论】:

    • 我按照您的建议编写了代码,但收到了这条消息:ValueError: The model function generated NaN values and the fit aborted! Please check your model function and/or set boundaries on parameters where applicable. In cases like this, using "nan_policy='omit'" will probably not work.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-06
    • 1970-01-01
    • 2017-04-18
    • 2015-08-25
    相关资源
    最近更新 更多