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

25 visualizzazioni (ultimi 30 giorni)
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!

Risposte (1)

Vaibhav
Vaibhav il 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

Categorie

Scopri di più su Interpolation in Help Center e File Exchange

Prodotti


Release

R2020b

Community Treasure Hunt

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

Start Hunting!

Translated by