Multi-Parameter Curve Fitting --- How to use lsqcurvefit ?

16 views (last 30 days)
Hello!
I am major in chemistry and inexperience with Matlab.
Currently, I'm trying to fit a nonlinear curve with my model, so I use lsqcurvefit to get the parameters of my function. After finishing the code, I obtain this output:
"Error using lsqfcnchk (line 80)
FUN must be a function, a valid character vector expression, or an inline function object.
Error in lsqnsetup (line 46)
funfcn = lsqfcnchk(FUN,caller,lengthVarargin,funValCheck,flags.grad);"
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
My curve fitting problem can be described as follows:
In order to display my code in a simple way, I set N=2, and I make a fake Objective function J_aim for testing. My code is as follows:
global Dim_N
Dim_N = 2;
%--------Objective Function (Curve)---------------
x = linspace(1.4,1.9,1000);
J_aim = 0.01./((x-1.6).^2+0.01^2)+0.05./((x-1.7).^2+0.05^2);
plot(x,J_aim);
hold on
%-----It is just a test, not the real curve I want to fit-----------
%-------Fitting Parameters----------------
gT = [0.5,0.2];
g = transpose(gT);
w = [1.6,0 ; 0, 1.7];
kappa = [0.01,0.05];
%-------Reshape these Parameters----------
para = [gT, kappa, reshape(w,[1,Dim_N^2])];
%-------Initial Gauss---------------------
g0 = [0.3,0.3]; w0 = [1,0; 0, 1]; kappa0 = [0.1, 0.1];
para0 = [gT, kappa, reshape(w,[1,Dim_N^2])];
para_opt = lsqcurvefit(FunModel(para0,x),para0,x,J_aim); % lsqcurvefit fitting method
%-------Fitting Model---------------------
function [J_mod] = FunModel(para,x)
global Dim_N
gT = para(1:Dim_N);
kappa = para(Dim_N+1:2*Dim_N);
w = zeros(Dim_N);
%-------Reconstruct the w matrix----------
point = 0;
for index = 2*Dim_N+1: length(para)
point = point + 1;
i = fix( (point-1)/Dim_N ) + 1;
j = point - (i-1)*Dim_N;
w(i,j) = para(index);
end
%-------My fitting model "J_mod"----------
J_mod = zeros(1,length(x));
g = transpose(gT);
Ht = w - 0.5i*diag(kappa);
for i=1:length(x)
temp = Ht - x(i)*eye(Dim_N);
J_mod(i) = imag( gT*inv(temp)*g ); % J_mod = imag( g^T.(1/(Ht-x)).gT )
end
end
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
So my question is that why is Matlab telling me that the code is wrong? How can I fix my code and return the fitting parameters I want?
Any help will be appreciated. Thanks!

Answers (1)

Vaibhav
Vaibhav on 17 Apr 2024
Hi Siwei
The error is due to lsqcurvefit expecting a function handle as its first input.
Here is a way to modify the code:
  1. Define FunModel as a separate function or as an anonymous function that accepts the parameters and the independent variable (x) as inputs and returns the dependent variable (J_mod).
  2. Pass a handle to this function as the first argument to lsqcurvefit.
Here is a code snippet to help you get started:
global Dim_N
Dim_N = 2;
%--------Objective Function (Curve)---------------
x = linspace(1.4,1.9,1000);
J_aim = 0.01./((x-1.6).^2+0.01^2)+0.05./((x-1.7).^2+0.05^2);
plot(x,J_aim);
hold on
%-------Fitting Parameters----------------
gT = [0.5,0.2];
g = transpose(gT);
w = [1.6,0 ; 0, 1.7];
kappa = [0.01,0.05];
%-------Reshape these Parameters----------
para = [gT, kappa, reshape(w,[1,Dim_N^2])];
%-------Initial Gauss---------------------
g0 = [0.3,0.3]; w0 = [1,0; 0, 1]; kappa0 = [0.1, 0.1];
para0 = [g0, kappa0, reshape(w0,[1,Dim_N^2])]; % Fixed to use initial guesses
% Define the model function as an anonymous function
FunModel = @(para,x)modelFunction(para, x);
% Use lsqcurvefit with the function handle
para_opt = lsqcurvefit(FunModel, para0, x, J_aim);
Solver stopped prematurely. lsqcurvefit stopped because it exceeded the function evaluation limit, options.MaxFunctionEvaluations = 8.000000e+02.
%-------Fitting Model---------------------
function J_mod = modelFunction(para, x)
global Dim_N
gT = para(1:Dim_N);
kappa = para(Dim_N+1:2*Dim_N);
w = zeros(Dim_N);
%-------Reconstruct the w matrix----------
point = 0;
for index = 2*Dim_N+1: length(para)
point = point + 1;
i = fix( (point-1)/Dim_N ) + 1;
j = point - (i-1)*Dim_N;
w(i,j) = para(index);
end
%-------My fitting model "J_mod"----------
J_mod = zeros(1,length(x));
g = transpose(gT);
Ht = w - 0.5i*diag(kappa);
for i=1:length(x)
temp = Ht - x(i)*eye(Dim_N);
J_mod(i) = imag( gT*(temp\g) ); % Corrected to use matrix left division
end
end

Categories

Find more on Interpolation in Help Center and File Exchange

Products


Release

R2020b

Community Treasure Hunt

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

Start Hunting!