Blockwise operations in Numpy

前端 未结 3 1070
难免孤独
难免孤独 2021-01-04 13:08

Are there any convenience utilities for doing blockwise operations on Numpy arrays?

I am thinking of operations like Ising spin renormalization where you divide a ma

3条回答
  •  佛祖请我去吃肉
    2021-01-04 14:01

    For sliding blockwise operations, you can borrow an implementation from Implement Matlab's im2col_sliding 'sliding' in python that groups each block into a column, thereby blockwise operation would become as easy as operating along the axis = 0 and as such would accept all NumPy ufuncs for vectorized solutions. Here's a formal way to define such a sliding blocks creating function -

    def im2col_sliding(A,BLKSZ):   
    
        # Parameters
        M,N = A.shape
        col_extent = N - BLKSZ[1] + 1
        row_extent = M - BLKSZ[0] + 1
    
        # Get Starting block indices
        start_idx = np.arange(BLKSZ[0])[:,None]*N + np.arange(BLKSZ[1])
    
        # Get offsetted indices across the height and width of input array
        offset_idx = np.arange(row_extent)[:,None]*N + np.arange(col_extent)
    
        # Get all actual indices & index into input array for final output
        return np.take (A,start_idx.ravel()[:,None] + offset_idx.ravel())
    

    Sample run to calculate blockwise sum, average, std, etc. -

    In [6]: arr                 # Sample array
    Out[6]: 
    array([[6, 5, 0, 6, 0],
           [7, 4, 2, 3, 6],
           [6, 3, 3, 8, 1],
           [5, 5, 1, 1, 8]])
    
    In [7]: im2col_sliding(arr,[2,3])   # Blockwise array with blocksize : (2,3)
    Out[7]: 
    array([[6, 5, 0, 7, 4, 2, 6, 3, 3],
           [5, 0, 6, 4, 2, 3, 3, 3, 8],
           [0, 6, 0, 2, 3, 6, 3, 8, 1],
           [7, 4, 2, 6, 3, 3, 5, 5, 1],
           [4, 2, 3, 3, 3, 8, 5, 1, 1],
           [2, 3, 6, 3, 8, 1, 1, 1, 8]])
    
    In [8]: np.sum(im2col_sliding(arr,[2,3]),axis=0) # Perform blockwise summation
    Out[8]: array([24, 20, 17, 25, 23, 23, 23, 21, 22])
    
    In [9]: np.mean(im2col_sliding(arr,[2,3]),axis=0) # Perform blockwise averaging
    Out[9]: 
    array([ 4.        ,  3.33333333,  2.83333333,  4.16666667,  3.83333333,
            3.83333333,  3.83333333,  3.5       ,  3.66666667])
    
    In [10]: np.std(im2col_sliding(arr,[2,3]),axis=0) # Blockwise std. deviation
    Out[10]: 
    array([ 2.38047614,  1.97202659,  2.47767812,  1.77169097,  1.95078332,
            2.40947205,  1.67497927,  2.43241992,  3.14466038])
    

提交回复
热议问题