我有在四个时间点(t)内测量的三个浓度(c)的数据(y)。
因此数据将像:
在c1下:y11,y12,y13,y14(在4个时间点测量)
在c2:y21,y12,y23,y24下
在c3下:y31,y32,y33,y34
我想做的是通过同时拟合所有浓度不同的所有这些数据度量来估计两个参数c
和d
。
但是,其中一些值为NaN。例如,
在c2:y21,y12,NaN,NaN下
在c3下:y31,y32,y33,NaN
这是我编写的Matlab代码。
%C contains the different concentration values (c1,c2,c3)
[fittedVals,errorVals]=lsqcurvefit(@(xEstimate,thours)model(xEstimate,t,C),initial,t,y,lb,ub);
function output= model(xEstimate,t,C)
intVals=repmat(10^5,3,1);%initial value of the ODE system
[~,values] = ode45(@(t,y)Equations(t,y,C),t,intVals);
function s=Equations(~,y,para)
a=0.25;
b=-0.1;
k=xEstimate(1);
d=xEstimate(2);
concentration=para;%different concentrations
s=zeros(3,1);
s(1)=a*y(1)-y(1)*(((a-b)*(concentration(1)/k).^d)/((concentration(1)/k).^d-(b/(a))));
s(2)=a*y(2)-y(2)*(((a-b)*(concentration(2)/k).^d)/((concentration(2)/k).^d-(b/(a))));
s(3)=a*y(3)-y(3)*(((a-b)*(concentration(3)/k).^d)/((concentration(3)/k).^d-(b/(a))));
end
output=values;
end
当数据不是NaN但缺少数据时,此代码将起作用,它会给出如下错误:
目标函数在初始点返回未定义的值。 lsqcurvefit无法继续。
在这里我该怎么解决?我应该将时间和y数据作为单元格数组输入吗?
如果是这样,我不太了解如何更改代码以使用单元格数组。
任何帮助表示赞赏。
答案 0 :(得分:1)
您可以使用lsqnonlin
代替lsqcurvefit
。这使您在想要最小化的误差向量上具有更大的灵活性。
您可以确定每种浓度的每次测量的误差,然后将它们组合到要最小化的较大误差向量上。一个简单的例子是具有变化的幅度,频率和相位的正弦模型。假设我们知道相位,并想要找到振幅和频率。
模型是:
function y = model(t, A, w, phi)
y = A.*sin(w.*t+phi);
end
拟合过程的误差函数将获取测量数据和已知参数。确定某个参数集(由y_estimated
给定)的lsqnonlin
,并用测量值y_meas
确定误差。对所有不同的浓度执行此操作,然后合并到一个误差向量中。由于y_meas
中的某些值为NaN,而您想忽略它们,因此请从误差向量中将其删除。
function err = errorFun(params, y_meas, t, phi)
% get w and phi from params
A = params(1:3);
w = params(4:6);
% simulate model with params to estimate
yest = model(t, A, w, phi);
% determine error vector
err = y_meas-yest;
err = err(:); % make one vector
err(isnan(err)) = []; % remove NaNs
end
示例:
t = 0:0.5:4*pi;
A = rand(3,1);
w = rand(3,1);
phi = rand(3,1);
y_true = A.*sin(w.*t+phi); % three sinusoids
% measured data
y_meas = y_true;
y_meas(randi([1 numel(y_meas)], 10,1)) = NaN; % set some values to NaN
% optimize
% p = [A;w];
p0 = [A;w;]+0.1; % small deviation from initial parameters, for the example
[p_estimated,a] = lsqnonlin(@(p) errorFun(p,y_meas,t,phi), p0);
A_est = p_estimated(1:3);
w_est = p_estimated(4:6);
disp([A A_est w w_est])