Search code examples
pythonnumpymatrixmultidimensional-arraymax-pooling

Array Padding Numpy


I have the following matrix:

x = \
    np.array([[[[0.99256822,  0.63019905],
                [0.77484078,  0.27471319]],

               [[0.94722451,  0.95948516],
                [0.81838252,  0.48979609]],

               [[0.81673764,  0.9388614],
                [0.57575844,  0.82265243]]],


              [[[0.95485566,  0.94870753],
                [0.92680463,  0.90044481]],

               [[0.90128127,  0.98683992],
                  [0.9115591,  0.85900321]],

               [[0.949711,    0.85709163],
                  [0.70392261,  0.91043368]]]])

It has dimensions: 2,3,2,2. What I want to do is multiply it with the following matrix:

y = \
    np.array([[[[ 0.,          0.,          0.63019905,  0.        ],
   [ 0.,          0.99256822,  0.,          0.        ],
   [ 0.77484078,  0.,          0.,          0.27471319],
   [ 0.,          0.,          0.,          0.        ]],
  [[ 0.,          0.,          0.,          0.        ],
   [ 0.94722451,  0.,          0.,          0.95948516],
   [ 0.81838252, 0.,          0.,          0.        ],
   [ 0.,          0.,          0.48979609,  0.        ]],

  [[ 0.,          0.,          0.,          0.        ],
   [ 0.,          0.81673764,  0.,          0.9388614 ],
   [ 0.,          0.,          0.,          0.82265243],
   [ 0.57575844,  0.,          0.,          0.        ]]],
 [[[ 0.,          0.95485566,  0.,          0.        ],
   [ 0.,          0.,          0.,          0.94870753],
   [ 0.,          0.92680463,  0.,          0.        ],
   [ 0.,          0.,          0.,          0.90044481]],

  [[ 0.,          0.90128127,  0.,          0.        ],
   [ 0.,          0.,          0.,          0.98683992],
   [ 0.,          0.9115591,   0.,          0.        ],
   [ 0.,          0.,          0.,          0.85900321]],

  [[ 0.,          0.,          0.,          0.85709163],
   [ 0.,          0.949711,    0.,          0.        ],
   [ 0.,          0.70392261,  0.,          0.91043368],
   [ 0.,          0.,          0.,          0.        ]]]])

This has dimensions 2,3,4,4. So what I need to do is to pad the first matrix in such a way that we have each entry copied 4 times, so that the multiplication can take place (3 of the results will elaborate to 0, and the final result will be the multiplication I want). Therefore, I need to convert the first matrix into something that looks like this:

    [[[[ 0.99256822          0.99256822          0.63019905  0.63019905        ]
       [ 0.99256822          0.99256822          0.63019905  0.63019905        ]
        [ 0.77484078         0.77484078          0.27471319  0.27471319]
        [ 0.77484078         0.77484078          0.27471319  0.27471319        ]]

and so on...

Update:

 def bprop(self, inputs, outputs, grads_wrt_outputs):

        m,n = grads_wrt_outputs.shape[:2]
        o = inputs.shape[2]
        p = inputs.shape[3]
        return (self.mask.reshape(m,n,2,2,2,2)*grads_wrt_outputs[:,:,:,None,:,None]).reshape(m,n,o,p) 

This is the scenario I am using this in.


Solution

  • I am assuming a and b as the two arrays respectively.

    Approach #1

    To get that repeated version, we could extend a to 6D with np.broadcast_to and then reshape to 4D -

    a6D = a[:,:,:,None,:,None]
    m,n,p,q = a.shape
    r,s = b.shape[-2:]
    a_repeated = np.broadcast_to(a6D, (m,n,p,r//p,q,s//q)).reshape(b.shape)
    

    Then, use a_repeated for element-wise multiplication with b.

    Approach #2 (Memory efficient one)

    You can extend a to 6D by adding in new axes and thus avoiding any actual repeating or tiling for memory efficiency, perform element-wise multiplication with a 6D reshaped b and finally reshape back to 4D output. Hence, for 4D arrays a and b, we would have -

    m,n,p,q = a.shape
    r,s = b.shape[-2:]
    out = (b.reshape(m,n,p,r//p,q,s//q)*a[:,:,:,None,:,None]).reshape(b.shape)