13 views (last 30 days)

I wonder if it is possible to fit a familiar model to this data?

My first thought tends to use the mixed Gaussian model to fit a bimodal distribution. I don't know if it can work, please give some advice. Also, is there any other distribution that I can use to fit this data more properly?

Thiago Henrique Gomes Lobato
on 28 Jun 2020

You can estimate a continious function from your data using ksdensity and then fit two gaussians on it. My answer for the following questions does this https://de.mathworks.com/matlabcentral/answers/482688-get-parameters-of-gaussian-distributions-from-ksdensity-function#answer_393989?s_tid=prof_contriblnk . For sake of breviety, here is the copied code from the answer:

[f,xi] = ksdensity(x); % x is your data

% Here I generate a function from two Gaussians and output

% the rms of the estimation error from the values obtained from ksdensity

fun = @(xx,t,y)rms(y-(xx(5)*1./sqrt(xx(1)^2*2*pi).*exp(-(t-xx(2)).^2/(2*xx(1)^2))+...

xx(6)*1./sqrt(xx(3)^2*2*pi).*exp(-(t-xx(4)).^2/(2*xx(3)^2)) ) );

% Get the parameters with the minimum error. To improve convergence,choose reasonable initial values

[x,fval] = fminsearch(@(r)fun(r,xi,f),[0.2,4.7,0.2,5.3,0.5,0.5]);

% Make sure sigmas are positive

x([1,3]) = abs(x([1,3]));

% Generate the Parametric functions

pd1 = makedist('Normal','mu',x(2),'sigma',x(1));

pd2 = makedist('Normal','mu',x(4),'sigma',x(3));

% Get the probability values

y1 = pdf(pd1,xi)*x(5); % x(5) is the participation factor from pdf1

y2 = pdf(pd2,xi)*x(6); % x(6) is the participation factor from pdf2

% Plot

figure

plot(xi,f);

hold on;

plot(xi,y1);

plot(xi,y2);

plot(xi,y2+y1);

legend({'ksdensity',['\mu : ',num2str(x(2)),'. \sigma :',num2str(x(1))],...

['\mu : ',num2str(x(4)),'. \sigma :',num2str(x(3))],'pdf1+pdf2'})

Walter Roberson
on 30 Jun 2020

fminunc() and fmincon() both tend to get caught in local minima, which is a problem for fitting sum of gaussians because sum of gaussians turns out to have a lot of local minima. fminsearch() is less likely to get caught in small-scale local minima (but it can still get caught in large-scale local minima.)

One technique that can be helpful is to use fminsearch() to find a good "nearby" value, and then to use the result as a starting point for fminunc() or fmincon()

One point I would make is that often when you are dealing with gaussians, you have a location, height, and phase -- three parameters (sometimes expressed as four parameters.) And phase is usually constrained, because there is no benefit for searching outside of +/- 2*pi. Notice I did not say outside of +/- pi : when the phase is close to +/- pi then you want to be able to search on both sides of the +/- pi boundary for continuity . You would prefer not to end up partitioning the search into two different spaces, one approaching +pi from below and the other approaching -pi from above.

Walter Roberson
on 1 Jul 2020

I think I might still suggest fminsearch() first, using the value from the previous search, and then fmincon() to narrow down more precisely

You might also want to look in the File Exchange as John D'Errico has posted fminsearchbnd for bounded search.

Image Analyst
on 28 Jun 2020

I've attached code, fit_two_Gaussians.m, to find two Gaussians with a slope in the x direction (to give a slightly better fit). Replace the demo (x,y) with your (x,y) and it will fit your data.

I'm also attaching a demo that fits any number of Gaussians to the data. The demo uses 6 Gaussians but you can tell it how many you want it to find.

Image Analyst
on 30 Jun 2020

No, that's not correct. It's a 1-D situation.

I have an independent variable X, and for that I have one dependent variable Y, not two. So it's a 1-D situation.

It's not a 2-D situation, which would be like you're trying to fit 2-D Gaussians to "spots" or "humps" in a 2-D grayscale image. Realize that x,y is a 1-D situation while x,y and intensity (z) is a 2-D situation. 2-D data would be like I had an intensity for an x, y pair on an image.

Image Analyst
on 30 Jun 2020

What you call x is the dependent variable. So in your case the independent variable would simply be the index. So to make your data be x,y, you'd do

y = x; % Make a copy of the x variable in a variable called y.

x = 1 : length(y); % The x, or independent variable, is simply the index number.

Opportunities for recent engineering grads.

Apply Today
## 1 Comment

## Direct link to this comment

https://ch.mathworks.com/matlabcentral/answers/556006-fit-two-peak-model#comment_916246

⋮## Direct link to this comment

https://ch.mathworks.com/matlabcentral/answers/556006-fit-two-peak-model#comment_916246

Sign in to comment.