简体   繁体   English

python curve_fit 没有给出合理的拟合结果

[英]python curve_fit does not give reasonable fitting result

I am trying to fit gaussian to a spectrum and the y values are on the order of 10^(-19).我试图将高斯拟合到频谱中,y 值约为 10^(-19)。 Curve_fit gives me poor fitting result, both before and after I multiply my whole data by 10^(-19). Curve_fit 在我将整个数据乘以 10^(-19) 之前和之后都给了我很差的拟合结果。 Attached is my code, it is fairly simple set of data except that the values are very small.附上我的代码,它是一组相当简单的数据,只是值非常小。 If I want to keep my original values, how would I get a reasonable gaussian fit that would give me the correct parameters?如果我想保留我的原始值,我将如何获得合理的高斯拟合来为我提供正确的参数?

#get fits data
aaa=pyfits.getdata('p1.cal.fits')

aaa=np.matrix(aaa)
nrow=np.shape(aaa)[0]
ncol=np.shape(aaa)[1]

ylo=79
yhi=90
xlo=0
xhi=1023
glo=430
ghi=470

#sum all the rows to get spectrum
ysum=[]
for x in range(xlo,xhi):
sum=np.sum(aaa[ylo:yhi,x])
ysum.append(sum)

wavelen_pix=range(xhi-xlo)
max=np.max(ysum)
print "maximum is at x=", np.where(ysum==max)

##fit gaussian
#fit only part of my data in the chosen range [glo:ghi]
x=wavelen_pix[glo:ghi]
y=ysum[glo:ghi]
def func(x, a, x0, sigma):
    return a*np.exp(-(x-x0)**2/float((2*sigma**2)))

sig=np.std(ysum[500:1000]) #std of background noise

popt, pcov = curve_fit(func, x, sig)
print popt  
#this gives me [1.,1.,1.], which is obviously wrong
gaus=func(x,popt[0],popt[1],popt[2])

aaa is a 153 by 1024 image matrix, partly looks like this: aaa 是一个 153 x 1024 的图像矩阵,部分如下所示:

matrix([[ -8.99793629e-20,   8.57133275e-21,   4.83523386e-20, ...,
-1.54811004e-20,   5.22941515e-20,   1.71179195e-20],
[  2.75769318e-20,   1.03177243e-20,  -3.19634928e-21, ...,
1.66583803e-20,  -9.88712568e-22,  -2.56897725e-20],
[  2.88121935e-20,   8.57964252e-21,  -2.60784327e-20, ...,
1.72335180e-20,  -7.61189937e-21,  -3.45333075e-20],
..., 
[  1.04006903e-20,   1.61200683e-20,   7.04195205e-20, ...,
1.72459645e-20,   4.29404029e-20,   1.99889374e-20],
[  3.22315752e-21,  -5.61394194e-21,   3.28763096e-20, ...,
1.99063583e-20,   2.12989880e-20,  -1.23250648e-21],
[  3.66591810e-20,  -8.08647455e-22,  -6.22773168e-20, ...,
-4.06145681e-21,   4.92453132e-21,   4.23689309e-20]], dtype=float32)

You are calling curve_fit incorrectly, here is the usage您错误地调用了curve_fit ,这是用法

curve_fit(f, xdata, ydata, p0=None, sigma=None, absolute_sigma=False, check_finite=True, **kw)
  • f is your function whose first arg is an array of independent variables, and whose subsequent args are the function parameters (such as amplitude, center, etc) f是您的函数,其第一个 arg 是自变量数组,其后续 args 是函数参数(例如幅度、中心等)
  • xdata are the independent variables xdata是自变量
  • ydata are the dependedent variable ydata是因变量
  • p0 is an initial guess at the function parameters (for Guassian this is amplitude, width, center) p0是对函数参数的初始猜测(对于高斯,这是幅度、宽度、中心)

By default p0 is set to a list of ones [1,1,...], which is probably why you get that as a result, the fit just never executed because you called it incorrectly.默认情况下,p0 被设置为一个 [1,1,...] 的列表,这可能就是你得到它的原因,因为你错误地调用了它,所以它从未执行过。

Try estimating the amplitude, center, and width from the data, then make a p0 object (see below for details)尝试从数据中估计幅度、中心和宽度,然后制作一个 p0 对象(详情见下文)

init_guess = ( a_i, x0_i, sig_i) # same order as they are supplied to your function
popt, pcov = curve_fit(func, xdata=x,ydata=y,p0=init_guess)

Here is a short example这是一个简短的例子

xdata = np.linspace(0, 4, 50)
mygauss = ( 10,2,0.5) #( amp, center, width)
y     = func(xdata, *mygauss  ) # using your func defined above    
ydata = y + 2*(np.random.random(50)- 0.5) # add some noise to create fake data

Now I can guess the fit params现在我可以猜出合适的参数

ai    = np.max( ydata) # guess the amplitude
xi    = xdata[ np.argmax( ydata)] # guess the position of center

Guessing the width is tricky, I would first find where the half max is located (there are two, but you only need to find one, as the Gaussian is symmetric):猜测宽度很棘手,我会首先找到半最大值所在的位置(有两个,但您只需要找到一个,因为高斯是对称的):

pos_half = argmin( np.abs( ydata-ao/2 ) ) # subtract half the amplitude and find the minimum

Now evaluate how far this is from the center of the gaussian (xi) :现在评估这离高斯 (xi) 的中心有多远:

sig_i = np.abs( xi - xdata[ pos_half] ) # estimate the width

Now you can make make the initial guess现在你可以做出最初的猜测

init_guess = (ai, xi sig_i)

and fit和适合

params, variance = curve_fit( func, xdata=xdata, ydata=ydata, p0=init_guess)
print params
#array([ 9.99457443,  2.01992858,  0.49599629])

which is very close to mygauss .这非常接近mygauss Hope it helps.希望能帮助到你。

Forget about rescaling, or making linear changes, or using the p0 parameter, which usually don't work!忘记重新缩放,或进行线性更改,或使用 p0 参数,这些通常不起作用! Try using the bounds parameter in the curve_fit for n parameters like this:尝试使用 curve_fit 中的 bounds 参数用于 n 个参数,如下所示:

a0=np.array([a01,...,a0n])
af=np.array([af1,...,afn])
method="trf",bounds=(a0,af)

Hope it works!希望它有效! ;) ;)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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