用Python拟合数据的总和

3
鉴于拟合函数的类型为: enter image description here 我打算将这样的函数拟合到我手头上的实验数据(x,y=f(x))。但是我有一些疑问:
  • 当涉及求和时,我该如何定义我的拟合函数?

  • 一旦定义了函数,即def func(..) return ...,是否仍然可以使用scipy.optimize中的curve_fit进行拟合?因为现在与通常的拟合案例相比,多了一组参数s_i和r_i。

  • 最后,这种情况是否完全不同处理?

我有点迷失了,在此感谢您的任何帮助。

你是不是也想要 $x_i$,还是只有一个 $x$?如果是后者,那么你的参数无法确定。但如果是前者,你可以使用 scipy.optimize.leastsq - Alan
@Alan 在这种情况下,$x$ 是变量,但是它是离散的。 - user4587874
最糟糕的部分是我甚至不知道如何在Python中定义这样的函数(即作为总和)。 - user4587874
2个回答

3
这很容易使用scipy.optimize.curve_fit(或者只是scipy.optimize.leastsqr)来实现,内容涉及到IT技术。事实上,求和并不重要,也不重要你是否有参数数组。唯一需要注意的是,curve_fit希望将参数作为单独的参数提供给拟合函数,而leastsqr则提供一个单一向量。这里是一个解决方案:
import numpy as np
from scipy.optimize import curve_fit, leastsq

def f(x,r,s):
    """ The fit function, applied to every x_k for the vectors r_i and s_i. """
    x = x[...,np.newaxis]  # add an axis for the summation
    # by virtue of numpy's fantastic broadcasting rules,
    # the following will be evaluated for every combination of k and i.
    x2s2 = (x*s)**2
    return np.sum(r * x2s2 / (1 + x2s2), axis=-1)

# fit using curve_fit
popt,pcov = curve_fit(
    lambda x,*params: f(x,params[:N],params[N:]),
    X,Y,
    np.r_[R0,S0],
)
R = popt[:N]
S = popt[N:]

# fit using leastsq
popt,ier = leastsq(
    lambda params: f(X,params[:N],params[N:]) - Y,
    np.r_[R0,S0],
)
R = popt[:N]
S = popt[N:]

需要注意的几点:

  • 开始时,我们需要适合于测量的1d数组XY,初始猜测为1d数组R0S0N是这两个数组的长度。
  • 我将实际模型f的实现与提供给拟合器的目标函数分开。我使用lambda函数实现了这些目标函数。当然,也可以使用普通的def...函数并将它们组合成一个函数。
  • 模型函数f使用numpy的广播功能同时对一组参数进行求和(沿着最后一个轴),并且在许多x上并行计算(沿着最后一个轴之前的任何轴,尽管如果有多个轴...可以使用.ravel()来帮助解决)
  • 我们使用numpy的简写np.r_[R,S]将拟合参数R和S连接成单个参数向量。
  • curve_fit将每个单独的参数作为独立参数提供给目标函数。我们希望它们作为一个向量,因此我们使用*params:它将所有剩余的参数捕获到单个列表中。
  • leastsq提供单个params向量。但是,它既不提供x,也不将其与y进行比较。它们直接绑定到目标函数中。

1
非常感谢您的回答,对我很有帮助(虽然有点复杂哈哈)。我正在尝试使用curve_fit使其正常工作,但是到目前为止,由于初始猜测不正确,我一直失败并收到“未找到最佳参数:函数调用次数已达到maxfev = 20200。” 我想这只意味着我必须不断尝试不同的猜测。 - user4587874
你确定这是适合你的数据的正确函数吗?那个函数的问题在于对于接近的$s_i$,相应的$r_i$基本上是退化的:你可以自由地从一个$r_i$重新分配到另一个$r_i$而不改变函数。因此,你应该确保所有的$s_i$最终都是不同的,并相应地提供不同的起始值。 - burnpanck
哦,有趣的点,我现在会记住并尝试一下。谢谢。 - user4587874
再次感谢您。您可能也会对我的另一篇帖子感兴趣,在这里,看到您的方法将是很有趣的。最后,如果可以的话,我真的很喜欢您在这里提供的解决方案,并想知道您是否有任何关于这些计算和Python方法的文献或书籍推荐,主要是物理学家经常使用的那些。干杯 - user4587874
不幸的是,我从来没有读过任何书,而是通过实践学习。Numpy用户指南在[http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html]上有一个广播部分,这是一个非常强大的工具。然后,只需要在需要时阅读文档,并尝试注意一些你目前不需要但在另一个环境中有用的功能和技术即可。 - burnpanck

0
为了使用scipy.optimize.leastsq来估计多个参数,您需要将它们打包到一个数组中,并在函数内部解包。然后您可以对它们进行任何操作。例如,如果您的s_i是数组p中的前3个参数,而r_i是接下来的三个参数,您只需设置ssum=p[:3].sum()rsum=p[3:6].sum()。但是,根据您的评论,您的参数没有被识别,因此估计是无意义的。
有关使用leastsq的示例,请参见食谱中的Fitting Data example

我认为你误解了原帖:$f$ 是一个关于 $x$ 的函数,用来拟合数据 $y$,也就是说,他有许多 $x_k$ 要拟合到 $y_k$。只要有比 $2N$ 更多的 $k$,那么这个拟合问题就是良好定义的。 - burnpanck
@burnpanck 我不明白你的意思。考虑一组值r1..rN和s1...sN。现在选择不同的i和j,并通过简单地将si与sj和ri与rj交换来生成一组新的值。就我所看到的,无论x的值如何,f(x)都不会改变,相应地,任何适合度量都不能区分这两个集合。 - Alan
啊哈,我明白了,是我误解了你。当然,你是正确的。在这个公式中,有N!个等价解。从这个意义上讲,优化问题只能针对索引i的排列进行定义。对于像leastsq这样的本地数值求解器来说,这并不是问题,只要在解决方案中没有任何一个si接近另一个sj即可。作为本地数值求解器,它不会知道其他等价解,并且只会给出一个随机解。 - burnpanck

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接