[英]Fitting gaussian to a curve in Python II
我有两个清单。
import numpy
x = numpy.array([7250, ... list of 600 ints ... ,7849])
y = numpy.array([2.4*10**-16, ... list of 600 floats ... , 4.3*10**-16])
它们形成 U 形曲线。 现在我想将高斯拟合到该曲线上。
from scipy.optimize import curve_fit
n = len(x)
mean = sum(y)/n
sigma = sum(y - mean)**2/n
def gaus(x,a,x0,sigma,c):
return a*numpy.exp(-(x-x0)**2/(2*sigma**2))+c
popt, pcov = curve_fit(gaus,x,y,p0=[-1,mean,sigma,-5])
pylab.plot(x,y,'r-')
pylab.plot(x,gaus(x,*popt),'k-')
pylab.show()
我最终得到了嘈杂的原始 U 形曲线和一条穿过曲线的水平直线。
我不确定上面代码中的 -1 和 -5 代表什么,但我确定我需要调整它们或其他东西来获得高斯曲线。 我一直在尝试可能的值,但无济于事。
有任何想法吗?
首先,您的变量sigma
实际上是方差,即sigma平方--- http://en.wikipedia.org/wiki/Variance#Definition 。 通过给它一个次优的起始估计值,它会混淆curve_fit。
然后,您拟合的ansatz gaus
包括振幅a
和偏移量,这是您真正需要的吗? 起始值为a=-1
(负钟形)和偏移c=-5
。 他们来自哪里?
这是我要做的:
a
由sigma
等固定。 如果您实际上只想要一个没有任何curve_fit
的高斯函数,那么您可能实际上并不需要curve_fit
:一个高斯函数是由两个第一刻完全定义的,即mean
和sigma
。 按您的方式计算它们,将它们绘制在数据上,看看是否还没有准备好。
调用curve_fit时的p0给出了除x之外的函数附加参数的初始猜测。 在上面的代码中,您要说的是我希望curve_fit函数使用-1作为a的初始猜测,-5作为c的初始猜测,均值作为x0的初始猜测,并且sigma用作sigma的猜测。 然后,curve_fit函数将调整这些参数以尝试获得更好的拟合度。 问题在于,给定(x,y)s的顺序,您最初对函数参数的猜测确实很糟糕。
考虑一下您的高斯参数的数量级。 a应该在y值的大小(10 **-16)左右,因为在高斯峰时,指数部分永远不会大于1。x0将在x值内给出您指数部分的位置高斯将为1,因此x0应该在7500左右,可能在数据中心的某个位置。 Sigma表示高斯的宽度或展宽,因此100左右的值只是一个猜测。 最后,c只是使整个高斯向上或向下移动的偏移量。
我建议做的是,在拟合曲线之前,为a,x0,sigma和c选择一些看起来合理的值,然后使用高斯绘制数据,并使用a,x0,sigma和c直到得到看起来至少与您希望高斯拟合的方式相似,然后将其用作curve_fit p0值的起点。 我提供的值应该可以帮助您入门,但可能无法完全满足您的要求。 例如,如果您想翻转高斯以获得“ U”形,则可能需要为负数。
另外,打印出curve_fit认为对您的a,x0,sigma和c有用的值,可能会帮助您了解它的作用,以及该函数是否在正确的轨道上以最小化拟合残差。
使用gnuplot进行曲线拟合时,我遇到了类似的问题,如果初始值与您要拟合的值相差太远,则它会在完全错误的方向上使用参数以最大程度地减少残差,并且您可能会做得更好。 将这些功能视为通过肉眼估计这些参数来微调您的一种方法。
希望能有所帮助
我认为您没有正确估计初始估计的均值和西格玛。
在这里看看SciPy Cookbook
我认为应该看起来像这样。
x = numpy.array([7250, ... list of 600 ints ... ,7849])
y = numpy.array([2.4*10**-16, ... list of 600 floats ... , 4.3*10**-16])
n = len(x)
mean = sum(x*y)/sum(y)
sigma = sqrt(abs(sum((x-mean)**2*y)/sum(y)))
def gaus(x,a,x0,sigma,c):
return a*numpy.exp(-(x-x0)**2/(2*sigma**2))+c
popy, pcov = curve_fit(gaus,x,y,p0=[-max(y),mean,sigma,min(x)+((max(x)-min(x)))/2])
pylab.plot(x,gaus(x,*popt))
如果有人链接到简单的说明,那么为什么现在才是正确的时机,我将不胜感激。 我坚信SciPy Cookbook正确无误。
这是解决方案,感谢大家。
x = numpy.array([7250, ... list of 600 ints ... ,7849])
y = numpy.array([2.4*10**-16, ... list of 600 floats ... , 4.3*10**-16])
n = len(x)
mean = sum(x)/n
sigma = math.sqrt(sum((x-mean)**2)/n)
def gaus(x,a,x0,sigma,c):
return a*numpy.exp(-(x-x0)**2/(2*sigma**2))+c
popy, pcov = curve_fit(gaus,x,y,p0=[-max(y),mean,sigma,min(x)+((max(x)-min(x)))/2])
pylab.plot(x,gaus(x,*popt))
也许是因为我使用 matlab 和 fminsearch 或者我的拟合必须处理更少的数据点(~ 5-10),我使用以下起始值获得了更好的结果(就像它们一样简单):
a = max(y)-min(y);
imax= find(y==max(y),1);
mean = x(imax);
avg = sum(x.*y)./sum(y);
sigma = sqrt(abs(sum((x-avg).^2.*y) ./ sum(y)));
c = min(y);
西格玛工作正常。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.