如何将2D曲线拟合到矩阵

时间:2018-07-27 19:14:47

标签: python numpy scipy curve-fitting

我有一个实数值的平方矩阵,并且我想为它们拟合低阶多项式或其他简单函数。这是一个玩具示例矩阵:

M = [[ 0.63,  2.58,  8.7 , 18.17, 32.97],
     [ 3.97,  4.42, 11.9 , 19.88, 34.74],
     [ 7.75, 10.68, 14.11, 24.11, 34.99],
     [15.75, 10.86, 10.72, 24.99, 42.02],
     [16.57,  7.48, 16.91, 42.33, 48.43]]

我想拟合一个函数,以便当我给它(i,j)时,它计算出的值大约为M[i,j]

scipy或numpy(或任何其他python库)中有某种方法可以做到这一点吗?

1 个答案:

答案 0 :(得分:2)

内置工具RectBivariateSpline为2D网格数据提供了平滑的近似值(平滑度由参数s控制)。但是,您似乎想要一个适合数据的简单公式;花键不是。但是您可以按照以下基本原则建立最小二乘拟合(我假设M是NumPy 2D数组):

degrees = [(0, 0), (1, 0), (0, 1), (2, 0), (1, 1), (0, 2)]   # degrees to use
row = np.arange(M.shape[0])
col = np.arange(M.shape[1])
basis = np.array([np.outer(row**deg[0], col**deg[1]).ravel() for deg in degrees])
coeffs = np.linalg.lstsq(basis.T, M.ravel(), rcond=None)[0]
fit = coeffs.dot(basis).reshape(M.shape)

说明:

  1. 列表degrees指出了模型中使用的单项式:这里是常数row**0 * col**0,线性row**1 * col**0row**0 * col**1以及二次项。
  2. basis是通过在正方形网格上评估这些单项式项而形成的。
  3. lstsq通过基础元素的线性组合找到与M拟合的最小二乘法。
  4. fit是重构,它是通过将基本元素与我们发现的系数相结合而获得的。

在此示例中,系数为[3.46017143, 1.26657143, -3.31471429, 0.38585714, 0.2627, 2.64942857],这意味着模型为

3.46017143 + 1.26657143*row - 3.31471429*col + 0.38585714*row**2 + 0.2627*row*col + 2.64942857*col**2

鉴于数据中的各种突然跳跃,拟合是合理的。例如。 M的最后一行7.48真的很难适应任何事物,并且那里还有其他奇怪之处。

  [[ 3.46017143,  2.79488571,  7.42845714, 17.36088571, 32.59217143],
   [ 5.1126    ,  4.71001429,  9.60628571, 19.80141429, 35.2954    ],
   [ 7.53674286,  7.39685714, 12.55582857, 23.01365714, 38.77034286],
   [10.7326    , 10.85541429, 16.27708571, 26.99761429, 43.017     ],
   [14.70017143, 15.08568571, 20.77005714, 31.75328571, 48.03537143]]

通过将多项式添加到basis,可以将其推广到多项式以外的其他函数: np.outer(np.sin(row), np.cos(col)).ravel()将向模型添加sin(row)*cos(col)项。

(我不叫变量x和y,因为它经常使矩阵坐标的垂直-水平顺序映射为x-y坐标的水平-垂直顺序令人困惑。)