如何提高3D数据的表面拟合度?

问题描述

我一直在使用scipy将3d数据拟合到表面,该表面被定义为多项式函数。但是结果看上去并不十分接近数据。如何改善拟合度?

import numpy as np
from scipy.optimize import curve_fit

# import my data
data = my_data_matrix

# define polynomial function
def func(X,A,B,C,D,E,F):
    # unpacking the multi-dim. array column-wise,that's why the transpose
    x,y,z = X.T

    return (A * x ** 2) + (B * y ** 2) + (C * x * y) + (D * x) + (E * y) + F

# fit the polynomial function to the 3d data
popt,_ = curve_fit(func,data,data[:,2])


# print coefficients of the polynomial function,i.e.,E and F
from string import ascii_uppercase
for i,j in zip(popt,ascii_uppercase):
    print(f"{j} = {i:.3f}")

在这种情况下,我得到了:

A = 0.903  
B = 0.022  
C = 0.325  
D = -362.140  
E = -52.875  
F = 31057.352

将拟合的曲面与原始数据(散点)进行比较:

plot of the surface fit result

解决方法

您确定您的数据来自于二次曲面并且没有任何噪声吗?此curve_fit函数基本上与line of best fit类似。最合适的线是当您将一些数据散布成一条线(但不完全是一条线)并且您希望通过数据找到最接近该数据的线时。定义“紧密度”的方式是针对每个数据点,找到该点实际所在的位置与直线预测的位置之间的差异,将其平方,然后为所有数据点求和。最合适的线是将其最小化的线。

现在,如果数据比较嘈杂(几乎总是这样),那么最佳拟合线将不会精确穿过每个点,而是应该接近。如果您有充分的理由认为您的数据具有线性关系,那么这很好,并且不准确之处会告诉您数据有多嘈杂。

将其扩展到您的示例中,您试图找到x和y均为二次方的最佳曲面以适合您的数据。如果您有理由相信生成此数据的过程是二次的,那么您在图表中看到的差异就是数据的噪声。

但是,可能是您的数据确实来自三次或更高级的数据。您可以尝试这些类型的功能,但不要太着急,通常来自物理过程的数据不是太高阶。过度使用功能基本上称为过度拟合。高阶函数将减少数据上的错误,甚至可以转到可以“完全”预测所有数据的点(通过使用度数等于数据点数的多项式)。但是,如果您过度拟合(=太高阶),那么当您获得新数据时,过度拟合模型将比更简单的模型预测更糟糕。