ガウス曲線を当てはめ、それから全幅の半分の最大値を取得する必要があるピークを持つ一連の周波数データがあります。私ができるFWHMの部分、私はすでにそのためのコードを持っていますが、Gaussianに適合するコードを書くのに問題があります。
誰かが私のためにこれを行うか、私を正しい方向に向けることができる機能を知っていますか? (私は線と多項式に対して最小二乗フィッティングを行うことができますが、ガウスに対してそれを機能させることができません)
また、現時点でOctaveを使用しているが、来週までMatlabにアクセスできないため、OctaveとMatlabの両方と互換性がある場合にも役立ちます。
どんな助けでも大歓迎です!
単一の1Dガウスを直接当てはめることは、非線形当てはめの問題です。既成の実装 here 、または here 、または here for 2D 、または here (ifあなたは統計ツールボックスを持っています)(Googleについて聞いたことがありますか?:)
とにかく、もっと簡単な解決策があるかもしれません。データy
がガウス分布でよく記述され、x
の範囲全体に適度に分布していることが確実にわかっている場合は、問題を線形化できます(これらは方程式であり、ステートメントではありません):
_ 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
とクロスチェックできます(smallの違いのみが必要です)。
多分これはあなたが探しているものを持っていますか?互換性については不明: 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.
私は、MATLABの "fit"関数が遅いことを発見し、インラインガウス関数で "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')
同様の問題がありました。これはグーグルでの最初の結果であり、ここにリンクされているスクリプトのいくつかは私のMATLABをクラッシュさせました。
最後に、私は here を発見しました。MATLABには、ガウス関数にもフィットできるfit関数が組み込まれています。
それはそのように見えます:
>> 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)