在三维空间中,将随机散布的数据插值和外推到均匀网格上。

14

我有一个 $256 \times 256 \times 32$ 的网格,其中包含沿着 $x$、$y$ 和 $z$ 方向平均分布的点,并带有一个关联变量 "a"。 我还有一个在更小的 x、y、z 空间中随机散布的点组,带有一个相关变量 "b"。 我想做的是将这些随机数据插值和外推到与 "a" 立方体匹配的规则网格上,如下图所示:

Visual representation.

目前,我使用的是 Scipy 中的 griddata 来实现插值,似乎效果不错,但它无法处理外推(据我所知),输出结果被截断为 'nan' 值。 在研究这个问题时,我遇到了一些人第二次使用 griddata,将 'nearest' 作为插值方法来填充 'nan' 值。 我尝试了这个方法,但结果似乎不可靠。 如果我使用“线性”模式的 fill_Value,可以获得更适当的结果,但目前只是一种权宜之计,因为 fill_Value 必须是一个常数。

我注意到 MATLAB 有一个 ScatteredInterpolant 类,似乎可以实现我想要的功能,但我无法在 Python 中找到等效的类,也无法弄清楚如何在 3D 中高效地实现这样的例程。 任何帮助都将不胜感激。

以下是我用于插值的代码:

x, y, z, b = np.loadtxt(scatteredfile, unpack = True)

# Create cube to match aCube dimensions
xi = np.linspace(-xmax_aCube, xmax_aCube, 256)
yi = np.linspace(-ymax_aCube, ymax_aCube, 256)
zi = np.linspace(zmin_aCube, zmax_aCube, 32)

# Interpolate scattered points
X, Y, Z = np.meshgrid(xi, yi, zi)
bCube = griddata((x, y, z), b, (X, Y, Z), method = 'linear')    

这些空间点是计数数据还是带有相应测量值 f(x,y,z) 的坐标?你确定这是插值和外推吗?看起来你可能想将这些点分配到你构建的三维箱中。 - James
如果您的“b”数据比较规整,您可以向散点云中添加一些均匀间隔的合成数据点,以强制实现所需的行为 - 但这完全取决于您的用例(仅用于显示数据可能是合理的)... - mommermi
2个回答

9

这个讨论适用于任何维度。对于您的3D情况,让我们首先谈论计算几何,以理解为什么区域的一部分会从griddata中给出NaN

您体积内的散点构成了一个凸包(convex hull);具有以下特性的几何形状:

  • 表面始终是凸的(正如名称所示)
  • 形状的体积最低,而不违反凸性
  • 表面(在3d中)被三角化并封闭

不太正式地说,凸包( 您可以使用scipy轻松计算)就像在框架上拉伸气球一样,其中框架角是您散布的集群的最外点。

在气球内部的常规网格位置周围都是已知点。您可以对这些位置进行插值。在外部,您必须进行外推。

外推很难。 没有通用的规则来做这件事...它是针对问题的。在那个区域,像 griddata 这样的算法会选择返回 NaN - 这是告诉科学家必须选择合理的外推方式的最安全方法。

让我们来看看一些方法。

1. [最糟糕] 瞎搞

将某些标量值分配到外壳之外。 在 numpy 文档中,您可以看到以下操作: s = mean(b) bCube = griddata((x, y, z), b, (X, Y, Z), method='linear', fill_value=s)

缺点:这会在外壳边界处产生尖锐的插值场不连续性,严重偏离平均标量场值,并且不尊重数据的函数形式。

2. [次糟糕] “混合瞎搞”

假设在您的区域角落处应用某些值。这可能是与散点相关的标量场的平均值。
抱歉,这是伪代码,因为我根本不使用numpy,但它可能会相当清晰。
# With a unit cube, and selected scalar value
x, y, z, b = np.loadtxt(scatteredfile, unpack = True)
s = mean(b)
x.append([0 0 0 0 1 1 1 1])
y.append([0 0 1 1 0 0 1 1])
z.append([0 1 0 1 0 1 0 1])
b.append([s s s s s s s s])
# drop in the rest of your code
缺点:这会在船体边界处产生插值场的梯度急剧不连续,相当严重地偏差了平均标量场值,并且不尊重数据的函数形式。

3. [仍然相当糟糕] 最近邻居

对于每个常规NaN点,找到最近的非NaN并分配该值。这是有效和稳定的,但粗糙,因为您的场可能会出现模式特征(如从船体辐射出的条纹或梁),通常在视觉上不吸引人或更糟,在数据平滑方面不可接受。

