NumPy
When implementing deep learning, arrays and matrices are often calculated. The array class of NumPy (numpy.array)
provides many convenient methods that are used to implement deep learning. This section provides a brief description of NumPy, which we will use later.
Importing NumPy
NumPy is an external library. The word external here means that NumPy is not included in standard Python. So, you must load (import) the NumPy library first:
>>> import numpy as np
In Python, an import statement is used to import a library. Here, import numpy as np
means that numpy
is loaded as np
. Thus, you can now reference a method for NumPy as np
.
Creating a NumPy Array
You can use the np.array()
method to create a NumPy array. np.array()
takes a Python list as an argument to create an array for NumPy—that is, numpy.ndarray
:
>>> x = np.array([1.0, 2.0, 3.0]) >>> print(x) [ 1. 2. 3.] >>> type(x) <class 'numpy.ndarray'>
Mathematical Operations in NumPy
The following are a few sample mathematical operations involving NumPy arrays:
>>> x = np.array([1.0, 2.0, 3.0]) >>> y = np.array([2.0, 4.0, 6.0]) >>> x + y # Add arrays array([ 3., 6., 9.]) >>> x - y array([ -1., -2., -3.]) >>> x * y # element-wise product array([ 2., 8., 18.]) >>> x / y array([ 0.5, 0.5, 0.5])
Take note that the numbers of elements of arrays x
and y
are the same (both are one-dimensional arrays with three elements). When the numbers of elements of x
and y
are the same, mathematical operations are conducted for each element. If the numbers of elements are different, an error occurs. So, it is important that they are the same. "For each element" is also called element-wise, and the "product of each element" is called an element-wise product.
In addition to element-wise calculations, mathematical operations of a NumPy array and a single number (scalar value) are also available. In that case, calculations are performed between each element of the NumPy array and the scalar value. This feature is called broadcasting (more details on this will be provided later):
>>> x = np.array([1.0, 2.0, 3.0]) >>> x / 2.0 array([ 0.5, 1. , 1.5])
N-Dimensional NumPy Arrays
In NumPy, you can create multi-dimensional arrays as well as one-dimensional arrays (linear arrays). For example, you can create a two-dimensional array (matrix) as follows:
>>> A = np.array([[1, 2], [3, 4]]) >>> print(A) [[1 2] [3 4]] >>> A.shape (2, 2) >>> A.dtype dtype('int64')
Here, a 2x2 matrix, A
, was created. You can use shape
to check the shape of the matrix, A
, and use dtype
to check the type of its elements. Here are the mathematical operations of matrices:
>>> B = np.array([[3, 0],[0, 6]]) >>> A + B array([[ 4, 2], [ 3, 10]]) >>> A * B array([[ 3, 0], [ 0, 24]])
As in arrays, matrices are calculated element by element if they have the same shape. Mathematical operations between a matrix and a scalar (single number) are also available. This is also conducted by broadcasting:
>>> print(A) [[1 2] [3 4]] >>> A * 10 array([[ 10, 20], [ 30, 40]])
A NumPy array (np.array
) can be an N-dimensional array. You can create arrays of any number of dimensions, such as one-, two-, three-, ... dimensional arrays. In mathematics, a one-dimensional array is called a vector, and a two-dimensional array is called a matrix. Generalizing a vector and a matrix is called a tensor. In this book, we will call a two-dimensional array a matrix, and an array of three or more dimensions a tensor or a multi-dimensional array.
Broadcasting
In NumPy, you can also do mathematical operations between arrays with different shapes. In the preceding example, the 2x2 matrix, A
, was multiplied by a scalar value of s
. Figure 1.1 shows what is done during this operation: a scalar value of 10
is expanded to 2x2 elements for the operation. This smart feature is called broadcasting:
Figure 1.1: Sample broadcasting – a scalar value of 10 is treated as a 2x2 matrix
Here is a calculation for another broadcasting sample:
>>> A = np.array([[1, 2], [3, 4]]) >>> B = np.array([10, 20]) >>> A * B array([[ 10, 40], [ 30, 80]])
Here (as shown in Figure 1.2), the one-dimensional array B
is transformed so that it has the same shape as the two-dimensional array A
, and they are calculated element by element.
Thus, NumPy can use broadcasting to do operations between arrays with different shapes:
Figure 1.2: Sample broadcasting
Accessing Elements
The index of an element starts from 0
(as usual). You can access each element as follows:
>>> X = np.array([[51, 55], [14, 19], [0, 4]]) >>> print(X) [[51 55] [14 19] [ 0 4]] >>> X[0] # 0th row array([51, 55]) >>> X[0][1] # Element at (0,1) 55
Use a for
statement to access each element:
>>> for row in X: ...    print(row) ... [51 55] [14 19] [0 4]
In addition to the index operations described so far, NumPy can also use arrays to access each element:
>>>X = X.flatten( )
# Convert X into a one-dimensional array >>> print(X) [51 55 14 19 0 4] >>>X[np.array([0, 2, 4])]
# Obtain the elements of the 0th, 2nd, and 4th indices array([51, 14, 0])
Use this notation to obtain only the elements that meet certain conditions. For example, the following statement extracts values that are larger than 15
from X
:
>>> X > 15 array([ True, True, False, True, False, False], dtype=bool) >>> X[X>15] array([51, 55, 19])
An inequality sign used with a NumPy array (X > 15
, in the preceding example) returns a Boolean array. Here, the Boolean array is used to extract each element in the array, extracting elements that are True
.
Note
It is said that dynamic languages, such as Python, are slower in terms of processing than static languages (compiler languages), such as C and C++. In fact, you should write programs in C/C++ to handle heavy processing. When performance is required in Python, the content of a process is implemented in C/C++. In that case, Python serves as a mediator for calling programs written in C/C++. In NumPy, the main processes are implemented by C and C++. So, you can use convenient Python syntax without reducing performance.