簡體   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