根据数据密度,您可以使用最近的散点数据点而不是最近的非NaN常规点。这可以通过以下方式简单实现(同样是伪代码):

bCube = griddata((x, y, z), b, (X, Y, Z), method = 'linear', fill_value=nan)
bCubeNearest = griddata((x, y, z), b, (X, Y, Z), method = 'nearest')
indicesMask = isNan(bCube)
# Use nearest interpolation outside the hull, keeping linear interpolation inside.
bCube(indicesMask) = bCubeNearest(indicesMask)

使用MATLAB的Delaunay方法可以揭示更强大的一行代码实现相似功能的方法,但numpy在这方面似乎有些受限。

4. [并非总是糟糕] 自然加权

对于本节中较差的解释,我表示歉意,我从未编写过该算法,但我相信对自然邻居技术进行一些研究将会让你走得更远

使用一种距离加权函数和某个参数D,它可能类似于您的盒子的长度或两倍(例如)。您可以进行调整。对于每个NaN位置,计算到每个散点的距离。

# Don't do it this way for anything but small matrices - this is O(NM) 
# and it can be done much more effectively (e.g. MATLAB has a quick 
# natural weighting option), but for illustrative purposes:
for each NaN point 1:N
    for each scattered point 1:M
        calculate a basis function using inverse distance from NaN to point, normalised on D, and store in a [1 x M] vector of weights
Multiply weights by the b value, summate and divide by M   

你基本上想要得到一个函数,它能够平滑地到达距离壳体D处的B的平均强度,但在边界处与壳体重合。远离边界时,它在最近点上的加权最强。
优点:非常稳定且相当连续。由于加权,比最近邻更具有单个数据点的噪声鲁棒性。
5. [英勇的摇滚巨星] 功能形式假设
你对物理学了解多少?假设一个代表你对物理学期望的功能形式,然后对散布的数据进行最小二乘(或某些等效)拟合。使用该函数来稳定外推。
一些有助于构建函数的好主意:
- 你是否期望对称性或周期性? - b是否是具有某些特性(如零散度)的向量场的组成部分? - 方向性:你是否期望所有角落都相同?或者可能是一个方向的线性变化? - b在某个时间点上是否为场-也许可以使用平滑的测量时间序列来得出基本函数? - 是否已经存在已知形式,例如高斯或二次函数?
一些例子:
  • b代表通过一个体积的激光束的强度。你期望进入侧与出口侧基本相同,其他四个边界的强度为零。强度将具有同心高斯分布。

  • b是不可压缩流体中速度场的一个分量。流体必须无散,因此在NaN区域产生的任何场也必须无散,因此应用此条件。

  • b代表房间内的温度。你期望顶部温度更高,因为热空气上升。

  • b代表在三个独立变量上测试的翼型升力。你可以轻松查找失速时的升力,因此知道空间某些部分的升力。

优缺点:如果做对了,它会很棒。如果做错了,特别是非线性函数形式,结果将会非常不稳定。

健康警告:你不能假设一个函数形式,得到漂亮的结果,然后用它们来证明函数形式是正确的。这只是错误的科学方法。该形式需要是一些行为良好且独立于数据分析的已知形式。


1
如果您的点散布形状较为接近一个立方体,一种方法是使用 griddata 对数据进行插值,使其落在一个适合于您的点云的规则网格中(因此避免了nans),然后使用这个规则网格值作为interpn 的输入,它可以实现线性外推(但需要规则网格作为输入)。
这样,您可以像之前一样使用 griddata 来处理散布点凸包内的所有点,并使用 interpn 估算返回为 nans 的点。
这远非完美,但我认为它更接近您所寻求的结果。 优点:
  • 避免了尖锐的不连续性。
  • 捕捉数据集边缘的基本线性趋势,而无需知道函数形式。
  • 尊重数据的不对称性(例如,在大距离处不趋向于人口平均值,因此数据集的一侧在大距离处可能具有比另一侧更大的值。)

缺点:

  • 这种方法的有效性很大程度上取决于您可以适合初始散点图凸包内的多大立方体。如果您的数据是凹凸不平和不规则的,那么即使在凸包的边缘上的点也可能已经从嵌套立方体的边缘外推了显著的距离,这会产生误差,因为外推不会考虑到位于立方体外部的更近的数据点。
  • 线性外推将受到点云边缘噪声的影响。
  • 执行两组插值的计算成本。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接