我有实数值的方阵,我想将低次多项式或其他简单函数拟合到它们。这是一个玩具示例矩阵:
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 库)是否有某种方法可以做到这一点?
最佳答案
内置工具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)
说明:
- 列表
Degrees
指示模型中使用的单项式:这里它们是常量row ** 0 * col ** 0
,线性row * *1 * col**0
和row**0 * col**1
以及二次方程。 basis
是通过在方形网格上评估这些单项式而形成的。lstsq
通过基本元素的线性组合找到适合M
的最小二乘法。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]]
通过将它们添加到基础
中,可以将其推广到多项式以外的函数:例如np.outer(np.sin(row), np.cos(col)).ravel()
会将 sin(row)*cos(col)
项添加到模型。
(我不调用变量 x 和 y,因为矩阵坐标的垂直水平顺序如何映射到 x-y 坐标的水平垂直顺序常常令人困惑。)
关于python - 如何将二维曲线拟合到矩阵,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51564228/