NumPy provides powerful tools for performing mathematical operations on arrays and matrices. One of the most common operations performed on matrices is matrix multiplication. In some cases, we may need to compute the product of several matrices at once. For example, suppose we have p
matrices A1, A2, ..., Ap
, and we want to compute their product A1*A2*...*Ap
. One way to do this is to perform p-1
matrix multiplications, each time multiplying the current result with the next matrix. However, this can be computationally expensive, especially when dealing with large matrices. Fortunately, NumPy provides multiple functionalities to do this efficiently, which are as follows:
1. Using "np.einsum()":
- The
np.ones()
is a function that returns a new array of a given shape and data type, where all the elements are set to 1. In this example code, a 3-dimensional arrayM
of shape(p, n, n)
and a 3-dimensional arrayV
of shape(p, n, 1)
is created using thenp.ones()
function. - The
np.einsum()
function implements Einstein summation notation, which is a compact way to express tensor operations. - The
subscripts
argument'pjk,pki->ij'
ofnp.einsum()
specifies the indices of the input arrays to be contracted and the output array and the function performs a tensor contraction over the indicesp
,k
, andi
ofM
andp
,k
, andj
ofV
, resulting in a 2-dimensional array of shape(n, n)
which is assigned to the variableS
. - Finally, the code prints the value of
S
to the console.
- The output of the code will be a 2D array of shape
(n, n)
, with all elements set to the valuep * n
: - The advantage of using NumPy’s broadcasting rules to create this array is that it can be done with a single line of code, without the need for loops or list comprehensions. This can be much faster and more memory-efficient than equivalent operations using loops or list comprehensions, especially for large arrays.
- Also, NumPy’s broadcasting rules make it easy to perform element-wise operations between arrays of different shapes and sizes, which is a common task in scientific computing and data analysis.
2. Using "np.dot()":
- In this method too, the arrays
M
andV
are created in the same way using thenp.ones()
function. - The
dot()
function performs matrix multiplication between two arrays. Here, the multiplication is performed betweenM
andV
. SinceV
has shape(p, n, 1)
, the result of the dot product will be a 3D array of shape(p, n, 1)
. - The
squeeze()
function is used to remove any dimensions with size 1 from an array. In this case, it is used to remove the extra dimension of size 1 from the result of the dot product, since we want a 2D array of shape(p, n)
instead of a 3D array of shape(p, n, 1)
. - Lastly, the
sum()
function is used to compute the sum of all elements inS
along the first dimension (p
). This results in a 1D array of shape(n,)
, which is stored inS
.
- The output of this code will be a 1D array of shape
(n,)
, with all elements set to the valuep * n
: - The advantage of using matrix multiplication and broadcasting rules to perform this operation is that it can be done with a single line of code, without the need for loops or list comprehensions. This can be much faster and more memory-efficient than equivalent operations using loops or list comprehensions, especially for large arrays.