我想通过以八度音程实现它来理解回归是如何工作的。要检查我的函数是否正确,我将其结果与内置函数polyfit
进行比较。这是我的代码:
p = [0, 1.5 * pi];
function y = f(x)
y = (exp(-4 * sin(4*x)));
end
function c = regress1(x, y, degree)
L = @(j)(arrayfun( @(k)(j^k), (0:degree)));
x_data = [];
for i = x
x_data = [x_data; L(i)];
end
mx = x_data;
my = y';
c = fliplr((pinv(mx' * mx) * mx' * my)');
end
% number of known points
N = 50;
% polynomial degree
D = 20;
% known points
X = linspace(p(1), p(2), N);
Y = arrayfun(@f, X);
% my function
R = regress1(X, Y, D);
% reference function
C = polyfit(X, Y, D);
% test points
W = linspace(p(1), p(2), 1000);
V1 = arrayfun(@(x)(polyval(R,x)), W);
Z = arrayfun(@(x)(polyval(C,x)), W);
clf;
hold on;
fplot(@f, p);
plot(X, Y, '*');
plot(W, V1, '1-');
plot(W, Z, '2-');
hold off;
问题是它适用于小程度(我的程序中的变量D
),但是对于更大的程度,它产生的系数太小。原始函数的图和两个近似值:
原始 - 蓝色,我 - 红色,polyfit - 绿色
我怀疑这部分(pinv(mx' * mx) * mx' * my)'
中的某些内容可能有误。此外,如果我从pinv
更改为inv
,我会得到不同的结果,但更糟。
我做了一些研究,找到了其他一些解决方案,例如,但即使这些程序相似,我也找不到我的错误。
有人可以解释我有什么问题吗?
答案 0 :(得分:1)
对于大D(近似多项式的次数),矩阵会变得病态。您可以尝试使用不同类型的多项式基数来进行回归。对于例如使用Chebyshev多项式代替x,x ^ 2,x ^ 3,...,x ^ D.
如果您居中并扩展数据,则可以获得稍微好一点的结果。基本上,如果您尝试将函数拟合到集合(x,y),则可以使用以下命令重新定义问题:
xn =(x - mean(x))/ std(x)
之后将设置放在(xn,y)上。