python - curve_fit 似乎无法拟合高斯总和
python - curve_fit is seemingly unable to fit sum of gaussians
这里我定义了一个函数return任意数量的高斯分布的总和:
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
我知道函数本身运行正常,因为我已经用它绘制并验证了它的有效性。
这里的问题是 curve_fit 期望您正在优化的函数采用输入向量和 return 输出向量。如所写,函数 GaussSum 接受单个输入或输入向量(即 numpy.array),但无论哪种方式,它 return 都是单个标量输出。 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 和 return 聚合为一个值,而您需要使用内置的 python 求和,这将 numpy.array 的原生列表聚合为一个 numpy.array.
这里我定义了一个函数return任意数量的高斯分布的总和:
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
我知道函数本身运行正常,因为我已经用它绘制并验证了它的有效性。
这里的问题是 curve_fit 期望您正在优化的函数采用输入向量和 return 输出向量。如所写,函数 GaussSum 接受单个输入或输入向量(即 numpy.array),但无论哪种方式,它 return 都是单个标量输出。 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 和 return 聚合为一个值,而您需要使用内置的 python 求和,这将 numpy.array 的原生列表聚合为一个 numpy.array.