我有一个实数值的平方矩阵,并且我想为它们拟合低阶多项式或其他简单函数。这是一个玩具示例矩阵:
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库)中有某种方法可以做到这一点吗?
答案 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)
说明:
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]]
通过将多项式添加到basis
,可以将其推广到多项式以外的其他函数: np.outer(np.sin(row), np.cos(col)).ravel()
将向模型添加sin(row)*cos(col)
项。
(我不叫变量x和y,因为它经常使矩阵坐标的垂直-水平顺序映射为x-y坐标的水平-垂直顺序令人困惑。)