The dot product of the arrays can be calculated by the function called linalg.multi_dot of the NumPy library, which is easier to compute and takes less computational time than its predecessor, `np.dot`

.

We are also going to see the comparison of `np.dot`

and `multi_dot`

in this post.

**What Is the Dot Product?**

The dot product is a mathematical operation between two arrays of the same length that returns a scalar value. It is calculated as the sum of the element-wise products of the two arrays. It is given as : `dot(a, b)[i,j,k,m] = sum(a [i,j,:] * b[k,:,m])`

**Everything You Need to Know About linalg.multi_dot**

This function of the NumPy library is convenient as it can compute the dot product of two or more arrays in a single function call.

By single function call, we mean that while computing the dot product of two or more arrays, there is no necessity to compute the dot product of arrays separately in different function calls and then combine the result into another function call. We can compute the dot product of as many arrays in just one call of the function.

The multi_dot can be thought of as :

def mulit_dot(arrays): return functools.reduce(np.dot, arrays)

**Syntax:**

`linalg.multi_dot(`

`arrays`

`, `

`*`

`, `

`out=None`

`)`

Arguments | Description | Default value | Required/Optional |

arrays | If the first argument is 1-D it is treated as a row vector. If the last argument is 1-D it is treated as a column vector The resultant array has the same number of rows as the first argument and the same number of columns as the second argument | sequence of array_like | Required |

out | Output argument. It is not usually specified in the syntax, but when it is specified, the output of the computation should be the same type and memory layout as specified in this field The purpose of this parameter is to reuse an existing NumPy array as the output argument, which can lead to performance improvements If the specified condition for the `out` the argument is not met, the function will raise an exception | ndarray | Optional |

`multi_dot`

**Returns: **This function returns the dot product of the given arrays as input. The output is a NumPy array.

**Dot Product of Two Simple Arrays**

Let us compute the dot product of two simple 2D matrices.

The code is given below.

```
import numpy as np
#creating two arrays
a=np.array([[1,2],[3,4]])
b=np.array([[5,6],[7,8]])
#computing the dot product
comp=np.linalg.multi_dot([a, b])
print(comp)
```

`import numpy as np`

**: **We are importing the NumPy library with an alias name- np.

In the third and fourth lines, two arrays are created using `np.array`

function and are stored in two different variables a and b.

The dot product of a and b is computed with the help of `np.linalg.multi_dot`

and is stored in a variable called comp in the sixth line.

In the next line, we are printing the result of the dot product.

The dot product of the a and b is shown below./

Let us check the time taken to execute.

```
#checking the execution time
%timeit np.linalg.multi_dot([a, b])
```

The `%timeit`

function is used to calculate the time taken to perform this operation.

Now that we have understood the basic functionality let us see a more complex example.

**Dot Product of Two Arrays When One of Them Has Infinity Values**

Let us first consider one array with a positive infinity value.

While we are dealing with the elimination of infinite values , here is an article that shows how to create infinity in python.

The code is given below.

```
import numpy as np
#creating arrays
a=np.array([[3,np.inf],[4,5]])
b=np.array([[5,6],[7,8]])
print("The first array is:\n",a)
print("-"*15)
print("The second array is :\n",b)
print("-"*15)
#converting the infintiy values to some number
a1=np.nan_to_num(a,posinf=12)
print("Modified array :\n",a1)
print("*"*15)
comp1=np.linalg.multi_dot([a1, b])
print("The dot product of two arrays is:\n",comp1)
```

`import numpy as np`

** : **We are importing the NumPy library with an alias name- np.

In the third line, we are creating a two-dimensional array that has one positive infinite value in it. The keyword `np.inf`

is used to create a positive infinity value. This array is stored in a variable called a.

In the fourth line, we are creating a two-dimensional array that is stored in a new variable called b.

In the next line, we are printing the first array to the screen.

`print("-"*15)`

is used as a separator. It prints 15 hyphens(-) on the screen.

In line 7, we are printing the second array to the screen.

`print("-"*15)`

is used as a separator. It prints 15 hyphens(-) on the screen.

We now have two arrays a and b. But we need to replace the positive infinity value with some number. It can be done using `np.nan_to_num`

method by passing the array we need to modify (a) and the number we wish to replace the infinity with(in this case, 12). `posinf`

is used to specify that the number we are giving is a positive number.

This modified array is stored in a1 and is passed as an argument to the `multi_dot`

function.

The result of the dot product is stored in comp1 and is printed in line 14.

And the output is:

Let us see if the dot product works with negative values.

The code is shown below.

```
import numpy as np
#creating arrays
a=np.array([[3,6],[4,5]])
b=np.array([[5,-np.inf],[7,8]])
print("The first array is:\n",a)
print("-"*15)
print("The second array is :\n",b)
print("-"*15)
#converting the infintiy values to some number
b1=np.nan_to_num(b,neginf=-13)
print("Modified array :\n",b1)
print("*"*15)
comp2=np.linalg.multi_dot([a, b1])
print("The dot product of two arrays is:\n",comp2)
```

`import numpy as np`

** : **We are importing the NumPy library with an alias name- np.

In the third line, we are creating a two -dimensional array which is stored in a new variable called a.

