Lsqcurvefit告诉我数据大小不一样:不准确?

时间:2018-03-16 18:27:07

标签: matlab curve-fitting

我正在尝试获取适合我的曲线的参数到我的数据。

脚本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; **

为什么会这样?

1 个答案:

答案 0 :(得分:2)

inaccurate? 。代码完全按照编程的方式工作,并给出预期的错误。

lsqcurvefit要求您的函数Model1_Results输出与ydata向量tumor_vol_norm大小相同的向量,该向量包含5个元素。

但是,ode45并不总是输出5个元素向量。通常在优化时,对于优化程序尝试的某些值,最小化的函数将失败。您需要保护它们并替换不会阻止代码工作的值,但指示当前正在测试的参数集错误

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