2

I know there has been some questions about this and it should be possible with broadcasting. But somehow I dont really get how broadcasting works with adding ann additional axis. There is a similar question where each column of one array is multiplied with each column of another array here: Multiply each column with each column. In my case I want to multiply each row of the 2d arrays against each other

I simply have a 3 dimensional array created as the triangular matrix:

matrix = np.tril(np.ones((3,3,3),dtype='bool'))

For simplification just look at the first two arrays:

matrix[:2]

[[[ True False False]
  [ True  True False]
  [ True  True  True]]

 [[ True False False]
  [ True  True False]
  [ True  True  True]]]

This should become:

[[[ True False False]
  [ True False False]
  [ True False False]]#First row of first array multiplied with each row of second array

 [[ True False False]
  [ True  True False]
  [ True  True False]]#Second row of first array multiplied with each row of second array

 [[ True False False]
  [ True  True False]
  [ True  True  True]]]#Third row of first array multiplied with each row of third array

I can achieve this with

matrix[0][None,...]*matrix[1][:,None])

But how can I do it for the whole matrix without looping and how is the broadcasting works? This should then result in an 3d array with 9 2d arrays.

EDIT

For detailed explanation of what this is all about and how the resulting array should look like. I have a number of categories, lets say 3. All of this 3 categories could have 4 states, every state consists of a bool array with 4 bool values for example(Could also be 10 categories with 100 states with 100 bool values). I now want a resulting array which i can index to. So for example I want the output of the multiplied states of all 3 categories and the 3 value of it. I would index to it with resultingArray[0,0,0,1] for the second bool value of the multiplication.

With a 3x4x4 array (3 caategories,4 states,4bool values) but for visualtization with numbers this would look like as follows:

cats = 3
values = 4

matrix = np.arange(48).reshape(cats,values,values)
matrix.shape


totalArray=np.zeros((values,values,values,values))
for row1 in range(len(matrix[0])):
    for row2 in range(len(matrix[1])):
        for row3 in range(len(matrix[2])):
            totalArray[row1,row2,row3] = matrix[0][row1]*matrix[1][row2]*matrix[2][row3]

print(matrix)            
print(totalArray)

Output

[[[ 0  1  2  3]
  [ 4  5  6  7]
  [ 8  9 10 11]
  [12 13 14 15]]

 [[16 17 18 19]
  [20 21 22 23]
  [24 25 26 27]
  [28 29 30 31]]

 [[32 33 34 35]
  [36 37 38 39]
  [40 41 42 43]
  [44 45 46 47]]]
