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.

对于大多数优化例程,例如 fminconfminunc,其中您指定的函数是实际成本,那么这相对简单,只需将代码包装在 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