The world’s leading publication for data science, AI, and ML professionals.

All The NumPy You Need To Supercharge Your Deep Learning Code

NumPy or Numerical Python is an open-source Python library that makes it easy to complex numerical operations. Working with machine…

Photo by Mick Haupt on Unsplash
Photo by Mick Haupt on Unsplash

NumPy or Numerical Python is an open-source Python library that makes it easy to complex numerical operations. Working with machine learning and Deep Learning applications involve complex numerical operations with large datasets. NumPy makes implementing these operations relatively simple and effective when compared to their pure Python implementation.

At its core, NumPy implements its (n-dimensional array) data structure, which is similar to a regular Python list. Most programming languages only have the concept of arrays. Python implements lists, which work as arrays, but there are differences.

One key difference between regular python lists and NumPy is that python lists can contain various data types. In contrast, a NumPy array can only contain objects of the same data type. In other words, the data structures are homogenous. While this may seem like a negative, it allows NumPy operations to be faster as they can avoid conversions and constraints while doing computations.

Why should you care about NumPy, and why specifically for deep learning?

I will cover several specific use cases in the post, but one of the most crucial features of NumPy as compared to other python data structures is speed. NumPy is orders of magnitude faster than using regular Python lists. The performance boost is possible because NumPy functions are implemented in C, which in addition to making execution fast, also enables NumPy to decompose large jobs and execute multiple jobs in parallel. Deep learning involves working with large datasets, and NumPy arrays can be an efficient technique when working with those large datasets.

Creating NumPy arrays

There are a few different ways to create a NumPy array, and a straightforward way is to create them using the array() function.

#import NumPy
import numpy as np
#create a NumPy array
a = np.array([1,2,3])
#check the shape of the array
a.shape
#get the dimensions 
a.dim

Besides, you can create directly from standard Python lists. Numpy arrays are smart. If you pass in a Python list to the array() function, it will automatically do the operation and return a Numpy array. You do not have first explicitly to convert to a NumPy array.

#python List
my_list = [1,2,3,4,5]
#creating a NumPy array from a list
np.array(my_list)

You can also convert a pandas DataFrame to a NumPy array using the Pandas function. to_numpy()

#import Pandas
import pandas as pd
#create a DataFrame
df = pd.DataFrame({"A":[1, 2],"B":[3, 4]})
#convert DataFrame to NumPy array
df.to_numpy()

It is important to note that since NumPy arrays can only contain elements of the same data type. By default, when you convert a DataFrame, the dtype of the returned array will be the common NumPy dtype of all types in the DataFrame.

NumPy Loves Math

NumPy arrays exist specifically to do maths. The package includes several helper mathematical functions that allow you to do these computations without writing them yourself quickly.

Popular examples includesqrt() a function that is used to get the square root, the log() function to calculate the log and the tanh() function to calculate the hyperbolic tangent, commonly used as an activation function in deep neural networks.

a = np.array([1,2,3])
#get the square root
np.sqrt(a)
#get log
np.log(a)
#find the tanh
np.tanh(a)

Linear Algebra

Linear algebra is used extensively in Machine Learning and deep learning applications. When working with Deep Learning, you will find yourself working with high-dimensional arrays that can be easily be turned into linear equations to analyze the interaction of features in a given space.

NumPy has several built-in linear algebra algorithms available as methods within the linalg submodule.

A commonly used linear algebra function is norm() a function used to compute the vector’s length also called the vector norm or vector magnitude. Vector norms are applied as a normalization technique to solve overfilling problems in machine learning and deep learning applications. Numpy‘s linalg submodule has the norm() function to calculate the vector norm

a = np.array([1,2,3])
#getting a norm of the vector
np.linalg.norm(a)

When working with linear algebra, it is not uncommon to run into mathematical errors. Some mathematical operations are not permitted. A graceful way to handle these errors is using linalg.LinAlgError exception handling, a general-purpose exception class derived from Python‘s exception class.

For instance, If we try to invert a singular matrix, the operation is not permitted and with throw up an error.

x=np.ones((2,2)) 
np.linalg.inv(x) #this will throw an error
#exception handling using LinAlgError
try:
    np.linalg.inv(x)
except np.linalg.LinAlgError:
    print("Linear Algebra Error")

These linear algebra functions can compute results for several matrices if they are stacked onto the same array.

Broadcasting

One of the foundational features of how NumPy does arithmetic computations is via broadcasting. Broadcasting allows operations between NumPy arrays of different shapes and sizes.

Broadcasting works by comparing trailing dimensions, and there are two main rules for broadcasting to be valid.

  • The dimensions are equal, or
  • one of the dimensions is 1

When you do an element-wise operation in NumPy like adding a scalar to a np.array, it is essentially broadcasting in action.

x = np.ones((2,2))
y = np.ones((3,2,1))
a = np.ones((2,3,3))
x+y #Broadcasting will work; trailing dimensions match
x+a #Broadcasting will fail; trailing dimensions do not match

