2012-11-08 111 views
8

我有一套帶有峯值的頻率數據,我需要擬合一個高斯曲線,然後從中獲得半峯全寬。 FWHM的一部分我可以做,我已經有了一個代碼,但我無法編寫代碼來適應高斯。如何在matlab/octave中擬合高斯數據?

有沒有人知道任何功能,會爲我做這個或將能夠指出我在正確的方向嗎? (我可以做線和多項式的最小二乘擬合,但我不能讓它適用於高斯)

如果它與Octave和Matlab兼容,這是有幫助的,因爲我現在有Octave,但不會直到下週才能訪問Matlab。

任何幫助將不勝感激!

+0

你有一個單峯(僅1高斯)?還是多個高峯(多重重疊的高加索人)? –

+0

這只是每個文件的單個峯值。 – user1806676

+1

如果它只是一個峯值,則取數值的均值和標準值,並定義您的樣本正態分佈。你嘗試過嗎?否則,如果您有統計工具箱,請使用normfit()。 – Justin

回答

19

直接擬合單維高斯是一個非線性擬合問題。你會發現現成的實現here,或here,或者here for 2D,或here(如果你有統計工具箱)(你有沒有聽說過谷歌的?:)

無論如何,有可能是一個簡單的解決方案。如果你確信你的數據y將由高斯很好的描述,併合理地分佈在整個x -range,可以線性化問題(這些方程,不是語句):

y = 1/(σ·√(2π)) · exp(-½ ((x-μ)/σ)²) 
ln y = ln(1/(σ·√(2π))) - ½ ((x-μ)/σ)² 
    = Px² + Qx + R   

其中取代

P = -1/(2σ²) 
Q = +2μ/(2σ²)  
R = ln(1/(σ·√(2π))) - ½(μ/σ)² 

已經被製成。現在,解決與線性系統Ax=b(這是Matlab的語句):

% design matrix for least squares fit 
xdata = xdata(:); 
A = [xdata.^2, xdata, ones(size(xdata))]; 

% log of your data 
b = log(y(:));     

% least-squares solution for x 
x = A\b;      

x你找到了這樣的載體將等於

x == [P Q R] 

這你就必須逆向工程找到均值μ和標準偏差σ:

mu = -x(2)/x(1)/2; 
sigma = sqrt(-1/2/x(1)); 

x(3) == R,您可以交叉檢查(應該只有差異)。

+0

非常感謝。我只能通過谷歌找到第一個鏈接,但沒有與我的數據一起工作,第二個雖然工作。 也感謝您的解釋/方程式。 :D – user1806676

+0

@ user1806676:我還沒有嘗試線性化方法,但至少數學是正確的。你應該在那裏做一些實驗和驗證。 –

+0

試過了線性化的方法。效果很好。 –

2

也許這有你正在尋找的東西?不知道兼容性: http://www.mathworks.com/matlabcentral/fileexchange/11733-gaussian-curve-fit

從它的文檔:

[sigma,mu,A]=mygaussfit(x,y) 
[sigma,mu,A]=mygaussfit(x,y,h) 

this function is doing fit to the function 
y=A * exp(-(x-mu)^2/(2*sigma^2)) 

the fitting is been done by a polyfit 
the lan of the data. 

h is the threshold which is the fraction 
from the maximum y height that the data 
is been taken from. 
h should be a number between 0-1. 
if h have not been taken it is set to be 0.2 
as default. 
+0

更適合作爲評論,不是嗎? –

+0

儘管這個鏈接可能回答這個問題,但最好在這裏包含答案的基本部分,並提供供參考的鏈接。如果鏈接頁面更改,則僅鏈接答案可能會失效。 - [來自評論](/評論/低質量帖/ 13114204) –

+1

@ScottHoltzman感謝您的高擡頭,我已經包括了相關的描述。 –

1

我有類似的問題。 這是谷歌的第一個結果,這裏鏈接的一些腳本使我的matlab崩潰。

終於找到了here這個matlab已經建立了適合函數,也可以適合高斯。

它看起來像:

>> v=-30:30; 
>> fit(v', exp(-v.^2)', 'gauss1') 

ans = 

    General model Gauss1: 
    ans(x) = a1*exp(-((x-b1)/c1)^2) 
    Coefficients (with 95% confidence bounds): 
     a1 =   1 (1, 1) 
     b1 = -8.489e-17 (-3.638e-12, 3.638e-12) 
     c1 =   1 (1, 1) 
+1

請注意,'fit'不是內置的;它是曲線擬合工具箱的一部分 –

0

我發現MATLAB「適合」的功能緩慢,並用「lsqcurvefit」具有內嵌高斯函數。這適用於擬合高斯函數,如果您只想將數據擬合到正態分佈,請使用「normfit」。

檢查

% % Generate synthetic data (for example) % % % 

    nPoints = 200; binSize = 1/nPoints ; 
    fauxMean = 47 ;fauxStd = 8; 
    faux = fauxStd.*randn(1,nPoints) + fauxMean; % REPLACE WITH YOUR ACTUAL DATA 
    xaxis = 1:length(faux) ;fauxData = histc(faux,xaxis); 

    yourData = fauxData; % replace with your actual distribution 
    xAxis = 1:length(yourData) ; 

    gausFun = @(hms,x) hms(1) .* exp (-(x-hms(2)).^2 ./ (2*hms(3)^2)) ; % Gaussian FUNCTION 

% % Provide estimates for initial conditions (for lsqcurvefit) % % 

    height_est = max(fauxData)*rand ; mean_est = fauxMean*rand; std_est=fauxStd*rand; 
    x0 = [height_est;mean_est; std_est]; % parameters need to be in a single variable 

    options=optimset('Display','off'); % avoid pesky messages from lsqcurvefit (optional) 
    [params]=lsqcurvefit(gausFun,x0,xAxis,yourData,[],[],options); % meat and potatoes 

    lsq_mean = params(2); lsq_std = params(3) ; % what you want 

% % % Plot data with fit % % % 
    myFit = gausFun(params,xAxis); 
    figure;hold on;plot(xAxis,yourData./sum(yourData),'k'); 
    plot(xAxis,myFit./sum(myFit),'r','linewidth',3) % normalization optional 
    xlabel('Value');ylabel('Probability');legend('Data','Fit')