{:check ["true"]}

Index

1 Constructing Tensors

Tensors with NumPy

We will be manipulating tensors in Python. The primary library we will focus on will be NumPy.

NumPy uses native libraries for highly efficient storage and accelerated performance.

In [1]:
import numpy as np
import matplotlib.pyplot as pl

np.__version__
Out[1]:
'1.19.4'

Tensors

Some examples of Tensors

Tensor provides a generalization of scalars, vectors, matrices and deeper nested numeric arrays.

Scalars

A person's income can be described as a scalar.

$$ \mathrm{income} = 60000 $$

Vectors

  1. If we have a group of individuals, we can view their individual incomes as a vector.

    $$ \mathrm{team} = [60000, 62000, 62000, 70000] $$

  2. If we know more about a single person, e.g. their age, height, we can represent these numerical attributes as a vector

    $$ \mathrm{person} = \left[\begin{array}{l} \$60000 \\ 65 \mathrm{yo} \\ 1.78 \mathrm{m} \\ \end{array} \right]$$

Matrices

  1. A grayscale image is a 2D matrix. Each entry is a scalar value representing the intensity of that pixel.

    $$ \mathrm{image} = \left[\begin{array}{} 0 & 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 & 0 \\ 1 & 1 & 0 & 0 & 0 \\ 1 & 1 & 0 & 0 & 0 \\ 1 & 0 & 0 & 0 & 0 \\ \end{array}\right]$$

  2. A collection personal records is a 2D matrix with each person as a vector.

    $$ \mathrm{persons} = \left[\begin{array}{cc} \$60000 & \$62000\\ 65 \mathrm{yo} & 60\mathrm{yo} \\ 1.78 & 1.82\mathrm{m} \\ \end{array} \right]$$

Tensors

  1. A color image is a tensor with three axes. For example, a color image of size 5x5 will be a tensor with shape (5, 5, 3). The axis with three entries will store the RGB value of that pixel.

  2. If we monitor the persons over a period of 10 years, then the observation forms a tensor with shape (10, 3, 2). There will be 10 matrices, and each matrix is 3x2, describing their income, age and height.

NumPy API for loading data

Loading from Python lists

Python arrays can be converted to NDArray using array(...).

In [2]:
# Converting python list into vectors
np.array([1, 2, 3])
Out[2]:
array([1, 2, 3])
In [3]:
# We can specify the datatype as well.
np.array([1, 2, 3], dtype='float32')
Out[3]:
array([1., 2., 3.], dtype=float32)
In [4]:
# Higher rank tensors can be constructed
# from nested Python lists.

np.array([
    [1,2,3],
    [4,5,6],
    [7,8,9],
    [10,11,12]
])
Out[4]:
array([[ 1,  2,  3],
       [ 4,  5,  6],
       [ 7,  8,  9],
       [10, 11, 12]])

Loading from files

We can also create NDArrays from a wide range of sources.

  • images
  • files on disk
In [5]:
# We can load common image formats using the
# Python Image Library (PIL), which can then
# be converted to NumPy arrays.

from PIL import Image
im = Image.open('./blackhole.jpg')
im_array = np.array(im)
print("Array size", im_array.shape)
pl.imshow(im_array);
Array size (590, 787, 3)
In [6]:
# We can load from a file.

with open('./data.txt') as f:
    print(f.read())
    
file_array = np.loadtxt('./data.txt', delimiter=",")
file_array
1,2,3,4,5
6,7,8,8,9

Out[6]:
array([[1., 2., 3., 4., 5.],
       [6., 7., 8., 8., 9.]])

Loading from iterators

We can also create NDArrays from a Python generator.

In [7]:
#
# Let's build a function that constructs
# a generator of Fibonacci numbers.
#
def get_fib(n):
    a = 1
    b = 1
    for i in range(n):
        if i <= 1:
            yield 1
        else:
            x = a + b
            a,b = b, x
            yield x
print(get_fib(10))
<generator object get_fib at 0x7f0460a134a0>
In [8]:
#
# We can load the generator into a NDArray
# directly without going through Python list.
#
np.fromiter(get_fib(10), int)
Out[8]:
array([ 1,  1,  2,  3,  5,  8, 13, 21, 34, 55])

NumPy API for NDArray construction

Constructing simple matrices

We can construct empty NDArrays using various functions.

In [9]:
np.empty(shape=(2,2), dtype=int)
Out[9]:
array([[4619792497756654800, 4639894992141672037],
       [4628103046444036916, 4640246835862560357]])
In [10]:
np.zeros(shape=(2,2))
Out[10]:
array([[0., 0.],
       [0., 0.]])
In [11]:
np.ones(shape=(2,2))
Out[11]:
array([[1., 1.],
       [1., 1.]])
In [12]:
np.eye(5)
Out[12]:
array([[1., 0., 0., 0., 0.],
       [0., 1., 0., 0., 0.],
       [0., 0., 1., 0., 0.],
       [0., 0., 0., 1., 0.],
       [0., 0., 0., 0., 1.]])
In [13]:
np.full(shape=(5,5), fill_value=3.1415)
Out[13]:
array([[3.1415, 3.1415, 3.1415, 3.1415, 3.1415],
       [3.1415, 3.1415, 3.1415, 3.1415, 3.1415],
       [3.1415, 3.1415, 3.1415, 3.1415, 3.1415],
       [3.1415, 3.1415, 3.1415, 3.1415, 3.1415],
       [3.1415, 3.1415, 3.1415, 3.1415, 3.1415]])

More construction functions

Constructing sequences

Here are a few more ways of constructing NDArrays that follow a certain pattern.

  1. Linear sequence

  2. Logarithmic sequence

In [14]:
np.arange(10)
Out[14]:
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [15]:
np.linspace(0, 2 * np.pi, 10)
Out[15]:
array([0.        , 0.6981317 , 1.3962634 , 2.0943951 , 2.7925268 ,
       3.4906585 , 4.1887902 , 4.88692191, 5.58505361, 6.28318531])

np.logspace(a, b, n) constructs n values in the range:

$$[10^a, 10^b]$$

evenly in logspace.

In [18]:
np.logspace(0, 1, 10)
Out[18]:
array([ 1.        ,  1.29154967,  1.66810054,  2.15443469,  2.7825594 ,
        3.59381366,  4.64158883,  5.9948425 ,  7.74263683, 10.        ])

Meshgrid is a pair of matrices that describe spatial coordinates in the XY plane.

In [17]:
xx, yy = np.meshgrid(np.arange(10), np.arange(5))
print('xx ='); print(repr(xx))
print('yy ='); print(repr(yy))
xx =
array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
       [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
       [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
       [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
       [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])
yy =
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
       [2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
       [3, 3, 3, 3, 3, 3, 3, 3, 3, 3],
       [4, 4, 4, 4, 4, 4, 4, 4, 4, 4]])