【问题标题】:Piecewise Function lmfit分段函数 lmfit
【发布时间】:2019-02-03 20:34:55
【问题描述】:

我正在尝试定义一个分段函数以供 Python 中的 lmfit 库拟合。我遇到的问题是我为函数定义的参数不会与我提交的数据一起评估。

我有一个与我的here 有点相似的案例示例。但是,答案描述的 vectorize 函数没有产生我想要的值,并且在阅读文档时,它似乎不是我的解决方案的答案。我也使用了 scipy.optimize.leastsq,但我遇到了与下面描述的 lmfit 相同的问题。

我定义了一个残差函数,例如

from lmfit import minimize, Parameters, Model

def residual(params, y, x):
    param1 = params['one']
    param2 = params['two']
    if(param2 < x):
        p = 1
    else:
        p = param1*x + param2
    return p - y 

params = Parameters()
params.add('one', value=1)
params.add('two', value=2)
out = minimize(residual, params,args=(y,x))

我也试过这样定义函数

  def f(param1,param2,x):
    if(param2 < x):
        p = 1
    else:
        p = param1*x + param2
    return p

  def residual(params, y, x):
    param1 = params['one']
    param2 = params['two']
    return f(param1,param2,x) - y

我也尝试过使用 lambda 函数进行内联。

我收到错误消息“包含多个元素的数组的真值不明确。”当我得到错误时,它发生的原因是有道理的,因为 (param2

与 nlinfit 相比,lmfit 的操作似乎也有点不同,因为我们必须始终让残差返回 (model - y),而 nlinfit 一旦给出函数就会输出结果,我不确定这可能是另一个问题。

所以重申一下,我的主要问题是是否有定义分段函数的方法,以便它可以将参数与数据集进行比较。

任何帮助或解释将不胜感激,谢谢!

【问题讨论】:

    标签: python non-linear-regression lmfit


    【解决方案1】:

    您想使用numpy.where 代替(param2 &lt; x)(其中param2 是一个浮点数,x 是一个numpy 数组)。你可以试试:

    def residual(params, y, x):
        param1 = params['one']
        param2 = params['two']
        p = param1 * x + param2
        p[np.where(param2 < x)] = 1.0 
        return p - y
    

    我还应该警告您,这种将变量作为分段函数边界的方法存在潜在问题。

    在非线性拟合中,变量始终是浮点(连续、非离散)值。随着拟合的进行,它将对值进行小幅调整,并查看该小幅变化如何改变结果。在您的方法中,参数“two”既用作片段之间的过渡,也用作线条的偏移量——这很好。

    如果一个参数用作过渡,它可能不起作用。例如,考虑x=np.array([0, 1., 2., 3., 4., ..., 20.0])。拥有two = 10.5two=10.4 会得到相同的结果。在这种情况下,fit 将无法更改 two 的值:它会尝试一个非常小的更改,但看到结果没有任何变化并放弃。

    所以,要么确保two 也在你的真实模型中的其他地方使用(假设你的真实模型比给出的例子更复杂),或者考虑使用更温和的过渡而不是硬性的改变。我发现 x 点之间的宽度 ~spacing 的误差函数通常有效。根据您的问题的性质,您可以尝试以下方法:

     from scipy.special import erf, erfc
     def residual(params, y, x):
        param1 = params['one']
        param2 = params['two']
        dx = (max(x) - min(x))/(len(x)-1)
        xhi = (erf((x-param2)/dx) + 1)/2.0
        xlo = (erfc((x-param2)/dx) + 1)/2.0
        p = xlo*1.0 + xhi*(param1*x + param2)
        # note: did you really want?
        # p = xlo*param + xhi*(param1*x + param2)
        # p = param2 + xhi*param1*x
        return p - y
    

    希望对您有所帮助。

    【讨论】:

    • 谢谢你,现在我没有得到我描述的错误。我想看看我是否可以直观地了解为什么会这样。我的印象是 lmfit.minimize() 函数会遍历给定的 x,y 数组,因此当我输入 (param2
    • 不确定我是否理解 cmets 中的后续问题。 Numpy 数组作为一个整体被精确地处理以避免循环。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-01
    • 2023-04-09
    • 2018-03-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多