2016-09-10 91 views
4

x是一个形状为(A,B)的矩阵,并且是大小为A + B-1的阵列。如何在numpy中有效地实现x [i] [j] = y [i + j]?

for i in range(A): 
    for j in range(B): 
     x[i][j] = y[i+j] 

如何在numpy中使用函数有效实现等效代码?

+0

看起来像'y.reshape'就是你所追求的,这基本上只是将一维数组转换为二维数组。 – Andrew

+0

通常,您希望使用'x [i,j]'而不是'x [i] [j]'来更快地访问numpy数组。 – JoshAdel

回答

7

方法#1使用Scipy's hankel -

from scipy.linalg import hankel 

x = hankel(y[:A],y[A-1:] 

方法#2使用NumPy broadcasting -

x = y[np.arange(A)[:,None] + np.arange(B)] 

方法3使用NumPy strides technique -

n = y.strides[0] 
x = np.lib.stride_tricks.as_strided(y, shape=(A,B), strides=(n,n)) 

运行测试 -

In [93]: def original_app(y,A,B): 
    ...:  x = np.zeros((A,B)) 
    ...:  for i in range(A): 
    ...:   for j in range(B): 
    ...:    x[i][j] = y[i+j] 
    ...:  return x 
    ...: 
    ...: def strided_method(y,A,B): 
    ...:  n = y.strides[0] 
    ...:  return np.lib.stride_tricks.as_strided(y, shape=(A,B), strides=(n,n)) 
    ...: 

In [94]: # Inputs 
    ...: A,B = 100,100 
    ...: y = np.random.rand(A+B-1) 
    ...: 

In [95]: np.allclose(original_app(y,A,B),hankel(y[:A],y[A-1:])) 
Out[95]: True 

In [96]: np.allclose(original_app(y,A,B),y[np.arange(A)[:,None] + np.arange(B)]) 
Out[96]: True 

In [97]: np.allclose(original_app(y,A,B),strided_method(y,A,B)) 
Out[97]: True 

In [98]: %timeit original_app(y,A,B) 
100 loops, best of 3: 5.29 ms per loop 

In [99]: %timeit hankel(y[:A],y[A-1:]) 
10000 loops, best of 3: 114 µs per loop 

In [100]: %timeit y[np.arange(A)[:,None] + np.arange(B)] 
10000 loops, best of 3: 60.5 µs per loop 

In [101]: %timeit strided_method(y,A,B) 
10000 loops, best of 3: 22.4 µs per loop 

其他方法基于strides -

看来strides技术已在几个地方使用:extract_patchesview_as_windows了在这样的图像处理中使用基于模块。所以,对于那些,我们有两种方法 -

from skimage.util.shape import view_as_windows 
from sklearn.feature_extraction.image import extract_patches 

x = extract_patches(y,(B)) 
x = view_as_windows(y,(B)) 

In [151]: np.allclose(original_app(y,A,B),extract_patches(y,(B))) 
Out[151]: True 

In [152]: np.allclose(original_app(y,A,B),view_as_windows(y,(B))) 
Out[152]: True 

In [153]: %timeit extract_patches(y,(B)) 
10000 loops, best of 3: 62.4 µs per loop 

In [154]: %timeit view_as_windows(y,(B)) 
10000 loops, best of 3: 108 µs per loop 
+0

跨步技巧的时间? – wwii

+0

步骤*技巧*似乎已经过时了,所以我有时会看到评论说它并不像它被吹捧的那样高效*但是对于一个滚动窗口来说它的效果非常好。 – wwii

+0

@wwii正确!事实上,这是我的第一个答案,掌握了它,这对于我认为的窗口化操作来说非常神奇,特别是它的效率部分。 – Divakar

相关问题