Ошибка lsqnonlin при достижении значений с помощью вложенных функций - PullRequest
1 голос
/ 20 сентября 2019

Я хочу подогнать два параметра, используя lsqnonlin.Я настроил свою систему ODE и хочу решить их с помощью моих новых параметров, которые будут найдены после выполнения lsqnonlin.

function [dcdt] = CSTRSinSeries(t,c,par)  

for i=1:par.n

    if i==1

    dcdt(i) = 1/par.tau_per_tank * (par.c0-c(i))+par.kf*(par.c0_meth-c(i))- ...
    par.kb*c(i).^2;

    else 

    dcdt(i) = 1/par.tau_per_tank * (c(i-1)-c(i))+par.k*(par.c0_meth-c(i))- ...
    par.kb*c(i).^2;
    end

end
  dcdt = dcdt';
end

% fitcrit function 
function error = fitcrit(curve_fit_parameters,time_exp,conc_exp, par, init)
[time_model_fit,conc_model_fit] = ode45(@(t,c) CSTRSinSeries(t,c,par),time_exp,init,[]);
error = (conc_exp-conc_model_fit);
end

Я думаю, что проблема связана с тем фактом, что мои параметры находятся вПараметр struct Par и что я не хочу соответствовать всем этим параметрам, но только на основе двух из них.Это мой основной скрипт для выполнения подгонки кривой:

% initial guesses for model parameters, no. of indeces is number of fitted % parameters 
k0 = [0.028 0.002];
% lower and upper bounds for model parameters, this can be altered
LB = [0.00 0.00];
UB = [Inf Inf];
% Set up fitting options
options = optimset('TolX',1.0E-6,'MaxFunEvals',1000);
% Perform nonlinear least squares fit (note that we store much more
% statistics than just the final fitted parameters)
[curve_fit_parameters,RESNORM,RESIDUAL,EXITFLAG,OUTPUT,LAMBDA,JACOBIAN] = ...
lsqnonlin(@(k) fitcrit(k,time_exp, conc_exp, par, init),k0,LB,UB,options);

Код теперь не выдает ошибку, однако выходные данные моих curve_fit_parameters теперь совпадают с моими начальными значениями (также, когда я меняю свои начальные значениязначение остается неизменным).Ошибка:

>> PackedBed
Initial point is a local minimum.
Optimization completed because the size of the gradient at the initial point 
is less than the default value of the optimality tolerance.
<stopping criteria details>

Критерий остановки дает относительную оптимальность первого порядка 0,00 + 00, поэтому я думаю, что изменения параметров lsqnonlin не влияют на мою ошибку.Я думаю, что ошибкой является функция lsqnonlin, где я ссылаюсь на 'k' вместо 'par.kb и par.kf'.Тем не менее, я не знаю, как ссылаться на них, поскольку они являются вложенными функциями.Замена 'k' на 'par.kb, par.kf' дает мне ошибку: неожиданный оператор matlab.

Может ли кто-нибудь помочь мне с моей проблемой?

1 Ответ

0 голосов
/ 20 сентября 2019

Как предложил Адриан в комментариях, вы можете легко сделать копию структуры par в вашей функции fitcrit и назначить параметры для оптимизации этой структуре par_tmp.Тогда функция fitcrit становится:

function error = fitcrit(curve_fit_parameters,time_exp,conc_exp, par, init)
    par_tmp = par;
    par_tmp.kf = curve_fit_parameters(1); % change to parameters you need to fit
    par_tmp.kb = curve_fit_parameters(2);

    [time_model_fit,conc_model_fit] = ode45(@(t,c) odefun(t,c,par_tmp),time_exp,init,[]); % pass par_tmp to ODE solver
    error = (conc_exp-conc_model_fit);
end

В скрипте, вызывающем lsqnonlin, вам придется изменить структуру par, чтобы включить конвергентное решение подмножества параметров для оптимизации:

% initial guesses for model parameters, no. of indeces is number of fitted % parameters 
k0 = [0.028 0.002];
% lower and upper bounds for model parameters, this can be altered
LB = [0.00 0.00];
UB = [Inf Inf];
% Set up fitting options
options = optimset('TolX',1.0E-6,'MaxFunEvals',1000);
% Perform nonlinear least squares fit (note that we store much more
% statistics than just the final fitted parameters)
[curve_fit_parameters,RESNORM,RESIDUAL,EXITFLAG,OUTPUT,LAMBDA,JACOBIAN] = ...
    lsqnonlin(@(k) fitcrit(k,time_exp, conc_exp, par, init),k0,LB,UB,options);

% make par_final
par_final = par;
par_final.kf = curve_fit_parameters(1);
par_final.kb = curve_fit_parameters(2);
```
...