-4

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.

Alk
  • 5,215
  • 8
  • 47
  • 116

2 Answers2

1

The function you're looking for is np.repeat. I repeated the x matrix two times along the last two dimensions, like this:

>>> x = np.repeat(x, 2, axis=(2))
>>> x = np.repeat(x, 2, axis=(3))
>>> x
  [[[[ 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]]

  [[ 0.94722451  0.94722451  0.95948516  0.95948516]
   [ 0.94722451  0.94722451  0.95948516  0.95948516]
   [ 0.81838252  0.81838252  0.48979609  0.48979609]
   [ 0.81838252  0.81838252  0.48979609  0.48979609]]
   ...
>>> x.shape
(2, 3, 4, 4)
>>> y.shape
(2, 3, 4, 4)

Now that the two matrices have similar shape, they can be multiplied:

>>> x * y
[[[[ 0.          0.          0.39715084  0.        ]
   [ 0.          0.98519167  0.          0.        ]
   [ 0.60037823  0.          0.          0.07546734]
   [ 0.          0.          0.          0.        ]]

  [[ 0.          0.          0.          0.        ]
   [ 0.89723427  0.          0.          0.92061177]
   [ 0.66974995  0.          0.          0.        ]
   [ 0.          0.          0.23990021  0.        ]]

  [[ 0.          0.          0.          0.        ]
   [ 0.          0.66706037  0.          0.88146073]
   [ 0.          0.          0.          0.67675702]
   [ 0.33149778  0.          0.          0.        ]]]


 [[[ 0.          0.91174933  0.          0.        ]
   [ 0.          0.          0.          0.90004598]
   [ 0.          0.85896682  0.          0.        ]
   [ 0.          0.          0.          0.81080086]]

  [[ 0.          0.81230793  0.          0.        ]
   [ 0.          0.          0.          0.97385303]
   [ 0.          0.83093999  0.          0.        ]
   [ 0.          0.          0.          0.73788651]]

  [[ 0.          0.          0.          0.73460606]
   [ 0.          0.90195098  0.          0.        ]
   [ 0.          0.49550704  0.          0.82888949]
   [ 0.          0.          0.          0.        ]]]]
Adeel Ahmad
  • 1,033
  • 1
  • 11
  • 24
  • the function you suggested simply maps the whole matrix 4 times, what I need to do is map each element, as shown in the last part of the question – Alk Nov 23 '17 at 13:50
  • @mankee I just updated my answer. It produces the same output that you posted. – Adeel Ahmad Nov 23 '17 at 13:58
1

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)
Community
  • 1
  • 1
Divakar
  • 218,885
  • 19
  • 262
  • 358
  • How could I adjust this `(b.reshape(2,3,2,2,2,2)*a[:,:,:,None,:,None]).reshape(2,3,4,4)` to work for a general case in a neural network backprop? For example I am running this currently and obtain the following error `cannot reshape array of size 288000 into shape (2,3,2,2,2,2)` due to it being specific to the example in the question. I understand I would set the `(2,3,4,4)` to be the mask dimensions, but I'm not sure about the `(2,3,2,2,2,2)` – Alk Nov 23 '17 at 17:49
  • I have updated the question with my code, could you please confirm my understanding is correct. Also, do I not have to change the `2`s, is it fine to leave them hardcoded or do they also depend on the dimensions of the inputs and grads? Thanks! – Alk Nov 23 '17 at 17:59