Python中函数参数约束的拟合

Python中函数参数约束的拟合,python,curve-fitting,non-linear-regression,Python,Curve Fitting,Non Linear Regression,我有一些数据{x_I,y_I},我想拟合一个模型函数y=f(x,a,b,c),以找到参数的最佳拟合值(a,b,c);然而,这三者并不是完全独立的,而是对1的约束,就像James Phillips一样,我想推荐SciPy的曲线拟合。但是您定义函数的方式,其中一个约束是函数本身,SciPy的边界仅根据输入变量定义 你的函数的具体形式是什么?你能不能转换它们,这样你就可以使用一个标准的边界定义,然后反向转换,以你想要的原始形式给出一个函数 我在尝试使用SciPy的曲线拟合拟合指数回归时遇到了一个相关问

我有一些数据
{x_I,y_I}
,我想拟合一个模型函数
y=f(x,a,b,c)
,以找到参数的最佳拟合值
(a,b,c)
;然而,这三者并不是完全独立的,而是对
1的约束,就像James Phillips一样,我想推荐SciPy的
曲线拟合。但是您定义函数的方式,其中一个约束是函数本身,SciPy的边界仅根据输入变量定义

你的函数的具体形式是什么?你能不能转换它们,这样你就可以使用一个标准的边界定义,然后反向转换,以你想要的原始形式给出一个函数

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


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

如果我理解正确,您已经

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
的值,该值由
b
c
g
通过上述表达式导出

这可以通过
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个实际变量(现在是
g
b
、和
c
),以及从这些变量计算出的大量派生值,包括
a
。我当然会检查所有的数学。看起来您不会受到
负**分数幂
sqrt(负)
、和
gamma(-1)
,但请注意这些可能会破坏配合的可能性

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


希望有帮助。同样,如果这还没有达到您尝试执行的目的,请发布更多关于您试图施加的约束的详细信息。

上的scipy docs for curve_fit()有bounds参数的讨论和示例。@JamesPhillips curve_fit不允许像g(a,b,c)>0这样的约束;它们只能像{a0。可能可以使用
lmfit
中基于表达式的约束机制来处理
g(a,b,c)>0
约束,这取决于函数
g()
的功能。您必须提供一个更具体的示例。那么
f(x,a,b,c)是什么呢
看起来像是在
1f(x、a、b、c)附近包含伽马函数和超几何函数,因此不容易线性化…感谢您的尝试,但是如果有一种方法可以将约束条件简化为不等式,那么我不会在这里发布任何问题;-)。例如,函数g的形状涉及伽马函数,类似于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来实现它。。。