【问题标题】:How to fit data with piecewise linear function in matlab with some constraints on slope如何在matlab中用分段线性函数拟合数据,对斜率有一些限制
【发布时间】:2017-04-25 06:05:29
【问题描述】:

我正在尝试为我的 (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)

【问题讨论】:

    标签: matlab


    【解决方案1】:

    创建分段函数的关键是将if 条件替换为矢量化&gt;。通过在某个数组x 上调用y = x &gt; 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 维的:第一个元素是从零开始的恒定偏移量,第二个元素是角点,第三个和第四个元素是两个斜率。

    通过将theta(3).*xdataxdata&lt;=theta(2) 的结果相乘,对于xdata 中小于theta(2) 的每个点,您将得到theta(3).*xdata,对于所有其他点,您将得到0

    那么,调用lsqcurvefit就这么简单

    >> theta = lsqcurvefit(fun, [0; 15; 0; 1], xdata, ydata)
    
    theta =
    
       18.3793
       17.9639
       -0.0230
        0.9943
    

    lsqcurvefit 函数还允许您为要估计的变量指定下限lb 和上限ub。对于您不想指定界限的变量,您可以使用例如inf 绑定。为了确保您的a1a2,即theta(3)theta(4) 是正数,我们可以将下限指定为[-inf, -inf, 0, 0]

    但是,lsqcurvefit 函数不允许您添加约束 a2 &gt; a1(或任何线性不等式约束)。在示例数据中,这个约束可能甚至没有必要,因为这从数据中很明显。否则,一个可能的解决方案是将a2 替换为a1 + da,并为da 使用0 的下限。这可以确保a2 &gt;= 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
    

    【讨论】:

    • 非常感谢您的详尽解释!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-09
    • 1970-01-01
    • 2017-10-10
    相关资源
    最近更新 更多