将总和拟合到 Python 中的数据
Fitting a sum to data in Python
鉴于拟合函数的类型:
我打算将这样的函数拟合到我拥有的实验数据 (x,y=f(x)) 中。但是后来我有些疑惑:
涉及求和时如何定义拟合函数?
定义函数后,即 def func(..) return ...
是否仍然可以使用 scipy.optimize 中的 curve_fit?因为现在有一组参数 s_i 和 r_i 涉及,而通常的拟合情况只有很少的单个参数。
这种情况终于完全区别对待了吗?
感觉有点迷茫,感谢大家的帮助。
为了使用scipy.optimize.leastsq
估计多个参数,您需要将它们打包到一个数组中并在您的函数中解包。然后你可以用它们做任何你想做的事。例如,如果您的 s_i 是数组 p
中的前 3 个,而您的 r_i 是接下来的三个参数,您只需设置 ssum=p[:3].sum()
和 rsum=p[3:6].sum()
.但是同样,你的参数没有被识别(根据你的评论),所以估计是没有意义的。
有关使用 leastsq
的示例,请参阅 Cookbook 的 Fitting Data example。
这在 scipy.optimize.curve_fit
(或只是 scipy.optimize.leastsqr
)的范围内非常好。涉及总和的事实根本不重要,也不重要的是你有参数数组。唯一需要注意的是,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:]
注意几点:
- 开始时,我们需要一维数组
X
和 Y
的测量值,一维数组 R0
和 S0
作为初始猜测和 N
这两个数组的长度。
- 我将实际模型
f
的实现与提供给安装人员的 objective 函数分开。我使用 lambda 函数实现的那些。当然也可以把普通的def ...
功能合二为一
- 模型函数
f
使用numpy的广播同时对一组参数求和(沿着最后一个轴),并并行计算许多x
(沿着最后一个之前的任何轴,尽管如果有多个 fit 函数都会抱怨... .ravel()
帮助那里)
- 我们使用 numpy 的 shorthand
np.r_[R,S]
. 将拟合参数 R 和 S 连接成一个参数向量
curve_fit
将每个参数作为不同的参数提供给 objective 函数。我们希望它们作为向量,所以我们使用 *params
:它将所有剩余参数捕获在一个列表中。
leastsq
给出单个参数向量。但是,它既不提供 x
,也不与 y
进行比较。这些直接绑定到 objective 函数中。
鉴于拟合函数的类型:
我打算将这样的函数拟合到我拥有的实验数据 (x,y=f(x)) 中。但是后来我有些疑惑:
涉及求和时如何定义拟合函数?
定义函数后,即
def func(..) return ...
是否仍然可以使用 scipy.optimize 中的 curve_fit?因为现在有一组参数 s_i 和 r_i 涉及,而通常的拟合情况只有很少的单个参数。这种情况终于完全区别对待了吗?
感觉有点迷茫,感谢大家的帮助。
为了使用scipy.optimize.leastsq
估计多个参数,您需要将它们打包到一个数组中并在您的函数中解包。然后你可以用它们做任何你想做的事。例如,如果您的 s_i 是数组 p
中的前 3 个,而您的 r_i 是接下来的三个参数,您只需设置 ssum=p[:3].sum()
和 rsum=p[3:6].sum()
.但是同样,你的参数没有被识别(根据你的评论),所以估计是没有意义的。
有关使用 leastsq
的示例,请参阅 Cookbook 的 Fitting Data example。
这在 scipy.optimize.curve_fit
(或只是 scipy.optimize.leastsqr
)的范围内非常好。涉及总和的事实根本不重要,也不重要的是你有参数数组。唯一需要注意的是,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:]
注意几点:
- 开始时,我们需要一维数组
X
和Y
的测量值,一维数组R0
和S0
作为初始猜测和N
这两个数组的长度。 - 我将实际模型
f
的实现与提供给安装人员的 objective 函数分开。我使用 lambda 函数实现的那些。当然也可以把普通的def ...
功能合二为一 - 模型函数
f
使用numpy的广播同时对一组参数求和(沿着最后一个轴),并并行计算许多x
(沿着最后一个之前的任何轴,尽管如果有多个 fit 函数都会抱怨....ravel()
帮助那里) - 我们使用 numpy 的 shorthand
np.r_[R,S]
. 将拟合参数 R 和 S 连接成一个参数向量
curve_fit
将每个参数作为不同的参数提供给 objective 函数。我们希望它们作为向量,所以我们使用*params
:它将所有剩余参数捕获在一个列表中。leastsq
给出单个参数向量。但是,它既不提供x
,也不与y
进行比较。这些直接绑定到 objective 函数中。