是的,我们可以将问题限制为使用“4x4矩阵”进行计算。即使对于M个数据点的三次最小二乘拟合,也只需要解四个未知数的线性方程组。假设所有的x坐标都不同,则系数矩阵是可逆的,因此原则上可以通过求解系数矩阵的逆来解决该系统。我们假设M大于4,这通常是最小二乘拟合的情况。
这里有一个Maple的写作
Fitting a cubic to data,它几乎完全隐藏了正在解决的细节。一阶最小条件(关于系数的一阶导数作为平方误差的参数)给出了四个线性方程,通常称为
normal equations。
您可以在代码中“组装”这四个方程,然后应用矩阵求逆或更复杂的解决策略。显然,您需要以某种形式存储数据点。一种可能性是两个线性数组,一个用于x坐标,一个用于y坐标,长度均为M,即数据点的数量。
NB: 我将讨论此矩阵组装,以1为基的数组下标。多项式系数实际上是0为基的数组下标更简洁,但是将其重写成使用0为基的下标的C或任何其他语言留给读者作为练习。
正常方程组最容易用矩阵形式表示,通过引用一个Mx4数组A,其条目为x坐标数据的幂:
A(i,j) = 第i个数据点的x坐标的(j-1)次方
让A'表示A的转置,这样A'A就是一个4x4的矩阵。
如果我们让d是包含数据点y坐标(按给定顺序)的长度为M的列,则正常方程组就是这样的:
A'Au = A'd
其中u=[p0,p1,p2,p3]'是具有最小二乘拟合的三次多项式的系数列:
P(x) = p0 + p1 * x + p2 * x ^ 2 + p3 * x ^ 3
你的反对意见似乎集中在存储和/或操作Mx4数组A或其转置方面。因此,我的答案将侧重于如何组装矩阵A'A和列A'd,而无需一次性明确存储所有A。换句话说,我们将隐式地进行指示的矩阵-矩阵和矩阵-向量乘法,以获得一个4x4系统,您可以解决:
Cu = f
如果您考虑条目C(i,j)是A'的第i行与A的第j列的乘积,再加上A'的第i行实际上只是A的第i列的转置,那么应该清楚:
C(i,j) = 所有数据点上的SUM x^(i+j-2)
这当然是使用基于0的下标简化表述的地方之一!
累加矩阵C的条目可能是有意义的,这些条目仅取决于i+j的值,即所谓的
Hankel矩阵,并将它们放入长度为7的线性数组中,例如:
W(k) = 所有数据点上的SUM x^k
其中k = 0,..,6。4x4矩阵C具有“条纹”结构,这意味着只出现这七个值。循环遍历数据点的x坐标列表,可以在W的适当条目中累积每个数据点的每个幂的适当贡献。
类似的策略可用于组装列f = A' d,即循环遍历数据点并累积以下四个求和:
f(k) = 求和(x^k)*y所有数据点
其中k = 0,1,2,3。[当然,在上述总和中,值x,y是公共数据点的坐标]
注意事项:这满足仅使用4x4矩阵的目标。但是,通常尝试避免显式形成正规方程系数矩阵,因为这些矩阵在数值分析中经常被称为病态矩阵。特别是x坐标紧密间隔的情况在尝试通过反转系数矩阵来解决系统时可能会导致困难。
一种更为复杂的解决这些正规方程的方法是使用
正规方程的共轭梯度法,可以通过计算逐个条目的矩阵-向量乘积A u和A' v的代码来实现(使用上述关于A的条目的内容)。
由于其自然的迭代方法,特别是当可以使用略微额外精度计算所需的点积时,共轭梯度法的准确性通常是令人满意的。