18

我有离散的规则网格a,b点及其相应的c值,我进一步对其进行插值以获得平滑曲线。现在从插值数据中,我进一步想为曲线拟合创建一个多项式方程。如何在多项式中拟合 3D 图?

我尝试在 MATLAB 中执行此操作。我在 MATLAB (r2010a) 中使用曲面拟合工具箱对 3 维数据进行曲线拟合。但是,如何在 MATLAB/MAPLE 或任何其他软件中找到最适合一组数据的公式。有什么建议吗?同样最有用的是一些真实的代码示例,PDF文件,网络等。

这只是我数据的一小部分。

a = [ 0.001 .. 0.011];

b = [1, .. 10];

c = [ -.304860225, .. .379710865]; 

提前致谢。

4

3 回答 3

21

要将曲线拟合到一组点上,我们可以使用普通的最小二乘回归。MathWorks有一个解决方案页面描述了该过程。

例如,让我们从一些随机数据开始:

% some 3d points
data = mvnrnd([0 0 0], [1 -0.5 0.8; -0.5 1.1 0; 0.8 0 1], 50);

正如@BasSwinckels所示,通过构造所需的设计矩阵,您可以使用mldividepinv解决表示为的超定系统Ax=b

% best-fit plane
C = [data(:,1) data(:,2) ones(size(data,1),1)] \ data(:,3);    % coefficients

% evaluate it on a regular grid covering the domain of the data
[xx,yy] = meshgrid(-3:.5:3, -3:.5:3);
zz = C(1)*xx + C(2)*yy + C(3);

% or expressed using matrix/vector product
%zz = reshape([xx(:) yy(:) ones(numel(xx),1)] * C, size(xx));

接下来我们将结果可视化:

% plot points and surface
figure('Renderer','opengl')
line(data(:,1), data(:,2), data(:,3), 'LineStyle','none', ...
    'Marker','.', 'MarkerSize',25, 'Color','r')
surface(xx, yy, zz, ...
    'FaceColor','interp', 'EdgeColor','b', 'FaceAlpha',0.2)
grid on; axis tight equal;
view(9,9);
xlabel x; ylabel y; zlabel z;
colormap(cool(64))

1st_order_polynomial


A如前所述,我们可以通过向自变量矩阵( in Ax=b)添加更多项来获得高阶多项式拟合。

假设我们想要拟合一个具有常数项、线性项、交互项和平方项 (1, x, y, xy, x^2, y^2) 的二次模型。我们可以手动执行此操作:

% best-fit quadratic curve
C = [ones(50,1) data(:,1:2) prod(data(:,1:2),2) data(:,1:2).^2] \ data(:,3);
zz = [ones(numel(xx),1) xx(:) yy(:) xx(:).*yy(:) xx(:).^2 yy(:).^2] * C;
zz = reshape(zz, size(xx));

统计工具箱中还有一个辅助函数x2fx,可帮助构建几个模型订单的设计矩阵:

C = x2fx(data(:,1:2), 'quadratic') \ data(:,3);
zz = x2fx([xx(:) yy(:)], 'quadratic') * C;
zz = reshape(zz, size(xx));

最后polyfitn,John D'Errico 在 File Exchange 上提供了一个出色的功能,可让您指定所涉及的各种多项式顺序和项:

model = polyfitn(data(:,1:2), data(:,3), 2);
zz = polyvaln(model, [xx(:) yy(:)]);
zz = reshape(zz, size(xx));

2nd_order_polynomial

于 2013-09-06T00:54:27.053 回答
3

文件交换上可能有一些更好的功能,但手动完成的一种方法是:

x = a(:); %make column vectors
y = b(:);
z = c(:);

%first order fit
M = [ones(size(x)), x, y];
k1 = M\z; 
%least square solution of z = M * k1, so z = k1(1) + k1(2) * x + k1(3) * y

同样,您可以进行二阶拟合:

%second order fit
M = [ones(size(x)), x, y, x.^2, x.*y, y.^2];
k2 = M\z;

对于您提供的有限数据集,这似乎存在数值问题。键入help mldivide以获取更多详细信息。

要在一些常规网格上进行插值,您可以这样做:

ngrid = 20;
[A,B] = meshgrid(linspace(min(a), max(a), ngrid), ...
                 linspace(min(b), max(b), ngrid));
M = [ones(numel(A),1), A(:), B(:), A(:).^2, A(:).*B(:), B(:).^2];
C2_fit = reshape(M * k2, size(A)); % = k2(1) + k2(2)*A + k2(3)*B + k2(4)*A.^2 + ...

%plot to compare fit with original data
surfl(A,B,C2_fit);shading flat;colormap gray
hold on
plot3(a,b,c, '.r')

可以使用下面 TryHard 给出的公式进行三阶拟合,但是当阶数增加时,公式很快就会变得乏味。最好编写一个可以构造Mgiven的函数x,如果您必须多次这样做。yorder

于 2013-08-31T20:57:46.150 回答
2

这听起来更像是一个哲学问题,而不是具体的实现,特别是比特 - “如何找到适合一组数据的公式以发挥最大优势?” 根据我的经验,这是您必须根据您要实现的目标做出的选择。

什么对你来说是“最好的”?对于数据拟合问题,您可以继续添加越来越多的多项式系数并获得更好的 R^2 值……但最终会“过度拟合”数据。高阶多项式的一个缺点是超出了您用来拟合响应面的样本数据范围的行为 - 它可能会迅速向某个疯狂的方向发展,这可能不适合您尝试建模的任何内容.

您是否深入了解您正在安装的系统/数据的物理行为?这可以用作用于创建数学模型的方程组的基础。我的建议是使用您可以摆脱的最经济(简单)的模型。

于 2013-09-01T11:33:51.493 回答