DiegoDZ - 1 month ago 16

Python Question

I have two matrix:

`A = [a11 a12`

a21 a22]

B = [b11 b12

b21 b22]

And I want to multiply all its columns (without loops) in order to obtain the matrix:

`C =[a11*b11 a11*b12 a12*b11 a12*b12`

a21*b21 a21*b22 a22*b21 a22*b22]

I've tried with

`>>> C = np.prod(A,B,axis=0)`

but prod doesn't accept two input matrix. Neither np.matrix.prod.

Thanks in advance.

Answer

You could use `broadcasting`

for a vectorized solution -

```
(A[...,None]*B[:,None]).reshape(A.shape[0],-1)
```

**Philosophy :** In terms of vectorized/broadcasting language, I would describe this as *spreading* or putting the second dimension of the input arrays against each other, while keeping their first dimension aligned. This spreading is done by introducing new axes with `None/np.newaxis`

for these two inputs and then simply multiplying each other.

**Mathematical view :** Let's use less a bit more mathematical view of it with the help of a generic example that has different number of columns -

```
In [504]: A = np.random.rand(2,3)
In [505]: B = np.random.rand(2,4)
```

Extend the dimensions and check their shapes :

```
In [506]: A[...,None].shape
Out[506]: (2, 3, 1)
In [507]: B[:,None].shape
Out[507]: (2, 1, 4)
```

Now, perform the element-wise multiplication, which will perform these multiplications in a broadcasted manner. Take a closer look at the output's shape -

```
In [508]: (A[...,None]*B[:,None]).shape
Out[508]: (2, 3, 4)
```

So, the singleton dimensions (dimension with length = 1) introduced by the use of `None/np.newaxis`

would be the ones along which elements of the respective arrays would be broadcasted under the hood before being multiplied.

Finally, we reshape this `3D`

array to have a `2D`

array with number of rows same as that of the original inputs.

Sample run -

```
In [494]: A
Out[494]:
array([[2, 3],
[4, 5]])
In [495]: B
Out[495]:
array([[12, 13],
[14, 15]])
In [496]: (A[...,None]*B[:,None]).reshape(A.shape[0],-1)
Out[496]:
array([[24, 26, 36, 39],
[56, 60, 70, 75]])
```

**For NumPy matrix type inputs**

If you are working `NumPy matrix types`

, you could use `np.asmatrix`

that would simply create view into the inputs. Using those views, the broadcasted element-wise multiplication would be performed, finally resulting in a `2D`

array after the reshaping. So, the last step would be to convert back to `np.matrix`

type. Thus, for `np.matrix`

input, the solution would be -

```
In [553]: A
Out[553]:
matrix([[2, 3],
[4, 5]])
In [554]: B
Out[554]:
matrix([[12, 13],
[14, 15]])
In [555]: arrA = np.asarray(A)
In [556]: arrB = np.asarray(B)
In [557]: np.asmatrix((arrA[...,None]*arrB[:,None]).reshape(A.shape[0],-1))
Out[557]:
matrix([[24, 26, 36, 39],
[56, 60, 70, 75]])
```