【问题标题】:Fitting with funtional parameter constraints in Python在 Python 中拟合功能参数约束
【发布时间】:2020-01-11 12:41:18
【问题描述】:

我有一些数据{x_i,y_i},我想拟合一个模型函数y=f(x,a,b,c),以找到参数(a,b,c)的最佳拟合值;然而,它们三个并不是完全独立的,而是受限于1<b0<=c<1g(a,b,c)>0,其中g 是一个“好”函数。我如何在 Python 中实现这一点,因为使用 curve_fit 不能直接放置参数约束?

我一直在阅读 lmfit,但我只看到像 1<b, 0<=c<1 这样的数字约束,而没有看到 g(a,b,c)>0 的约束,这是最重要的。

【问题讨论】:

  • docs.scipy.org/doc/scipy/reference/generated/… 处的 curve_fit() 的 scipy 文档有关于 bounds 参数的讨论和示例。
  • @JamesPhillips curve_fit 不允许像 g(a,b,c)>0; 这样的约束。它们只能像 {a0
  • 可以使用lmfit 中基于表达式的约束机制来处理g(a, b, c) > 0 约束,具体取决于函数g() 的作用。你必须提供一个更具体的例子。
  • 那么f(x,a,b,c)1<b , 0<=c<1 附近看起来像什么?它有多非线性?告诉我们一个线性化的近似。您可能必须对您的区域和约束进行分段建模。
  • f(x,a,b,c) 包含 Gamma 和超几何函数,所以不容易线性化...

标签: python curve-fitting non-linear-regression


【解决方案1】:

如果我理解正确,你有

def g(a,b,c):
    c1 = (1.0 - c)
    cx = 1/c1
    c2 = 2*c1
    g  = a*a*b*gamma(2+cx)*gamma(cx)/gamma(1+3/c2)-b*b/(1+b**c2)**(1/c2)
    return g

如果是这样,并且如果数学正确,则可以表示为

    a = sqrt((g+b*b/(1+b**c2)**(1/c2))*gamma(1+3/c2)/(b*gamma(2+cx)*gamma(cx)))

也就是说,您可以将您的问题视为有一个 变量 g 大于 0 并且 a 的值源自 @987654325 @、cg 通过上述表达式。

可以使用lmfit 及其基于表达式的约束机制来做到这一点。您必须添加 gamma 函数,与

一样
  from lmfit import Parameters
  from scipy.special import gamma

  params = Parameters()
  params._asteval.symtable['gamma'] = gamma

然后设置带有边界和约束的参数。我可能会按照上面的数学来进行更好的调试并使用类似的东西:

  params.add('b', 1.5, min=1)
  params.add('c', 0.4, min=0, max=1)
  params.add('g', 0.2, min=0)
  params.add('c1', expr='1-c')
  params.add('cx', expr='1.0/c1')
  params.add('c2', expr='2*c1')
  params.add('gprod', expr='b*gamma(2+cx)*gamma(cx)/gamma(1+3/c2)')
  params.add('bfact', expr='(1+b**c2)**(1/c2)')
  params.add('a', expr='sqrt(g+b*b/(bfact*gprod))')

请注意,这给出了 3 个实际变量(现在是 gbc)以及从这些变量中计算得出的大量派生值,包括 a。我当然会检查所有的数学。看起来您可以免受 negative**fractional_powersqrt(negitive)gamma(-1) 的影响,但请注意这些可能会扼杀您的健康。

您可以将所有这些嵌入到您的拟合函数中,但是使用约束表达式使您能够独立于拟合或模型函数的定义方式来约束参数值。

希望对您有所帮助。同样,如果这没有达到您想要做的事情,请发布有关您尝试施加的约束的更多详细信息。

【讨论】:

    【解决方案2】:

    和 James Phillips 一样,我打算推荐 SciPy 的 curve_fit。但是,您定义函数的方式,其中一个约束是函数本身,而 SciPy 的边界仅根据输入变量来定义。

    您的函数的具体形式是什么?您能否对它们进行转换,以便您可以使用标准的边界定义,然后反转转换以提供您想要的原始形式的函数?

    我在尝试使用 SciPy 的 curve_fit 拟合指数回归时遇到了一个相关问题。参数搜索算法以线性方式变化,很容易无法建立梯度。如果我编写一个适合我想要的函数的对数的函数,那么让 curve_fit 工作起来会容易得多。然后,对于我的最后一项工作,我采用拟合函数的指数。

    同样的策略也适用于您。预测 ln(y)。该函数的值可以是无限的。然后对于你的最终结果,输出 exp(ln(y)) = y.

    【讨论】:

    • 感谢您的尝试,但如果有一种方法可以减少不等式约束,那么我不会在这里发布任何问题 ;-)。例如,函数 g 的形状涉及 Gamma 函数,例如 g(a,b,c)=a²b $\Gamma[2+1/(1-c)]\Gamma[1/(1-c)] /\Gamma[1+3/(2(1-c))]-b²/(1+b^(2(1-c)))^(1/2(1-c))$....所以没有办法单独设置数值范围。这就是我问这个的原因......在 Wolfram Mathematica 中,很容易以函数的方式表达这个约束,但是,我正在尝试在 Python 中做到这一点......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-18
    • 1970-01-01
    • 2021-11-01
    • 2019-03-19
    • 2015-11-26
    • 2021-08-07
    • 2015-09-29
    相关资源
    最近更新 更多