如何直接获取scipy插值的梯度?
我有一个较大的 3D numpy 标量值数组(如果必须的话,可以将其称为“体积”)。我想在一系列不规则的而不是全部的情况下插入一个平滑的标量场 已知的预先非整数 xyz 坐标。
现在 Scipy 对此的支持非常好:我使用
filtered_volume = scipy.ndimage.interpolation.spline_filter(volume)
过滤体积并调用,
scipy.ndimage.interpolation.map_coordinates(
filtered_volume,
[[z],[y],[x]],
prefilter=False)
感兴趣的 (x,y,z)
以获得明显表现良好(平滑等)的插值。到目前为止,一切都很好。但是,我的应用程序还需要插值场的局部导数。目前,我通过中心差分获得这些:我还在 6 个附加点处对体积进行采样(这至少可以通过一次调用 map_coordinates
来完成)并计算例如来自 ( i(x+h,y,z)-i(xh,y,z))/(2*h)
。 (是的,我知道我可以将额外的抽头数量减少到 3 次并进行“单侧”差异,但不对称性会让我烦恼。)
我的直觉是应该有一种更直接的方法来获取梯度 但我还不知道足够的样条数学来弄清楚,或者理解什么 Scipy 实现的内部正在进行: scipy/scipy/ndimage /src/ni_interpolation.c
。
有没有比中心差分更好的“更直接”获得梯度的方法?最好是允许使用现有功能而不是侵入 Scipy 的内部结构来获取它们。
I have a largish 3D numpy array of scalar values (OK call it a "volume" if you must). I want to interpolate a smooth scalar field over this at a succession of irregular, not all
known up-front non-integral xyz coordinates.
Now Scipy's support for this is just excellent: I filter the volume with
filtered_volume = scipy.ndimage.interpolation.spline_filter(volume)
and invoke
scipy.ndimage.interpolation.map_coordinates(
filtered_volume,
[[z],[y],[x]],
prefilter=False)
for (x,y,z) of interest to obtain apparently nicely behaved (smooth etc) interpolated values.
So far so good. However, my application also needs the local derivatives of the interpolated field. Currently I obtain these by central-differencing: I also sample the volume at 6 additional points (this can at least be done with just one call to map_coordinates
) and calculate e.g the x derivative from (i(x+h,y,z)-i(x-h,y,z))/(2*h)
. (Yes I know I could reduce the number of additional taps to 3 and do "one sided" differences, but the asymmetry would annoy me.)
My instinct is that there ought to be a more direct way of obtaining the gradient
but I don't know enough spline math (yet) to figure it out, or understand what's
going on in the guts of the Scipy implementation: scipy/scipy/ndimage/src/ni_interpolation.c
.
Is there a better way of obtaining my gradients "more directly" than central differencing ? Preferably one which allows them to be obtained using the existing functionality rather than hacking on Scipy's innards.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
啊哈:根据经典论文在 numpy 代码中引用的样条上,n 阶样条及其导数通过
使用 SciPy 的样条插值 I 相关联可以通过维护低阶预过滤量并针对每个导数查询几次来获得我的导数。这意味着添加相当数量的内存(可能与缓存的“主”卷竞争),但大概对低阶样条的评估速度更快,所以对我来说,它是否会比中央差分总体上更快还是不明显使用我目前正在做的小偏移量。还没试过。
Aha: according to the classic paper on splines cited in the numpy code, splines of order n and their derivatives are related by
So using SciPy's spline interpolation I could get my derivatives by also maintaining a lower-order prefiltered volume and querying that a couple of times per derivative. This means adding a fair amount of memory (maybe competition with the "main" volume for cache), but presumably evaluation of the lower order splines is faster, so it's not obvious to me whether it would be faster or not overall than the central differencing using small offsets I'm doing currently. Haven't tried it yet.