Choosing a suitable fit for the graph

7 次查看(过去 30 天)
Hi,
I'm a begginer in matlab, so maybe it's simple, but I couldn't find an answer online..
I work on scanning from fabry-perot, and I need to do fit on the plot. I'm not sure what type of fit I should use, here's the graph I have from the scan:
I found how to make a Gaussian fit for example, but this fit does not fit my graph.. Where can I see all the types of fits that exist? Or maybe I should make a fit with my own function? And if so, how do you do it?
I would appreciate help in terms of choosing the appropriate fit if you have an idea, and also help in terms of the code and how to do it.
Thank you!

回答(2 个)

Star Strider
Star Strider 2024-4-30
I would choose a different function, perhaps something similar to with appropriate additional parameters. Then use findpeaks to locate the peak values (this will become ‘b(3)’ in the initial parameter estimates), and then choose the optimisation function of your choice (for example fminsearch) to fit the parameters. The initial estimate for ‘b(2)’ should always be negative, and relatively large (I chose -15 here in this illustration), with ‘b(1)’ determining the amplitude. Fit each pulse individually.
x = linspace(0, 4, 250);
pkfcn = @(b,x) b(1).*(x-b(3)).*exp(b(2)*(x-b(3))) .* (x>b(3)); % Peak Function
B1 = [1.5; -15; 1.2];
B2 = [1.5; -15; 3];
figure
plot(x, pkfcn(B1,x))
hold on
plot(x, pkfcn(B2,x))
hold off
grid
It would of course help to have your data.
.
  4 个评论
Yohay
Yohay 2024-4-30
Hi, thanks for your answer!
I attached my data as x and y, I hope this file is OK for you. If not, tell me and I try again..
In general I understand what you say to do, but I don't understanding how to do this in the code. I will be happy if you can explain more about what you do in your code.
thanks!
Star Strider
Star Strider 2024-4-30
My pleasure!
The fit is not perfect, however it is reasonably close. (A better fit would be the function that describes the process that produced your data.)
Try this —
load('matlab data.mat')
whos('-file', 'matlab data.mat')
Name Size Bytes Class Attributes x 1x250000 2000000 double y 1x250000 2000000 double
[pks,locs] = findpeaks(y, 'MinPeakProminence',0.01) % Get Peak Values & Location Indices
pks = 1x2
0.0317 0.0316
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
locs = 1x2
111970 202959
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
pkfcn = @(b,x) b(1).*(x-b(3)).*exp(b(2)*(x-b(3))) .* (x>b(3)); % Peak Function
for k = 1:numel(pks)
B0 = [pks(k)*10; -15; x(locs(k))]; % Initial Parameters Estimate
[B(:,k) fv(k)] = fminsearch(@(b)norm(pkfcn(b,x)-y), B0); % Nonlinear Regression To Fit Parameters 'B'
end
% B
figure
plot(x, y, '.', 'MarkerSize', 0.015, 'DisplayName','Data')
hold on
for k = 1:numel(pks)
plot(x, pkfcn(B(:,k), x), '-', 'LineWidth',1.75, 'DisplayName',["Peak at "+B(3,k)])
end
hold off
grid
xlabel('x')
ylabel('y')
title('Fit of: y(x) = \beta_2 \cdot(x-\beta_3) \cdot e^{\beta_2 \cdot (x-\beta_3)}')
legend('Location','best')
Parameter_Estimates = table(B(3,:).',B(1,:).',B(2,:).', 'VariableNames',{'Location','Amplitude','Exponent'})
Parameter_Estimates = 2x3 table
Location Amplitude Exponent ________ _________ ________ 1.3402 1.3247 -24.031 2.8354 1.5807 -26.378
.

请先登录,再进行评论。


S0852306
S0852306 2024-4-30
You may try sum of multiple gaussian,i.e.
normalize x and y before the curve fit is perform, i.e.
x_hat = (x - mean(x)) / std(x);
y_hat = (y - mean(y)) / std(y);
, where are mean of and are standard deviation of .
this will make optimization easier to converge.
Here's the result when N is equal to 4. you might get more accurate fit when more gaussian are used.
e.g. N= 8
this can be done using MATLAB's Curve Fitter app.
the following code is generate by Curve Fitter.
function [fitresult, gof] = createFit(x_hat, y_hat)
%CREATEFIT(X_HAT,Y_HAT)
% Create a fit.
%
% Data for 'untitled fit 1' fit:
% X Input: x_hat
% Y Output: y_hat
% Output:
% fitresult : a fit object representing the fit.
% gof : structure with goodness-of fit info.
%% Fit: 'untitled fit 1'.
[xData, yData] = prepareCurveData( x_hat, y_hat );
% Set up fittype and options.
ft = fittype( 'gauss4' );
opts = fitoptions( 'Method', 'NonlinearLeastSquares' );
opts.Display = 'Off';
opts.Lower = [-Inf -Inf 0 -Inf -Inf 0 -Inf -Inf 0 -Inf -Inf 0];
opts.StartPoint = [7.52132714016075 -0.180555543273485 0.0773675110948242 7.50612216935737 1.08022250261202 0.0397394906485454 1.59916872787823 1.16365175905265 0.076917025245678 0.816149525496624 -0.0354931141625441 0.0690191466049118];
% If you have some prior knowledge about the data, you may guess a better
% start point.
[fitresult, gof] = fit( xData, yData, ft, opts );
% Plot fit with data.
figure( 'Name', 'untitled fit 1' );
h = plot( fitresult, xData, yData );
legend( h, 'y_hat vs. x_hat', 'untitled fit 1', 'Location', 'NorthEast', 'Interpreter', 'none' );
% Label axes
xlabel( 'x_hat', 'Interpreter', 'none' );
ylabel( 'y_hat', 'Interpreter', 'none' );
grid on
If you want to get a better fit, try this FEX,
Here's the result of FEX:
clear; clc;
data = load('DownloadData.mat');
x = data.x; y = data.y;
%%
NN.LabelAutoScaling = 'on';
NN.InputAutoScaling = 'on';
LayerStruct=[1, 10, 10, 10, 10, 1];
NN=Initialization(LayerStruct, NN);
%%
option.MaxIteration=300;
NN=OptimizationSolver(x, y, NN, option);
%%
predict = NN.Evaluate(x);
plot(x, y, 'LineWidth', 2)
hold on
plot(x, predict, 'LineWidth', 1)
legend('Data', 'Fitting')
%%
R = FittingReport(x, y, NN);

类别

Help CenterFile Exchange 中查找有关 Get Started with Curve Fitting Toolbox 的更多信息

标签

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by