python - 一个阵列轴的快速插补

标签 python arrays numpy interpolation

我想在 3 维数组中插入一个数据轴。不同值的给定 x 值略有不同,但它们都应映射到相同的 x 值。

由于给定的 x 值不相同,目前我执行以下操作:

import numpy as np
from scipy import interpolate

axes_have = np.ones( ( 2, 72, 2001 ) )
axes_have *= np.linspace( 0, 100, 2001 )[None,None,:]
axes_have += np.linspace( -0.3, 0.3, 144 ).reshape( ( 2, 72 ) )[:,:,None]

arr = np.sin( axes_have )
arr *= np.random.random( (2, 72 ) )[:,:,None]

axis_want = np.linspace( 0, 100, 201 )    

arr_ip = np.zeros( ( 2, 72, 201 ) )
for i in range( arr.shape[0] ):
    for j in range( arr.shape[1] ):
         ip_func = interpolate.PchipInterpolator( axes_have[i,j,:], arr[i,j,:], extrapolate=True )
         arr_ip[i,j,:] = ip_func( axis_want )

使用两个嵌套 for -loops 不出所料地非常慢。

有没有办法提高速度?也许通过做一些 NumPy 数组魔术或并行化。

最佳答案

我已经做了一些初步测试,似乎你的大部分时间都花在了生成实际的插值函数上。似乎只是矢量化不会使速度提高一吨,但它确实使并行化变得容易(这确实提高了产量)。这是一个例子。

import numpy as np
from scipy import interpolate
import timeit
import multiprocessing



def myfunc(arg):
    x, y = arg
    return interpolate.PchipInterpolator(x,
                                         y,
                                         extrapolate=True)

p = multiprocessing.Pool(processes=8)
axes_have = np.ones((2, 72, 2001))
axes_have *= np.linspace(0, 100, 2001)[None, None, :]
axes_have += np.linspace(-0.3, 0.3, 144).reshape((2, 72))[:, :, None]

arr = np.sin(axes_have)
arr *= np.random.random((2, 72))[:, :, None]

axis_want = np.linspace(0, 100, 201)

arr_ip = np.zeros((2, 72, 201))
s_time1 = timeit.default_timer()
for i in range(arr.shape[0]):
    for j in range(arr.shape[1]):
         ip_func = interpolate.PchipInterpolator(axes_have[i, j, :],
                                                 arr[i, j, :],
                                                 extrapolate=True)
         arr_ip[i, j, :] = ip_func(axis_want)
elapsed1 = timeit.default_timer() - s_time1

s_time2 = timeit.default_timer()
flatten_have = [y for x in axes_have for y in x]
flatten_arr = [y for x in arr for y in x]
interp_time = timeit.default_timer()
funcs = p.map(myfunc, zip(flatten_have, flatten_arr))
interp_elapsed = timeit.default_timer() - interp_time
arr_ip = np.asarray([func(axis_want) for func in funcs]).reshape(2, 72, 201)
elapsed2 = timeit.default_timer() - s_time2

print("Elapsed 1: {}".format(elapsed1))
print("Elapsed 2: {}".format(elapsed2))
print("Elapsed interp: {}".format(interp_elapsed))

典型结果(请注意,在没有并行化的情况下,矢量化实现的速度几乎完全相同,而且我有 2 个内核,因此您的运行时间应该大致为(原始时间/内核数)):
Elapsed 1: 10.4025919437
Elapsed 2: 5.11409401894
Elapsed interp: 5.10987687111

不要误会我的意思,可能有一种算法方法可以更快地做到这一点,但这似乎是产生立即加速的最简单方法,因为问题是令人尴尬的并行。

关于python - 一个阵列轴的快速插补,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46078272/

相关文章:

python - 如何使用 beautifulsoup 从 url 中的表返回多个页面的数据

python - 如果满足条件,从数组中减去一个数字python

PHP foreach 循环使用一个条目两次

python - 如何使用 pandas 和 numpy 一起处理 Series 和 Array?

python - 编辑列表以删除定义的变量以及字符之后(包括字符)的所有内容

python - 在cv2.imshow中的“Exception has occurred: error”

python - 对日期序列进行排序的最 pythonic 方法是什么?

ios - 遍历数组并在 Swift 中增加计数器

python - PANDAS:如何 pd.read_csv 并将 7 位整数拆分为 4 x 3 整数?

python - 计算汽车 OpenCV + Python 问题