使用 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
我尝试拟合分段线性函数
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