web-dev-qa-db-fra.com

Comment adapter un gaussien aux données de matlab/octave?

J'ai un ensemble de données de fréquence avec des pics sur lesquels je dois ajuster une courbe gaussienne, puis obtenir la moitié de la largeur maximale. La partie FWHM que je peux faire, j'ai déjà un code pour cela, mais j'ai du mal à écrire du code pour le gaussien.

Est-ce que quelqu'un connaît des fonctions qui feront cela pour moi ou qui pourraient me diriger dans la bonne direction? (Je peux faire les moindres carrés pour les lignes et les polynômes, mais je ne peux pas le faire fonctionner pour les Gaussiens.)

De plus, il serait utile que ce soit compatible avec Octave et Matlab, car j'ai Octave pour le moment, mais je n'ai pas accès à Matlab avant la semaine prochaine.

Toute aide serait grandement appréciée!

9
user1806676

Le montage direct d’un seul gaussien 1D est un problème d’ajustement non linéaire. Vous trouverez des implémentations toutes faites ici ou ici , ou ici pour 2D , ou ici (si vous avez les statistiques boîte à outils) (avez-vous entendu parler de Google? :) 

Quoi qu'il en soit, il pourrait y avoir une solution plus simple. Si vous êtes certain que vos données y seront bien décrites par un gaussien et raisonnablement bien réparties sur toute votre plage x-, vous pouvez linéariser le problème (il s'agit d'équations et non de déclarations):

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

où les substitutions

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

ont été faites. Maintenant, résolvez pour le système linéaire Ax=b avec (ce sont des instructions 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;                    

Le vecteur x que vous avez trouvé de cette façon sera égal à

x == [P Q R]

que vous devez ensuite désosser pour trouver la moyenne µ et l'écart-type σ: 

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

Que vous pouvez vérifier avec x(3) == R (il ne devrait y avoir que petites différences).

19
Rody Oldenhuis

Peut-être que ceci a la chose que vous recherchez? Pas sûr de la compatibilité: http://www.mathworks.com/matlabcentral/fileexchange/11733-gaussian-curve-fit

De sa documentation:

[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.
2

j'avais un problème similaire . c'était le premier résultat sur google, et certains des scripts liés ici ont fait planter mon matlab.

enfin, j’ai trouvé ici que matlab a une fonction d’ajustement intégrée, qui convient également aux Gaussiens.

ça ressemble à ça:

>> 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
Ohad Cohen

J'ai trouvé que la fonction "fit" de MATLAB était lente et j'ai utilisé "lsqcurvefit" avec une fonction gaussienne en ligne. C'est pour ajuster une fonction gaussienne, si vous voulez juste adapter des données à une distribution normale, utilisez "normfit".

Vérifie ça 

% % 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')
0
MJRunfeldt