的关键在于创造分段功能是通过向量化>
更换if
条件。通过在某个阵列x
上调用y = x > 1
,输出y
将是与x
相同尺寸的阵列,如果x
中的对应元素大于1,则逻辑为True
,否则为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维的参数:所述第一元件是一个常数偏离零,第二个元素是角点,第三个和第四个元素是两个斜坡。
通过与xdata<=theta(2)
结果乘以theta(3).*xdata
,你theta(3).*xdata
在xdata
每个点比theta(2)
小,0
为所有其他人。
然后调用lsqcurvefit
很简单,只要
>> theta = lsqcurvefit(fun, [0; 15; 0; 1], xdata, ydata)
theta =
18.3793
17.9639
-0.0230
0.9943
的lsqcurvefit
功能还允许您指定一个下界lb
和要估计的变量的上限ub
。对于不想指定边界的变量,可以使用例如作为绑定的inf
。为确保您的a1
和a2
,即theta(3)
和theta(4)
都是正数,我们可以指定下限为[-inf, -inf, 0, 0]
。
但是,lsqcurvefit
函数不允许添加约束a2 > a1
(或任何线性不等式约束)。在示例数据中,这个约束可能甚至不是必需的,因为这从数据中是显而易见的。否则,可能的解决方案是将a2
替换为a1 + da
,并且对于da
使用0
的下限。这确保了a2 >= a1
。
>> fun = @(theta, xdata) theta(1) + ...
(xdata<=theta(2)) .* theta(3) .* xdata + ...
(xdata>theta(2)) .* (theta(3) * theta(2) + ...
(theta(3)+theta(4)) .* (xdata-theta(2)))
>> theta = lsqcurvefit(fun, [0; 15; 0; 1], xdata, ydata, [-Inf, -Inf, 0, 0], [])
theta =
18.1162
18.1159
0.0000
0.9944
非常感谢您的回答,并给出了详尽的解释! – Alemex