我正在尝试为我的(xdata, ydata)
数据拟合分段线性方程。我必须面对挑战,第一个是如何以函数句柄的形式转换方程,第二个是如何在斜率上设置约束,例如a2>a1
和a2>0
和a1>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)
答案 0 :(得分:2)
创建分段函数的关键是用向量化if
替换>
条件。通过在某个数组y = x > 1
上调用x
,输出y
将是一个与x
大小相同的数组,如果相应的元素具有逻辑True
在x
中大于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
lsqcurvefit
函数还允许您为要估计的变量指定下限>> theta = lsqcurvefit(fun, [0; 15; 0; 1], xdata, ydata)
theta =
18.3793
17.9639
-0.0230
0.9943
和上限lb
。对于您不想指定边界的变量,您可以使用例如ub
受约束。为确保您的inf
和a1
,即a2
和theta(3)
为正,我们可以将下限指定为theta(4)
。
但是,[-inf, -inf, 0, 0]
函数不允许您添加约束lsqcurvefit
(或任何线性不等式约束)。在示例数据中,这种约束可能甚至不必要,因为从数据中可以明显看出这一点。否则,可能的解决方案是将a2 > a1
替换为a2
,并使用a1 + da
的下限0
。这样可以确保da
。
a2 >= a1