Asked by Rogier Busscher
on 1 Jun 2017

So i have a scatterplot scatter(x,y) and I would like to find a best fit for a function of the type F(x)=e^(-(Bèta)*x) with x matching x and F(x) matching/approximating the corresponding y.

I would like to find the best fit and get the value of Bèta returned.

How do i do this?

Answer by Walter Roberson
on 1 Jun 2017

Accepted Answer

If y = exp(-beta*x) then log(y) = -beta*x and beta = -log(y)/x . Your best fit in log space would then be approximately

beta = mean( -log(y) ./ x )

In linear space,

beta = lsqcurvefit(@(beta,x) exp(-beta*x), 3, x, y);

However, when I constructed artificial data by defining beta and using

c = 1;

y = exp(-beta*x + randn(size(x)) * c );

and then fit against that to recover beta, then I found that a closer beta to the one I defined could be calculated as

other_beta = lsqcurvefit(@(beta,x) beta*x, 3, x, -log(y));

As c gets reduced to (say) 1/10 then the two fittings become more similar.

With a noise model like

c = 1/15;

y = exp(-beta*x) + (2 * rand(size(x)) - 1) * c;

then the original beta version becomes a notably better fit. So which one to use would probably depend upon the model of noise / error that you have.

Sign in to comment.

Answer by Image Analyst
on 1 Jun 2017

Use fitnlm() in the Statistics and Machine Learning Toolbox. Here is a demo:

% Uses fitnlm() to fit a non-linear model (an exponential decay curve) through noisy data.

% Requires the Statistics and Machine Learning Toolbox, which is where fitnlm() is contained.

% Initialization steps.

clc; % Clear the command window.

close all; % Close all figures (except those of imtool.)

clear; % Erase all existing variables. Or clearvars if you want.

workspace; % Make sure the workspace panel is showing.

format long g;

format compact;

fontSize = 20;

% Create the X coordinates from 0 to 20 every 0.5 units.

X = 0 : 0.5 : 20;

% Define function that the X values obey.

a = 0 % Arbitrary sample values I picked.

b = 0.4

Y = a + exp(-X * b); % Get a vector. No noise in this Y yet.

% Add noise to Y.

Y = Y + 0.05 * randn(1, length(Y));

% Now we have noisy training data that we can send to fitnlm().

% Plot the noisy initial data.

plot(X, Y, 'b*', 'LineWidth', 2, 'MarkerSize', 15);

grid on;

% Convert X and Y into a table, which is the form fitnlm() likes the input data to be in.

tbl = table(X', Y');

% Define the model as Y = a + exp(-b*x)

% Note how this "x" of modelfun is related to big X and big Y.

% x((:, 1) is actually X and x(:, 2) is actually Y - the first and second columns of the table.

modelfun = @(b,x) b(1) + exp(-b(2)*x(:, 1));

beta0 = [10, .4]; % Guess values to start with. Just make your best guess.

% Now the next line is where the actual model computation is done.

mdl = fitnlm(tbl, modelfun, beta0);

% Now the model creation is done and the coefficients have been determined.

% YAY!!!!

% Extract the coefficient values from the the model object.

% The actual coefficients are in the "Estimate" column of the "Coefficients" table that's part of the mode.

coefficients = mdl.Coefficients{:, 'Estimate'}

% Create smoothed/regressed data using the model:

yFitted = coefficients(1) + exp(-coefficients(2)*X);

% Now we're done and we can plot the smooth model as a red line going through the noisy blue markers.

hold on;

plot(X, yFitted, 'r-', 'LineWidth', 2);

grid on;

title('Exponential Regression with fitnlm()', 'FontSize', fontSize);

xlabel('X', 'FontSize', fontSize);

ylabel('Y', 'FontSize', fontSize);

legendHandle = legend('Noisy Y', 'Fitted Y', 'Location', 'north');

legendHandle.FontSize = 25;

% Set up figure properties:

% Enlarge figure to full screen.

set(gcf, 'Units', 'Normalized', 'OuterPosition', [0 0 1 1]);

% Get rid of tool bar and pulldown menus that are along top of figure.

set(gcf, 'Toolbar', 'none', 'Menu', 'none');

% Give a name to the title bar.

set(gcf, 'Name', 'Demo by ImageAnalyst', 'NumberTitle', 'Off')

Sign in to comment.

Opportunities for recent engineering grads.

Apply Today
## 0 Comments

Sign in to comment.