Lsqcurvefit 告诉我数据大小不一样:不准确?
Lsqcurvefit tells me data is not the same size: Inaccurate?
我正在尝试获取使我的曲线适合我的数据的参数。
脚本 1:执行拟合命令。
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(函数函数)
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
我的实验数据、时间点和objective函数结果都是一样大小的:
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;**
为什么会这样?
inaccurate?
不是。该代码完全按照编程的方式工作,并给出了预期的错误。
lsqcurvefit
需要您的函数 Model1_Results
输出一个与您的 ydata 向量 tumor_vol_norm
大小相同的向量,它有 5 个元素。
但是,ode45
并不总是输出 5 元素向量。通常通过优化,被最小化的函数对于优化器尝试的某些值会失败。您需要防止这些并替换不会阻止代码工作的值,但表明当前正在试用的参数集是 bad.
对于大多数优化例程,例如 fmincon
和 fminunc
,其中您指定的函数是实际成本,那么这相对简单,只需将代码包装在 try-catch
块,如果失败输出一个比较大的成本。这告诉优化器这些不是好的值,并继续在解决方案的其他地方寻找 space。
对于 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
我正在尝试获取使我的曲线适合我的数据的参数。
脚本 1:执行拟合命令。
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(函数函数)
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
我的实验数据、时间点和objective函数结果都是一样大小的:
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;**
为什么会这样?
inaccurate?
不是。该代码完全按照编程的方式工作,并给出了预期的错误。
lsqcurvefit
需要您的函数 Model1_Results
输出一个与您的 ydata 向量 tumor_vol_norm
大小相同的向量,它有 5 个元素。
但是,ode45
并不总是输出 5 元素向量。通常通过优化,被最小化的函数对于优化器尝试的某些值会失败。您需要防止这些并替换不会阻止代码工作的值,但表明当前正在试用的参数集是 bad.
对于大多数优化例程,例如 fmincon
和 fminunc
,其中您指定的函数是实际成本,那么这相对简单,只需将代码包装在 try-catch
块,如果失败输出一个比较大的成本。这告诉优化器这些不是好的值,并继续在解决方案的其他地方寻找 space。
对于 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