我的问题是使用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
,默认为False
,ev
不存在,这允许您传递两个定义正交网格的向量。调用grid
设置为True
会导致调用fitpack例程bispev
,这比调用fitpack ev
的文档bispeu
函数快得多。 (我假设性能提升是因为bispev
利用了常规网格,而bispeu
可能只是循环遍历所有索引对......虽然我不确定。)
无论如何,我想以这样一种方式调用一个.ev
类似的函数,我可以插入一个可能不完全正常(但很接近)的网格,并且会比当前调用更快。 bispeu
。 “规范化”网格并使用bispev
是一个选项,最终结果是PRETTY接近,并且例程比这更快(20倍!)...但是,Matlab {{1允许略微不规则的网格并以相同的速度计算。我曾经考虑过尝试编写自己的C函数,但是我非常怀疑我能做的这么低,比Scipy中已有的并且由天才编写的更好。 :)
那么..有没有办法让我的蛋糕也可以吃?是否有一些非常棘手的方法我可以调用样条评估器?我已经考虑过为fitpack调用制作我自己的定制包装器...但是fitpack的文档并不是很容易获得(当然不是我的Scipy版本),如果可能的话,我想避免额外的工作。还要注意这个问题特别令人讨厌,因为我必须调用它两次,一次是我原始字段的实部和虚部(Matlab需要复杂的网格)。在一天结束时,我想给Matlab提供BOOT ......但这个速度问题可能是一个杀手。
感谢您的时间。