如何利用matlab中的分段线性函数拟合数据,并对斜率进行约束

时间:2017-04-25 06:05:30

标签: matlab

我正在尝试为我的(xdata, ydata)数据拟合分段线性方程。我必须面对挑战,第一个是如何以函数句柄的形式转换方程,第二个是如何在斜率上设置约束,例如a2>a1a2>0a1>0

xdata = 5:0.2:40;
ydata = max(18,xdata) + 0.5*randn(size(xdata));
a1 = (y1-y0)/(x1-x0); a2 = (y2-y1)/(x2-x1);
if x < x1;
    f(x) = y0 + a1*(x-x0);
else
    f(x) = y0 + a1*(x1-x0) + a2*(x-x1);
end
FU = matlabFunction(f)
x0 = 5; y0 = 16;
x = lsqcurvefit(FU,[x0,y0],xdata,ydata)

enter image description here

1 个答案:

答案 0 :(得分:2)

创建分段函数的关键是用向量化if替换>条件。通过在某个数组y = x > 1上调用x,输出y将是一个与x大小相同的数组,如果相应的元素具有逻辑Truex中大于1,否则为False。例如

>> x = [1, 2, 4; 3, 1, 2];
>> y = x > 2
y =

  2×3 logical array

   0   0   1
   1   0   0

您可以利用它来创建分段线性函数,如下所示:

>> fun = @(theta, xdata) theta(1) + ...
                         (xdata<=theta(2)) .* theta(3) .* xdata + ...
                         (xdata>theta(2)) .* (theta(3) * theta(2) + ...
                                              theta(4) .* (xdata-theta(2)))

参数向量theta将是4维的:第一个元素是从零开始的常量偏移,第二个元素是角点,第三个和第四个元素是两个斜率。

通过将theta(3).*xdata乘以xdata<=theta(2)的结果,theta(3).*xdata中每个小于xdata的点theta(2)和{{1}对于所有其他人。

然后,调用lsqcurvefit就像

一样简单
0

Resulting Plot

lsqcurvefit函数还允许您为要估计的变量指定下限>> theta = lsqcurvefit(fun, [0; 15; 0; 1], xdata, ydata) theta = 18.3793 17.9639 -0.0230 0.9943 和上限lb。对于您不想指定边界的变量,您可以使用例如ub受约束。为确保您的infa1,即a2theta(3)为正,我们可以将下限指定为theta(4)

但是,[-inf, -inf, 0, 0]函数不允许您添加约束lsqcurvefit(或任何线性不等式约束)。在示例数据中,这种约束可能甚至不必要,因为从数据中可以明显看出这一点。否则,可能的解决方案是将a2 > a1替换为a2,并使用a1 + da的下限0。这样可以确保da

a2 >= a1