我正在尝试获取适合我的曲线的参数到我的数据。
脚本1:执行fit命令。
tumor_Day = [5;8;11.25;17;18];
B0 = rand(6, 1);
[B,Rsdnrm,Rsd,ExFlg,OptmInfo,Lmda,Jmat] = lsqcurvefit(@Model1_Results,B0,tumor_Day,tumor_vol_norm);
功能2:Model1_results.m
function tumorvol = Model1_Results(B, t)
%% Input Parameters
a11 = B(1);
a12 = B(2);
a13 = B(3);
a21 = B(4);
a22 = B(5);
a23 = B(6);
a31 = 1;
a32 = .1;
a41 = 3;
a51 = 3e-3;
C = 0;
tau = 6;
%% Solve ODE
tspan = [5 8 11.25 17 18];
x0 = [1 1 0 0 0];
[t, x] = ode45(@(t, x) liotta_model1(t, x, ...
B(1), B(2), B(3), B(4), B(5), B(6), ...
a31, a32, a41, a51, C , tau), ...
tspan, x0);
tumorvol = x(:,1);
end
功能3:liotta_model1.m(odefunction)
function dxdt = liotta_model1(t, x, ...
a11, a12, a13, a21, a22, a23, a31, a32, a41, a51, ...
C, tau)
b1 = a11*(x(2)/x(1))/(a12 + (x(2)/x(1)));
d1 = a13*(x(1)/x(2))^2;
b2 = (a21*b1)/(a22+b1);
d2 = a23*d1;
dxdt(1) = (b1 - d1)*x(1);
dxdt(2) = (b2 - d2)*x(2);
dxdt(3) = a31*x(2) - a32*x(3);
dxdt(4) = a32*x(3) - a41*x(4);
dxdt(5) = a51*x(4)*heaviside(x(4) - C);
% Convert to column vector as required by ode45
dxdt = dxdt(:);
end
我的实验数据,时间点和目标函数结果都具有相同的大小:
tumor_vol_norm =
1.0000
1.5000
2.6250
3.5000
3.5000
t =
5.0000
8.0000
11.2500
17.0000
18.0000
Model1_Results(B0, t)
ans =
1.0000
1.3142
2.2052
7.2455
9.1094
但我仍然收到此错误:
**矩阵尺寸必须达成一致。
lsqcurvefit / objective出错(第265行) F = F - YDATA; **
为什么会这样?
答案 0 :(得分:2)
inaccurate?
不。代码完全按照编程的方式工作,并给出预期的错误。
lsqcurvefit
要求您的函数Model1_Results
输出与ydata向量tumor_vol_norm
大小相同的向量,该向量包含5个元素。
但是,ode45
并不总是输出5个元素向量。通常在优化时,对于优化程序尝试的某些值,最小化的函数将失败。您需要保护它们并替换不会阻止代码工作的值,但指示当前正在测试的参数集错误。
对于大多数优化例程,例如fmincon
和fminunc
,其中您指定的函数是实际成本,那么这相对简单,并且可能只涉及将代码包装在try-catch
块中如果失败则输出相对较大的成本。这告诉优化器这些不是好的值,并继续寻找解决方案领域的其他地方。
对于lsqcurvefit
,它可能会有点问题,因为你的功能不能直接输出成本。而是输出一个y_hat
值的向量,lsqcurvefit
然后用它来计算成本。
在您的情况下还有一个问题,因为ode45
中的失败只会引发警告,而不是错误。为了解决这个问题,您需要执行以下操作:
function tumorvol = Model1_Results(B, t)
%% Input Parameters
a11 = B(1);
a12 = B(2);
a13 = B(3);
a21 = B(4);
a22 = B(5);
a23 = B(6);
a31 = 1;
a32 = .1;
a41 = 3;
a51 = 3e-3;
C = 0;
tau = 6;
%% Solve ODE
tspan = [5 8 11.25 17 18];
x0 = [1 1 0 0 0];
try
[t, x] = ode45(@(t, x) liotta_model1(t, x,...
B(1), B(2), B(3), B(4), B(5), B(6),...
a31, a32, a41, a51, C , tau),...
tspan, x0);
tumorvol = x(:);
if ~all(size(x)==size(x0))
tumorvol = 1e10*ones(numel(x0),1);
end
catch ME
tumorvol = 1e10*ones(numel(x0),1);
end
end