2017-04-25 963 views
0

我想为我的(xdata, ydata)数据拟合分段线性方程。我必须面对挑战,第一个问题是如何将函数句柄的形式转换为方程,第二个问题是如何对斜率进行约束,例如a2>a1a2>0a1>0如何用matlab中的分段线性函数拟合数据,斜率有一些限制

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

的关键在于创造分段功能是通过向量化>更换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).*xdataxdata每个点比theta(2)小,0为所有其他人。

然后调用lsqcurvefit很简单,只要

>> theta = lsqcurvefit(fun, [0; 15; 0; 1], xdata, ydata) 

theta = 

    18.3793 
    17.9639 
    -0.0230 
    0.9943 

Resulting Plot

lsqcurvefit功能还允许您指定一个下界lb和要估计的变量的上限ub。对于不想指定边界的变量,可以使用例如作为绑定的inf。为确保您的a1a2,即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 
+0

非常感谢您的回答,并给出了详尽的解释! – Alemex

相关问题