NumPy and Matrices

The real potential of NumPy comes while working with matrices. Numpy supports various easy-to-use methods for doing standard matrix operations like dot products, transpose, getting the diagonal, and more.

Matrix multiplication, specifically, calculating the dot product of metrics, is a common task in deep learning, especially when working with convolutional neural networks. The NumPy function dot() calculates the dot product of two metrics. In later versions of NumPy, you can also use the @ operator to compute the dot product.

x = np.array([[1,2],[3,4]])
y = np.array([[5,6],[7,8]])
#dot product with dot()
x.dot(y)
#dot product with @
x@y

The next two commonly used matrix operations in deep learning are the inverse and the transpose.

Let’s look at the inverse first. What an inverse? A number multiplied by its inverse is equal to 1. It’s important to remember here that not all matrices will have an inverse, and in those cases, you will get an error. You can get an inverse of a matrix with the linalg.inv() function.

x = np.array([[1, 2], [3, 4]])
#getting the inverse
np.linalg.inv(x)

The transpose of a matrix is an operator that flips the matrix over its diagonal. That is, it switches the row and column indices of the matrix. In NumPy, you can get the transpose of a matrix with T

x = np.array([[1, 2], [3, 4]])
#getting the transpose
x.T

In deep learning, eigenvalues and eigenvectors useful when implementing dimensionality reduction methods like Principal Component Analysis (PCA)

You can calculate the eigenvalues for a vector or a matrix using the linalg.eignvals() function.

x = np.array([[1, 2], [3, 4]])
#getting the eigenvectors
np.linalg.eigvals(x)

When working with matrices, it is essential to remember not to use the matrix function from the NumPy class and instead use regular arrays.

Changing Shape

When working with deep learning, you will often encounter situations where you need to change an array or matrix’s shape. You can reshape a NumPy array using the reshape() function. The function returns a new NumPy array with the new shape.

x = np.array([[1, 2], [3, 4]])
#Reshape 2X2 to 4X1
x.reshape(4,1)

If you need to change the original NumPy array’s shape, you can use the resize() function instead. It works similarly to the reshape() function but changes the original object instead of creating a new object.

x = np.array([[1, 2], [3, 4]]
#Resize the original array 2X2 to 4X1
x.resize(4,1)

Flattening is another standard Deep Learning operation used to pass data or inputs to different layers of your neural network. The flatten() NumPy function will flatten a ndarray.

x = np.array([[1, 2], [3, 4]]
#flatten the array
x.flatten()

In addition to using the flatten() You could also use the ravel() method to do the same thing. The difference between flatten() and ravel() is that, ravel() can be used directly with regular lists and will return a NumPy array.

x_list = [[1, 2],[3, 4]]
#flatten a list
np.ravel(x_list)

A form of reshaping is to add a new dimension to an array. For example, you can unflatten by adding a new dimension newaxis with the keyword

y = np.array([1,2,3,4,5])
#add a new dimension
y[:,np.newaxis]

Yet another way to reshape your NumPy array is to split it using the function. The function takes an and returns sub-arrays based on the specified indices or sections.

x = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8])
#split array into 3 sections
np.split(x,3)

Data Generation with NumPy

NumPy provides a powerful toolkit for numerical operations; however, NumPy can also generate data. Let’s look at some common scenarios.

An identity matrix is a square matrix of any order with 1’s along the main diagonal and 0’s for all other entries. The NumPy function creates an identity matrix of the specified order.

#generate a identity matrix 5
np.identity(5)

In deep learning, you come across situations where you need a matrix of Zeros & Ones. NumPy has handy functions zeros() and ones() you can use to generate a matrix of 0s or 1s.

#generate a 2X3 matrix of 0s
np.zeros((2,3))
#generate a 2X3 matrix of 1s
np.ones((2,3))

Using the NumPy random.rand()function, you can create an array of the specified order that consists of random number elements.

#generate a 2X3 matrix of random numbers
np.random.rand(2,3)
#generate a 2X3 matrix of random integers
np.random.randint(2,3)

Note that if you want random integers instead, you can use the random.randint() function to get a NumPy array with random integers.

The data generation methods discussed above can be used with their _like counterparts such as zeros_like , ones_likeTo generate arrays that take the shape of the array passed as a parameter to the function.

x = np.array([[1, 2],[3, 4]])
#generate a matrix of 1s based on dimensions of x 
np.ones_like(x)

In other words, when using the _like form of the function, we do not specify the shape but instead, pass an existing NumPy array. The resulting NumPy array takes the shape of the array that was passed.

Concluding Thoughts

In this post, I covered all the essential NumPy you need to get started. NumPy has more than what was covered here, but what we covered here should be sufficient to begin working with NumPy in your Deep Learning projects. The best way to learn is by building. As you start working on Deep Learning projects, you will encounter situations requiring you to use additional techniques and learn more. Happy Building!


Related Articles