
Image by Editor | Midjourney
Vectorization makes Python code run faster by applying operations to whole arrays. It removes the need for loops and makes the code simpler. It also reduces memory use and improves readability. NumPy is the best library for vectorized operations. It has built-in functions that replace slow loops with fast calculations. In this article, we will explore different vectorized operations with examples.
Sum of Elements
The sum of elements in an array is a fundamental operation used in various mathematical and scientific computations. Instead of using a loop to iterate and sum elements, NumPy provides a vectorized function.
import numpy as np
import timeit
A = np.array([1, 2, 3, 4, 5])
# Loop-based sum
def loop_sum():
result = 0
for i in range(len(A)):
result += A[i]
return result
# Vectorized sum
vectorized_sum = np.sum(A)
print("Loop Sum:", loop_sum())
print("Vectorized Sum:", vectorized_sum)
print("Loop time:", timeit.timeit(loop_sum, number=100000))
print("Vectorized time:", timeit.timeit(lambda: np.sum(A), number=100000))
The loop_sum() function calculates the sum using a loop. It iterates through each element of A and adds it to result. The np.sum(A) function performs the same operation in a single step.
Output:
Loop Sum: 15 Vectorized Sum: 15 Loop time: 0.3073358199999916 Vectorized time: 0.8295847110000238
Dot Product
The dot product of two vectors is a mathematical operation that multiplies corresponding elements and sums them. It results in a scalar value and is widely used in machine learning.
import numpy as np
import timeit
A = np.array([1, 2, 3])
B = np.array([4, 5, 6])
def loop_dot():
result = sum(A[i] * B[i] for i in range(len(A)))
return result
def vectorized_dot():
return np.dot(A, B)
print("Loop Dot Product:", loop_dot())
print("Vectorized Dot Product:", vectorized_dot())
print("Loop time:", timeit.timeit(loop_dot, number=100000))
print("Vectorized time:", timeit.timeit(vectorized_dot, number=100000))
The loop_dot() function computes the dot product using a loop. It multiplies corresponding elements of two arrays and sums the results. The vectorized_dot() function uses np.dot() to calculate the dot product directly.
Output:
Loop Dot Product: 32 Vectorized Dot Product: 32 Loop time: 0.16283419900003082 Vectorized time: 0.12766433000001598
Outer Product
The outer product multiplies each element of one vector by each element of another. This creates a matrix where row values come from the first vector and column values come from the second.
import numpy as np
import timeit
A = np.array([1, 2, 3])
B = np.array([4, 5, 6])
# Loop-based outer product
def loop_outer():
result = np.zeros((len(A), len(B)))
for i in range(len(A)):
for j in range(len(B)):
result[i, j] = A[i] * B[j]
return result
# Vectorized outer product
def vectorized_outer():
return np.outer(A, B)
print("Loop Outer Product:\n", loop_outer())
print("Vectorized Outer Product:\n", vectorized_outer())
print("Loop time:", timeit.timeit(loop_outer, number=100000))
print("Vectorized time:", timeit.timeit(vectorized_outer, number=100000))
Loop Outer Product: [[ 4. 5. 6.] [ 8. 10. 12.] [12. 15. 18.]] Vectorized Outer Product: [[ 4 5 6] [ 8 10 12] [12 15 18]] Loop time: 0.6562794389999453 Vectorized time: 0.3103585869999961
Element-wise Product
The element-wise product multiplies corresponding elements of two arrays. Each element in the result is the product of elements at the same position in the input arrays.
import numpy as np
import timeit
A = np.array([1, 2, 3])
B = np.array([4, 5, 6])
# Loop-based element-wise product
def loop_elementwise():
result = np.zeros_like(A)
for i in range(len(A)):
result[i] = A[i] * B[i]
return result
# Vectorized element-wise product
def vectorized_elementwise():
return A * B
print("Loop Element-wise Product:", loop_elementwise())
print("Vectorized Element-wise Product:", vectorized_elementwise())
print("Loop time:", timeit.timeit(loop_elementwise, number=100000))
print("Vectorized time:", timeit.timeit(vectorized_elementwise, number=100000))
The loop_elementwise() function computes the element-wise product using a loop. It multiplies each corresponding element of A and B and stores the result in an array. The vectorized_elementwise() function uses A * B to achieve the same result directly.
Output:
Loop Element-wise Product: [ 4 10 18] Vectorized Element-wise Product: [ 4 10 18] Loop time: 0.41245563100000027 Vectorized time: 0.0632168790000378
Matrix Multiplication
Matrix multiplication combines rows of the first matrix with columns of the second. It follows the rule where the number of columns in the first matrix must match the number of rows in the second. The result is a new matrix with computed dot products.
X = np.array([[1, 2], [3, 4]])
Y = np.array([[5, 6], [7, 8]])
def loop_matrix_mult():
result = np.zeros((X.shape[0], Y.shape[1]))
for i in range(X.shape[0]):
for j in range(Y.shape[1]):
for k in range(X.shape[1]):
result[i, j] += X[i, k] * Y[k, j]
return result
print("Loop Matrix Multiplication:\n", loop_matrix_mult())
print("Vectorized Matrix Multiplication:\n", np.matmul(X, Y))
print("Loop time:", timeit.timeit(loop_matrix_mult, number=100000))
print("Vectorized time:", timeit.timeit(lambda: np.matmul(X, Y), number=100000))
The loop_matrix_mult function performs matrix multiplication using three nested loops. It manually calculates each element by summing the product of corresponding elements. The np.matmul(X, Y) function uses NumPy’s optimized implementation.
Output:
Loop Matrix Multiplication: [[19. 22.] [43. 50.]] Vectorized Matrix Multiplication: [[19 22] [43 50]] Loop time: 1.1891451749999646 Vectorized time: 0.32121877999998105
Conclusion
Vectorization makes Python code faster and more efficient. It applies operations to entire arrays instead of using loops. This improves performance and reduces memory usage.
NumPy provides many built-in functions for vectorized operations. These include summation, dot product, outer product, element-wise multiplication, and matrix multiplication. Each function replaces slow loops with optimized computations.
