Python - curve_fit似乎无法拟合高斯函数之和

3

在这里,我定义了一个函数来返回任意数量的高斯分布之和:

import numpy
from numpy import *
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

def GaussSum(x,*p):
    n=len(p)/3
    A=p[:n]
    w=p[n:2*n]
    c=p[2*n:3*n]
    return sum([ A[i]*exp(-(x-c[i])**2./(2.*(w[i])**2.))/(2*pi*w[i]**2)**0.5 for i in range(n)])

我随后根据给定的参数生成x和y数据,并要求curve_fit使用与生成集匹配的初始参数拟合此数据。我尝试了许多不同的集合,包括单个和多个高斯分布。

params = [1.,1.,-3.]; #parameters for a single gaussian
#params=[1.,1.,1.,2.,-3.,0.]; #parameters for the sum of two gaussians
xdata=arange(-6,6,0.01)
ydata = array([GaussSum(x,*params) for x in xdata])

popt,pcov = curve_fit(GaussSum,xdata,ydata,p0=params)

print popt
print pcov

每个参数设置都会给我一个不符合的结果,尽管我已经在解决方案处开始了拟合。(在上述单高斯函数中):

[    52.18242366   5549.66965192  15678.51803797]
inf

我知道该函数本身的运作正常,因为我已经使用它进行了绘图并验证了其有效性。

1个回答

4
这里的问题在于curve_fit函数期望优化的函数接收一个输入向量并返回一个输出向量。而GaussSum函数的写法只接受单个输入或一组输入(即numpy.array),但是无论哪种方式,它都只返回一个标量输出。因此,curve_fit函数无法找到良好的最优拟合值。
为了澄清发生了什么,当使用numpy(或任何外部库)时,建议始终明确使用命名空间,如下面的工作版本所示:
import numpy
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

def GaussSum(x,*p):
    n=len(p)/3
    A=p[:n]
    w=p[n:2*n]
    c=p[2*n:3*n]
    y = sum([ A[i]*numpy.exp(-(x-c[i])**2./(2.*(w[i])**2.))/(2*numpy.pi*w[i]**2)**0.5 for i in range(n)])
    return y

params = [1.,1.,-3.]; #parameters for a single gaussian                                                                                                                        
#params=[1.,1.,1.,2.,-3.,0.]; #parameters for the sum of two gaussians                                                                                                         
xdata=numpy.arange(-6,6,0.01)
ydata = numpy.array([GaussSum(x,*params) for x in xdata])

popt,pcov = curve_fit(GaussSum,xdata,ydata,p0=params)

具体地说,您隐式调用了numpy.sum,它会聚合numpy.array并返回单个值,而您需要使用内置的python sum将numpy.array的本机列表聚合为一个numpy.array。


谢谢。这澄清了问题所在。不过有一点,工作代码需要在函数定义中使用返回(return)而不是y =。 - brad.t
是的,抱歉,没注意到漏掉了一行代码。 - Conor

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