使用 MATLAB 使用 SVD 拟合分段线性函数

Fitting piecewise linear function with SVD using MATLAB

我尝试拟合分段线性函数

y=a1*x + a0, for x < 0 and
y=a1*x + a0 + a01, for x > 0

共享相同的坡度。我使用以下使用 MATLAB 反斜杠运算符的方法:

a0 = 1;
a01 = 1.1;
a1 = 0.5;

x= linspace(-1,1, 150);

y = tilt_step(x, a0, a01, a1);
y = y + 0.*rand(size(y));

figure(1); clf;
plot(x, y, '.');

[a0, a01, a1] = fit_tilt_step(x, y, 0.01);

hold on;
plot(x, tilt_step(x, a0, a01, a1), 'r');
grid on

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function y = tilt_step(x, a0, a01, a1)
y = a0 + a1.*x;
fi = find(x>0);
y(fi) = y(fi) + a01;
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [a0, a01, a1] = fit_tilt_step(x, y, separation)

x = x(:);
y = y(:);

my = mean(y);
y = y-mean(y);

fi = find(x<separation);
M = [ones(length(fi), 1) zeros(length(fi), 1) x(fi)];

fi = find(x>separation);
M = [M; ones(length(fi), 1) ones(length(fi), 1) x(fi)];

a = M \ y;

a0 = a(1) + my;
a01 = a(2);
a1 = a(3);

end

该方法适用于 < 150 个数据点。当使用 >= 150 个数据点时,结果有点偏差:

a0 =  1.0362
a01 = 1.0415
a1 =  0.5437

我猜这是一个数值准确性或稳定性问题。有人可以帮助如何重新制定问题以避免这种情况吗?

好吧,那真的很简单:我通过分离参数搞砸了数据点的选择。这是更正后的代码,可以正常工作:

a0 = 1;
a01 = 1.1;
a1 = 0.5;

x= linspace(-1,1, 1500);

y = tilt_step(x, a0, a01, a1);
y = y + 0..*rand(size(y));

figure(1); clf;
plot(x, y, '.');

[a0, a01, a1] = fit_tilt_step(x, y, 0.1);

hold on;
plot(x, tilt_step(x, a0, a01, a1), 'r');
grid on

a0
a01
a1

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function y = tilt_step(x, a0, a01, a1)
y = a0 + a1.*x;
fi = find(x>0);
y(fi) = y(fi) + a01;
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [a0, a01, a1] = fit_tilt_step(x, y, separation)

x = x(:);
y = y(:);

my = 0; % mean(y);
y = y-my;

fi1 = find(x<-separation);
M = [ones(length(fi1), 1) zeros(length(fi1), 1) x(fi1)];

fi2 = find(x>separation);
M = [M; ones(length(fi2), 1) ones(length(fi2), 1) x(fi2)];

a = M \ y([fi1;fi2]);

a0 = a(1) + my;
a01 = a(2);
a1 = a(3);

end