2017-04-25 962 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

相關問題