加速Scipy的RectBivariateSpline评估函数

时间:2015-07-20 18:53:04

标签: matlab python-3.x scipy interpolation

我的问题是使用scipy.interpolate.RectBivariateSpline函数来插值2D网格。我本质上是在尝试模拟Matlab的interp2函数的功能。

对于特定的(轻)用例,我在x和y向量上调用RectBivariateSpline,它们是规则间隔的,单调递增的向量,例如:

x = np.arange(0., 20., 1.)  # shape (20,)
y = np.arange(0., 20., 1.)  # shape (20,)

和一些2D字段,例如:

fld = np.reshape(np.arange(0., 400., 1.), (20, 20))  # shape (20, 20)

即:

fn = sp.interpolate.RectBivariateSpline(x, y, fld)

为了评估插值,然后,在特定的xi,yi坐标(或数组,服从numpy广播),文档建议调用RectBivariateSpline.ev函数,即:

val1 = fn.ev(1, 1)  # Ans: 21
val2 = fn.ev([1, 2], [1, 2])  # Ans: [21, 22]

这允许用户找到一个插值,例如(xi,yi)=(1.5,1.5)或许多插值,比如在特定域(常规或不规则网格)上。

我的问题是:对于大型xi,yi数组,如何让fn.ev调用更快?与Matlab interp2调用相比,它非常慢(数量级或更差)。

在调试器中调用函数之后,我发现ev实际上是RectBivariateSpline.__call__的包装器。这也是对Scipy插值功能所基于的fitpack函数(在C / Fortran中)的调用的包装器。 __call__函数有一个可选的关键字grid,默认为Falseev不存在,这允许您传递两个定义正交网格的向量。调用grid设置为True会导致调用fitpack例程bispev,这比调用fitpack ev的文档bispeu函数快得多。 (我假设性能提升是因为bispev利用了常规网格,而bispeu可能只是循环遍历所有索引对......虽然我不确定。)

无论如何,我想以这样一种方式调用一个.ev类似的函数,我可以插入一个可能不完全正常(但很接近)的网格,并且会比当前调用更快。 bispeu。 “规范化”网格并使用bispev是一个选项,最终结果是PRETTY接近,并且例程比这更快(20倍!)...但是,Matlab {{1允许略微不规则的网格并以相同的速度计算。我曾经考虑过尝试编写自己的C函数,但是我非常怀疑我能做的这么低,比Scipy中已有的并且由天才编写的更好。 :)

那么..有没有办法让我的蛋糕也可以吃?是否有一些非常棘手的方法我可以调用样条评估器?我已经考虑过为fitpack调用制作我自己的定制包装器...但是fitpack的文档并不是很容易获得(当然不是我的Scipy版本),如果可能的话,我想避免额外的工作。还要注意这个问题特别令人讨厌,因为我必须调用它两次,一次是我原始字段的实部和虚部(Matlab需要复杂的网格)。在一天结束时,我想给Matlab提供BOOT ......但这个速度问题可能是一个杀手。

感谢您的时间。

0 个答案:

没有答案