This example shows how to fit a nonlinear function to data. For this example, the nonlinear function is the standard exponential decay curve
where is the response at time , and and are the parameters to fit. Fitting the curve means finding parameters and that minimize the sum of squared errors
where the times are and the responses are . The sum of squared errors is the objective function.
Usually, you have data from measurements. For this example, create artificial data based on a model with and , with normally distributed pseudorandom errors.
rng default % for reproducibility tdata = 0:0.1:10; ydata = 40*exp(-0.5*tdata) + randn(size(tdata));
Write a function that accepts parameters
lambda and data
ydata, and returns the sum of squared errors for the model
. Put all the variables to optimize (
lambda) in a single vector variable (
x). For more information, see Minimizing Functions of Several Variables.
function sse = sseval(x,tdata,ydata) A = x(1); lambda = x(2); sse = sum((ydata - A*exp(-lambda*tdata)).^2);
Save this objective function as a file named
sseval.m on your MATLAB® path.
fminsearch solver applies to functions of one variable,
x. However, the
sseval function has three variables. The extra variables
ydata are not variables to optimize, but are data for the optimization. Define the objective function for
fminsearch as a function of
fun = @(x)sseval(x,tdata,ydata);
For information about including extra parameters such as
ydata, see Parameterizing Functions.
Start from a random positive set of parameters
x0, and have
fminsearch find the parameters that minimize the objective function.
x0 = rand(2,1); bestx = fminsearch(fun,x0)
bestx = 40.6877 0.4984
bestx is reasonably near the parameters that generated the data,
A = 40 and
lambda = 0.5.
To check the quality of the fit, plot the data and the resulting fitted response curve. Create the response curve from the returned parameters of your model.
A = bestx(1); lambda = bestx(2); yfit = A*exp(-lambda*tdata); plot(tdata,ydata,'*'); hold on plot(tdata,yfit,'r'); xlabel('tdata') ylabel('Response Data and Curve') title('Data and Best Fitting Exponential Curve') legend('Data','Fitted Curve') hold off