繁体   English   中英

将高斯拟合到 Python II 中的曲线

[英]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 他们来自哪里?

这是我要做的:

  • 修复您的拟合模型。 您是否只需要高斯,是否需要将其标准化。 如果是的话,则振幅asigma等固定。
  • 看一下实际数据。 尾巴是什么(偏移),符号是什么(振幅符号)。

如果您实际上只想要一个没有任何curve_fit的高斯函数,那么您可能实际上并不需要curve_fit :一个高斯函数是由两个第一刻完全定义的,即meansigma 按您的方式计算它们,将它们绘制在数据上,看看是否还没有准备好。

调用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM