分段函数

时间:2019-02-03 20:34:55

标签: python non-linear-regression lmfit

我正在尝试定义分段函数以供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的工作方式似乎也有所不同,因为我们必须始终使残差返回(模型-y),而一旦给出函数,nlinfit就会输出结果,我不确定这可能是另一个问题。

因此,我要重申的主要问题是,是否存在一种定义分段函数的方法,以便可以将参数与数据集进行比较。

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

1 个答案:

答案 0 :(得分:0)

您要使用(param2 < x)来代替param2(其中x是浮点数,而numpy.where是一个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会得到相同的结果。在这种情况下,拟合将无法更改two的值:它将尝试很小的更改,结果看不到更改并放弃。

因此,请确保在实模型的其他地方也使用了two(假设实模型比给定的示例更复杂),或者考虑使用更平缓的过渡而不是硬性地改变。我发现x点之间的宽度〜间距的误差函数经常起作用。根据问题的性质,您可以尝试以下操作:

 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

希望有帮助。