且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何在具有一定坡度约束的Matlab中使用分段线性函数拟合数据

更新时间:2023-11-25 18:58:16

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

The key to creating the piece-wise function is to replace the if condition by a vectorized >. By calling y = x > 1 on some array x, the output y will be an array of the same size as x, with a logical True if the corresponding element in x is larger than 1, and a False otherwise. For example

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

  2×3 logical array

   0   0   1
   1   0   0

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

You can utilize this to create a piece-wise linear function, as follows:

>> 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维的:第一个元素是从零开始的恒定偏移量,第二个元素是拐角点,第三个和第四个元素是两个斜率.

The parameter vector theta will be 4-dimensional: the first element is a constant offset from zero, the second element is the corner point, and the third and fourth elements are the two slopes.

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

By multiplying theta(3).*xdata with the result of xdata<=theta(2), you get theta(3).*xdata for each point in xdata which is smaller than theta(2), and 0 for all others.

然后,调用 lsqcurvefit 很简单

Then, calling lsqcurvefit is as simple as

>> 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].

The lsqcurvefit function also allows you to specify a lower bound lb and an upper bound ub for the variables you want to estimate. For variables where you don't want to specify a bound, you can use e.g. inf as bound. To make sure that your a1 and a2, i.e. theta(3) and theta(4) are positive, we can specify the lower bound to be [-inf, -inf, 0, 0].

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

However, the lsqcurvefit function doesn't allow you to add the constraint a2 > a1 (or any linear inequality constraints). In the example data, this constraint probably isn't even necessary as this is obvious from the data. Otherwise, a possible solution would be to replace a2 by a1 + da, and use a lower bound of 0 for da. This makes sure that 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