我有两个清单。
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代表什么,但我确定我需要调整它们或其他东西来获得高斯曲线。我一直在玩可能的价值但无济于事。
有什么想法吗?
答案 0 :(得分:2)
首先,您的变量sigma
实际上是方差,即西格玛平方--- http://en.wikipedia.org/wiki/Variance#Definition。
这会使curve_fit混淆,给它一个次优的起始估计。
然后,您的拟合ansatz gaus
包含幅度a
和偏移量,这是您实际需要的吗?起始值为a=-1
(否定钟形)和偏移c=-5
。它们来自哪里?
这就是我要做的事情:
a
由sigma
等固定。如果你真的只想要一个没有任何花里胡哨的高斯,你实际上可能不需要curve_fit
:高斯是由两个第一时刻完全定义的mean
和sigma
。像你一样计算它们,将它们绘制在数据上,看看你是否都没有设置好。
答案 1 :(得分:1)
稍微考虑一下高斯的不同参数的数量级。 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进行曲线拟合时遇到了类似的问题,如果初始值与你想要的东西相距太远,那么使用参数来完全错误的方向来最小化残差,你可能用眼睛做得更好。您可以将这些功能视为微调这些参数的估算方法。
希望有所帮助
答案 2 :(得分:1)
我不认为你正在估计你对正确和sigma的初步猜测。
查看SciPy Cookbook here
我认为它应该是这样的。
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做对了。
答案 3 :(得分:0)
感谢所有人,这是解决方案。
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))