[[[[    0.   561.  1224.  1995.]
   [    0.   629.  1368.  2223.]
   [    0.   697.  1512.  2451.]
   [    0.   765.  1656.  2679.]]

  [[    0.   693.  1496.  2415.]
   [    0.   777.  1672.  2691.]
   [    0.   861.  1848.  2967.]
   [    0.   945.  2024.  3243.]]

  [[    0.   825.  1768.  2835.]
   [    0.   925.  1976.  3159.]
   [    0.  1025.  2184.  3483.]
   [    0.  1125.  2392.  3807.]]

  [[    0.   957.  2040.  3255.]
   [    0.  1073.  2280.  3627.]
   [    0.  1189.  2520.  3999.]
   [    0.  1305.  2760.  4371.]]]


 [[[ 2048.  2805.  3672.  4655.]
   [ 2304.  3145.  4104.  5187.]
   [ 2560.  3485.  4536.  5719.]
   [ 2816.  3825.  4968.  6251.]]

  [[ 2560.  3465.  4488.  5635.]
   [ 2880.  3885.  5016.  6279.]
   [ 3200.  4305.  5544.  6923.]
   [ 3520.  4725.  6072.  7567.]]

  [[ 3072.  4125.  5304.  6615.]
   [ 3456.  4625.  5928.  7371.]
   [ 3840.  5125.  6552.  8127.]
   [ 4224.  5625.  7176.  8883.]]

  [[ 3584.  4785.  6120.  7595.]
   [ 4032.  5365.  6840.  8463.]
   [ 4480.  5945.  7560.  9331.]
   [ 4928.  6525.  8280. 10199.]]]


 [[[ 4096.  5049.  6120.  7315.]
   [ 4608.  5661.  6840.  8151.]
   [ 5120.  6273.  7560.  8987.]
   [ 5632.  6885.  8280.  9823.]]

  [[ 5120.  6237.  7480.  8855.]
   [ 5760.  6993.  8360.  9867.]
   [ 6400.  7749.  9240. 10879.]
   [ 7040.  8505. 10120. 11891.]]

  [[ 6144.  7425.  8840. 10395.]
   [ 6912.  8325.  9880. 11583.]
   [ 7680.  9225. 10920. 12771.]
   [ 8448. 10125. 11960. 13959.]]

  [[ 7168.  8613. 10200. 11935.]
   [ 8064.  9657. 11400. 13299.]
   [ 8960. 10701. 12600. 14663.]
   [ 9856. 11745. 13800. 16027.]]]


 [[[ 6144.  7293.  8568.  9975.]
   [ 6912.  8177.  9576. 11115.]
   [ 7680.  9061. 10584. 12255.]
   [ 8448.  9945. 11592. 13395.]]

  [[ 7680.  9009. 10472. 12075.]
   [ 8640. 10101. 11704. 13455.]
   [ 9600. 11193. 12936. 14835.]
   [10560. 12285. 14168. 16215.]]

  [[ 9216. 10725. 12376. 14175.]
   [10368. 12025. 13832. 15795.]
   [11520. 13325. 15288. 17415.]
   [12672. 14625. 16744. 19035.]]

  [[10752. 12441. 14280. 16275.]
   [12096. 13949. 15960. 18135.]
   [13440. 15457. 17640. 19995.]
   [14784. 16965. 19320. 21855.]]]]

The thing is that the category arrays are always equal, the triangular matrix. Maybe it would be sufficient to have one triangular array and do the multiplication with it. At the end i want to give a array of indices lists like [[0,0,0,1],[0,0,0,2]] to get the two bool values for that multiplication.

1 Answer 1

2

You need to spread out that second axis to create two 4D versions and let them multiply against each other -

matrix[:,None,:,:]*matrix[:,:,None,:]

Or simply -

matrix[:,None]*matrix[...,None,:]

Outer-operation

Explanation with schematic :

We are looking to perform outer-elementwise multiplication against each other along the second axis. So, we need to extend axes and create two 4D array versions such that there's singleton(axis with length=1) corresponding to a full-axis-length version in another. We are doing this dimension-extension with np.newaxis/None.

Consider a 2D case of shape (3,5) :

matrix : 3 x 5

Let's do outer-elementwise multiplication along the second axis. So, the extension of arrays would be -

matrix-version1 : 3 x 1 x 5
matrix-version2 : 3 x 5 x 1

Similarly, for performing outer-elementwise multiplication along the first axis, it would be -

matrix-version1 : 1 x 3 x 5
matrix-version2 : 3 x 1 x 5

Thus, extending this to our 3D case for outer-elementwise multiplication along the second axis and assuming a shape of (m,n,r), it would be -

matrix-version1 : m x 1 x n x r # [:,None,:,:]
matrix-version2 : m x n x 1 x r # [:,:,None,:]

Hence, after elementwise multiplication resulting in :

output          : m x n x n x r
Sign up to request clarification or add additional context in comments.

6 Comments

Thank you very much!!!. I know it is maybe too much, but can I somehow see visual how this adding of new axis works? I really want to understand this
@Varlor Added few comments.
Thank you for this detailed explanation!! But one last question: The output array of this matrix is not the one i expected. Wouldnt the first 2d array of the multiplication be row 1 of array 1 with the first row of second array with all rows of the third array. The second 2d array the first row of array1 with the second row of array2 with all rows of array3 and so on? And because all 3 starting arrays in the matrix are the same could the multiplication be shortened?
Maybe for additional explanation: In the end I want to get explicit bool value by indexing the oputout array with lets say results[0,0,0,1] which gives me the bool value of the multiplication of array1row1 array2row1 array3row1 bool value of entry 1
@Varlor For clarity, can you start off with say - matrix = np.arange(27).reshape(3,3,3) and show us the entire expected output?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.