scipy RegularGridInterpolator与interp2d相比非常慢

sg24os4d  于 10个月前  发布在  其他
关注(0)|答案(2)|浏览(114)

请考虑以下代码示例:

# %%
import numpy
from scipy.interpolate import interp2d, RegularGridInterpolator

x = numpy.arange(9000)
y = numpy.arange(9000)
z = numpy.random.randint(-1000, high=1000, size=(9000, 9000))
f = interp2d(x, y, z, kind='linear', copy=False)

f2 = RegularGridInterpolator((x, y), z, "linear")

mx, my = np.meshgrid(x, y)
M = np.stack([mx, my], axis=-1)

# %%
%timeit f(x, y)

# %%
%timeit f2(M)

字符串
它使用scipy.interpolate.interp2dscipy.interpolate.RegularGridInterpolator建立了一些示例插值器。上面两个单元格的输出是
1.09 s ± 4.38 ms/循环(平均值±标准差)7次运行,每次1次循环)
和/或
10 s ± 17.6 ms/循环(平均值±标准值)7次运行,每次1次循环)
分别。
RegularGridInterpolatorinterp2d慢大约10倍。问题是interp2d在scipy 1.10.0中被标记为已弃用。新代码应该使用RegularGridInterpolator。这对我来说似乎有点奇怪,因为这将是一个如此糟糕的替代品。上面的代码示例中是否存在问题?如何加快插值过程?

rwqw0loc

rwqw0loc1#

您的代码没有问题,可能是scipy中的bug。我已经在github上报告过了

p1iqtdky

p1iqtdky2#

如果其他人在这个问题上犯了错:
事实证明,手动计算双线性插值比scipy的RegularGridInterpolator快 * 10倍。当我说“手动”时,我的意思是:
1.从传递给RegularGridInterpolator的相同points(假设x_vals长度为N,y_vals长度为M)和values(假设z_grid形状为NxM)数组开始。
1.给定你想要的坐标(比如x,y),使用np.searchsorted()找到最近的四个点的索引(如果x_vals/y_vals是 * 递增 * --如果其中一个是 * 递减 *,这会自动工作,见下面的代码)。
1.使用标准公式计算双线性插值,我使用Raymond Hettinger's code
下面是我自己的实现中的一个稍微修改的摘录:

# since `x_vals` and `y_vals` are decreasing rather than increasing, we do some trickery on top of `np.searchsorted()` to get the desired indices.
i_x = x_vals.shape[0] - np.searchsorted(np.flip(x_vals), x)
i_y = y_vals.shape[0] - np.searchsorted(np.flip(y_vals), y)

points = (
    (
        x_vals[i_x - 1],
        y_vals[i_y - 1],
        z_grid[i_x - 1, i_y - 1]
    ),
    (
        x_vals[i_x],
        y_vals[i_y - 1],
        z_grid[i_x, i_y - 1]
    ),
    (
        x_vals[i_x - 1],
        y_vals[i_y],
        z_grid[i_x - 1, i_y]
    ),
    (
        x_vals[i_x],
        y_vals[i_y],
        z_grid[i_x, i_y]
    )
)

'''here's an option with list comprehension
points = [
    (
        x_vals[i_x-1+i],
        y_vals[i_y-1+j],
        z_grid[i_x-1+i, i_y-1+j]
    )
    for i, j in [(i, j) for i in range(2) for j in range(2)]
]
'''

return bilinear_interpolation(x, y, points) # see https://stackoverflow.com/a/8662355/22122546

字符串
就像我之前说的,从我自己的测试来看,这比RegularGridInterpolator快了大约10倍。我不知道为什么scipy没有在文档中提供一个警告,我已经浪费了几个小时在这个lol上。但至少有一个干净的解决方案:>
保重!

相关问题