使用 scipy.optimize 拟合多个高斯函数的最 Pythonic 方法

发布于 2025-01-09 05:53:43 字数 857 浏览 2 评论 0原文

from scipy.optimize import curve_fit

def func(x, a, b):
    return a * np.exp(-b * x)

xdata = np.linspace(0, 4, 50)
ydata = np.linspace(0, 4, 50)
popt, pcov = curve_fit(func, xdata, ydata)

使用类似于上述方法的方法在 python 中拟合任意高斯分布是非常容易的。但是,我想准备一个函数,让用户始终选择任意数量的高斯,并仍然尝试找到最合适的。

我试图弄清楚如何修改函数 func ,以便我可以向它传递一个附加参数 n=2 例如,它会返回一个会尝试的函数并拟合 2 个高斯函数,类似于:

from scipy.optimize import curve_fit

def func2(x, a, b, d, e):
    return (a * np.exp(-b * x) + c * np.exp(-d * x))  

xdata = np.linspace(0, 4, 50)
ydata = np.linspace(0, 4, 50)
popt, pcov = curve_fit(func2, xdata, ydata)

无需对这些额外的情况进行硬编码,这样我们就可以传递一个函数,例如 func(...,n=2) 并获得与以下相同的结果多于。我很难找到一个优雅的解决方案来解决这个问题。我的猜测是,最好的解决方案是使用 lambda 函数。

from scipy.optimize import curve_fit

def func(x, a, b):
    return a * np.exp(-b * x)

xdata = np.linspace(0, 4, 50)
ydata = np.linspace(0, 4, 50)
popt, pcov = curve_fit(func, xdata, ydata)

It is quite easy to fit an arbitrary Gaussian in python with something like the above method. However, I would like to prepare a function that always the user to select an arbitrary number of Gaussians and still attempt to find a best fit.

I'm trying to figure out how to modify the function func so that I can pass it an additional parameter n=2 for instance and it would return a function that would try and fit 2 Gaussians, akin to:

from scipy.optimize import curve_fit

def func2(x, a, b, d, e):
    return (a * np.exp(-b * x) + c * np.exp(-d * x))  

xdata = np.linspace(0, 4, 50)
ydata = np.linspace(0, 4, 50)
popt, pcov = curve_fit(func2, xdata, ydata)

Without having to hard code this additional cases, so that we could instead pass a single function like func(...,n=2) and get the same result as above. I'm having trouble finding an elegant solution to this. My guess is that the best solution will be something using a lambda function.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

笨笨の傻瓜 2025-01-16 05:53:43

您可以使用 def func(x, *args) 定义函数以接受可变数量的参数。然后,*args 变量包含类似 (a1, b1, a2, b2, a3, ...) 的内容。可以循环这些并对高斯求和,但我显示的是矢量化解决方案。

由于 curve_fit 无法再确定此函数的参数数量,因此您可以提供初始猜测来确定要拟合的高斯数量。每个高斯函数需要两个参数,因此 [1, 1]*n 会生成正确长度的参数向量。

from scipy.optimize import curve_fit
import numpy as np

def func(x, *args):
    x = x.reshape(-1, 1)
    a = np.array(args[0::2]).reshape(1, -1)
    b = np.array(args[1::2]).reshape(1, -1)
    return np.sum(a * np.exp(-b * x), axis=1)

n = 3

xdata = np.linspace(0, 4, 50)
ydata = np.linspace(0, 4, 50)
popt, pcov = curve_fit(func, xdata, ydata, p0=[1, 1] * n)

You can define the function to take a variable number of arguments using def func(x, *args). The *args variable then contains something like (a1, b1, a2, b2, a3, ...). It would be possible to loop over those and sum the Gaussians but I'm showing a vectorized solution instead.

Since curve_fit can no longer determine the number of parameters from this function, you can provide an initial guess that determines the amount of Gaussians you want to fit. Each Gaussian requires two parameters, so [1, 1]*n produces a parameter vector of the correct length.

from scipy.optimize import curve_fit
import numpy as np

def func(x, *args):
    x = x.reshape(-1, 1)
    a = np.array(args[0::2]).reshape(1, -1)
    b = np.array(args[1::2]).reshape(1, -1)
    return np.sum(a * np.exp(-b * x), axis=1)

n = 3

xdata = np.linspace(0, 4, 50)
ydata = np.linspace(0, 4, 50)
popt, pcov = curve_fit(func, xdata, ydata, p0=[1, 1] * n)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文