numpy最大窗口

Zaw*_*Lin 9 python numpy

I have an array and I would like to produce a smaller array by scanning a 2x2 non-overlappingly windows and getting the maximum. Here is an example:

import numpy as np

np.random.seed(123)
np.set_printoptions(linewidth=1000,precision=3)
arr = np.random.uniform(-1,1,(4,4))
res = np.zeros((2,2))
for i in xrange(res.shape[0]):
    for j in xrange(res.shape[1]):
        ii = i*2
        jj = j*2
        res[i][j] = max(arr[ii][jj],arr[ii+1][jj],arr[ii][jj+1],arr[ii+1][jj+1])

print arr
print res
Run Code Online (Sandbox Code Playgroud)

So a matrix like this:

[[ 0.393 -0.428 -0.546  0.103]
 [ 0.439 -0.154  0.962  0.37 ]
 [-0.038 -0.216 -0.314  0.458]
 [-0.123 -0.881 -0.204  0.476]]
Run Code Online (Sandbox Code Playgroud)

Should become this:

[[ 0.439  0.962]
 [-0.038  0.476]]    
Run Code Online (Sandbox Code Playgroud)

How can I do this more efficiently?

Dan*_*iel 9

你可以这样做:

print arr.reshape(2,2,2,2).swapaxes(1,2).reshape(2,2,4).max(axis=-1)

[[ 0.439  0.962]
 [-0.038  0.476]]
Run Code Online (Sandbox Code Playgroud)

解释从以下开始:

arr=np.array([[0.393,-0.428,-0.546,0.103],
[0.439,-0.154,0.962,0.37,],
[-0.038,-0.216,-0.314,0.458],
[-0.123,-0.881,-0.204,0.476]])
Run Code Online (Sandbox Code Playgroud)

我们首先要将轴分组到相关部分.

tmp = arr.reshape(2,2,2,2).swapaxes(1,2)
print tmp    

[[[[ 0.393 -0.428]
   [ 0.439 -0.154]]

  [[-0.546  0.103]
   [ 0.962  0.37 ]]]


 [[[-0.038 -0.216]
   [-0.123 -0.881]]

  [[-0.314  0.458]
   [-0.204  0.476]]]]
Run Code Online (Sandbox Code Playgroud)

再次重塑以获取我们想要的数据组:

tmp = tmp.reshape(2,2,4)
print tmp

[[[ 0.393 -0.428  0.439 -0.154]
  [-0.546  0.103  0.962  0.37 ]]

 [[-0.038 -0.216 -0.123 -0.881]
  [-0.314  0.458 -0.204  0.476]]]
Run Code Online (Sandbox Code Playgroud)

最后沿最后一轴取最大值.

对于方形矩阵,这可以推广为:

k = arr.shape[0]/2
arr.reshape(k,2,k,2).swapaxes(1,2).reshape(k,k,4).max(axis=-1)
Run Code Online (Sandbox Code Playgroud)

根据Jamie和Dougal的评论,我们可以进一步概括:

n = 2                   #Height of window
m = 2                   #Width of window
k = arr.shape[0] / n    #Must divide evenly
l = arr.shape[1] / m    #Must divide evenly
arr.reshape(k,n,l,m).max(axis=(-1,-3))              #Numpy >= 1.7.1
arr.reshape(k,n,l,m).max(axis=-3).max(axis=-1)      #Numpy <  1.7.1
Run Code Online (Sandbox Code Playgroud)

  • 交换轴后的最后一次重塑会触发完整阵列的副本,这对于大型阵列来说可能是昂贵的.最好的选择是完全跳过它(使用numpy> 1.7)给出一个轴元组到`.max`,即`arr.reshape(2,2,2,2).max(axis =( - 1, - 3))`即使你遇到了旧版本的numpy,你也会复制一半数据,如果你打两次调用`.max`,即`arr.reshape(2,2,2,2).max (轴= -3)的.max(轴= -1)`. (4认同)