In the fourth line, we are creating a two-dimensional array that has one negative infinite value in it. The keyword –`np.inf`

is used to create a negative infinity value. This array is stored in a variable called b.

In the next line, we are printing the first array to the screen.

`print("-"*15)`

is used as a separator. It prints 15 hyphens(-) on the screen.

In line 7, we are printing the second array to the screen.

`print("-"*15)`

is used as a separator. It prints 15 hyphens(-) on the screen.

We need to replace the negative infinity value with some number. It can be done using `np.nan_to_num`

method by passing the array we need to modify (b) and the number we wish to replace the infinity with(in this case, -13). `neginf`

is used to specify that the number we are giving is a negative number.

This modified array is stored in b1 and is passed as an argument to the `multi_dot`

function.

The result of the dot product is stored in comp1 and is printed in line 14.

The computed dot product is as follows:

**Dot Product of Three Arrays of Three Dimension**

Let us consider three matrices of 3×3 dimensions.

Here is the code.

```
import numpy as np
#creating three matrices
a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print("First 3x3 matrix:\n",a)
print("-"*15)
b = np.array([[9, 0,1], [1, 5, 4], [8,1,0]])
print("Second 3x3 matrix:\n",b)
print("-"*15)
c = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
print("Third 3x3 matrix:\n",c)
print("*"*15)
#calculating the dot product
comp3 = np.linalg.multi_dot([a,b,c])
print("The dot product is:")
print(comp3)
```

In the first line, we are bringing the NumPy library to the environment.

Three-dimensional arrays can be thought of as three lists combined together into one single matrix.

In the third line, we are creating the first array and storing it in a variable a.

In the next line, we print the array on the screen. The `\n`

is a newline character. All the arguments after `\n`

are printed in a new line.

`print("-"*15)`

: This line is used to create a separator and outputs 15 hyphens(-) on the screen.

The following line is used to create the second matrix stored in b.

We are printing the new array on the screen.

We are creating the third array and storing it in a variable called c in the ninth line,

The dot product of the three arrays(a, b, and c) is computed in line 13 and is stored in a variable called comp3.

Finally, we are printing the result in line 14.

The output is given below.

**Execution Time Taken by np.dot and multi_dot**

Let us compare the execution time of the two methods: `np.dot`

and `multi_dot`

.

Here is the code for `np.dot`

```
#using np.dot
import numpy as np
#Creating arrays
a = np.array([[1, 3], [4, 6]])
b = np.array([[5, 6], [7, 9]])
c = np.array([[6, 1], [3, 4]])
#computing the dot product
comp1 = np.dot(a, b)
res=np.dot(comp1,c)
print("Dot products of these 3 arrays is:")
print(res)
%timeit np.dot(a,b,c)
```

We are creating three arrays a,b, and c in lines 4,5, and 6, respectively.

Since we are using `np.dot`

, we cannot pass all three arrays as arguments to the function at once. So, we are computing the dot product of the first two arrays (a and b), storing the result in a variable called comp1.

Now, comp1 and the array c are passed as arguments to the `np.dot`

, and the dot product of the three matrices is stored in res.

In line 11, we are printing the result.

In line 12, we are calculating the execution time of `np.dot`

using the magic command `%timeit`

.

The output is given below.

As you can see, the time taken by `np.dot`

is less than 3 microseconds.

Let us see the code for `multi_dot`

.

```
#using multi_dot
import numpy as np
#Creating arrays
a = np.array([[1, 3], [4, 6]])
b = np.array([[5, 6], [7, 9]])
c = np.array([[6, 1], [3, 4]])
#computing the dot product
comp2 = np.linalg.multi_dot([a, b, c])
print("Dot products of these 3 arrays is:")
print(comp2)
%timeit np.linalg.multi_dot([a, b, c])
```

We are creating three arrays a,b, and c in lines 4,5, and 6, respectively.

Since we are using `multi_dot`

, we don’t need to compute the dot product multiple times. We can pass all three arrays to the function and obtain the dot product in a single function call.

The result is stored in a variable called comp2.

In the last line, we are checking the execution time of the `multi_dot`

using `%timeit`

.

As observed from both outputs, the `multi_dot`

takes almost 2x time than `np.dot`

.

**Conclusion**

We have seen what is a dot product and how `multi_dot`

function enables us to compute the dot product of two or more arrays in just a single function call. We have also seen the syntax of `multi_dot()`

.

In the first example, we have calculated the dot product of two simple matrices of 2d size.

Next, we have seen how to compute the dot product when one array has infinite values(both positive and negative).

We have also seen the calculation of the dot product for three-dimensional arrays.

Lastly, we have compared `np.dot`

and `multi_dot`

. Though `multi_dot`

helps us to compute the dot product of two or more arrays in a single call, `np.dot`

takes much less time to execute.

Hence, it is safe to say the choice between `np.dot`

and `multi-dot`

depends on the use case and the size of the arrays.

If the arrays are simple and of less dimension, `np.dot`

they can be used. But if the arrays are of higher dimension (like 4d), we need to go for `multi_dot`

.

**References**

Official NumPy manual for linalg.multi_dot.

Stack overflow question on the usage of timeit module.