我有一个稀疏的数组,如下所示。有没有一种算法可以用线性意义的值来填补所有空白?即从周围的原始值推导出来的。
我看过双线性插值和双三次插值,但还有其他的吗?
| 1 | 2 | 3 | 4 | 5 | 6 | 7
---------------------------------------------------------------------------------
1 |
2 |
3 | 55
4 | 50 12 6
5 | 45 19
6 | xxx
7 | 35 45 50 yyy
8 |
9 |
10 |
11 |
12 | zzz
13 |
14 |
15 |
例如,我预计xxx在40附近,yyy在50附近。然而zzz可能具有更随机的值。不过请注意:我想填充每一个空格,而不仅仅是xxx、yyy和zzz。并且能够为任何人烟稀少的阵列做到这一点。
这样的算法存在吗?
有一百万种这样的算法。因此,首先你有一些已知值的字典,比如:
known_values = {
(2, 3): 55.0,
(2, 4): 50.0,
(2, 5): 45.0,
(2, 7): 35.0,
(3, 7): 45.0,
(4, 7): 50.0,
(6, 4): 12.0,
(7, 4): 6.0,
(7, 5): 19.0,
}
最简单的方法是说,任何点的值都是所有填充点的加权平均值。将其加权1/距离的平方。所以在上面的例子中,你会有这样的代码:
def interpolate(known_values, p):
total_weight = 0.0
total_sum = 0.0
for q, value in known_values:
if p == q:
return value
d_square = (p[0] - q[0])**2 + (p[1] - q[1])**2
total_weight = total_weight + 1.0 / d_square
total_sum = total_sum + value / d_square
return total_sum/total_weight
只要矩阵中有ANY填充的数据,此解决方案就会起作用。
然而,从你问这个问题的方式来看,你可能想要一个在任何小区域近似线性的平滑插值。一种方法是查找(a, b, c)
,使函数a*x + b*y + c
最小化误差的加权平方和,权重是从所需点到已知点的距离的四次方。(前两个幂撤销了面积的平方,其他两个幂在附近的点更多。)
这里使用最小二乘法来计算误差的原因是数学计算很简单。当a
、b
或c
的微小变化不会使值发生太大变化时,即偏导数为0时,您将精确地最小化。因此,三个偏导数给出了三组线性方程。用3个变量求解3个方程相当容易。
然而,推导过程漫长而混乱。如果你想尝试一下,你应该看看通常的最小二乘法推导,并尝试处理细节。然后尝试实现它。但只有当真的想尝试对远离数据的点进行线性投影时,才可以尝试。
这个问题可以被视为"二元插值"问题,在这个领域有很多研究。您可以在Wiki中搜索"多元插值",并在"二维"部分查找算法。
在各种方法中,双线性/双三次插值需要数据来形成网格,而您的数据却不是这样。Delaunay三角测量法不适合根据您的情况进行外推。反加权距离法易于实现,适用于外推,但结果往往不令人满意。我个人建议使用径向基函数,只要你没有太多的数据点(比如数千个)。
GitHub上有一个解决方案,它使用薄板样条曲线方法:
https://github.com/davidqkelly/ThinPlateSpline_DotNet