PolarSPARC

Introduction to Deep Learning - Part 4


Bhaskar S 06/30/2023


Introduction


In Introduction to Deep Learning - Part 3 of this series, we got our hands dirty by building our own version of the perceptron and the neural network from scratch using Python.

In this article, we will continue our journey by introducing the very popular open source deep learning framework called PyTorch.


Installation and Setup


The installation and setup of PyTorch will be performed on a Ubuntu 22.04 LTS Linux desktop with a suitable NVidia graphics card and the Python programming language installed.

Open a Terminal window to perform the necessary installation step(s).

To install PyTorch, execute the following command:

$ sudo pip3 install torch torchaudio torchdata torchmetrics torchtext torchvision

This above command will install all the required dependencies along with the desired PyTorch packages.


Hands-on PyTorch


All the code snippets are executed in a Jupyter Notebook code cell.


PyTorch Basics


To import the PyTorch module, execute the following code snippet:


import torch

To check PyTorch was installed ok, execute the following code snippet:


torch.__version__

The following would be a typical output:

Output.1

'2.0.0+cu117'

Notice the +cu117 in the output above. This implies that PyTorch is CUDA enabled.

To check if the GPU is accessible, execute the following code snippet:


torch.cuda.is_available()

The following would be a typical output:

Output.2

True

The output above implies that PyTorch has access to the GPU device.

The core data structure in PyTorch is referred to as the Tensor and is an n-dimensional array structure. It can be thought of as similar to the ndarray structure in numpy. In other words, a Tensor can be used to represent a Scalar (zero dimension), or a Vector (one dimension), or a Matrix (two dimension), or a multi-dimensional structure (dimension greater than two).

The following are some of the features of Tensors:


To set the random seed for reproducibility, execute the following code snippet:


torch.manual_seed(101)

The following would be a typical output:

Output.3

<torch._C.Generator at 0x7f17dddab7f0>

To create a scalar using a number, a vector and matrix using numpy ndarray, and a tensor using a Python list, execute the following code snippet:


scalar = torch.tensor(11)
vector = torch.tensor(np.array([13.0, 15.0]))
matrix = torch.tensor(np.array([
    [17.0, 19.0],
    [21.0, 23.0]
]), dtype=torch.float)
tensor = torch.tensor([[
    [25, 27, 29],
    [31, 33, 35],
    [37, 39, 41]
],
[
    [43, 49, 55],
    [45, 51, 57],
    [47, 53, 59]
]], dtype=torch.float, device='cuda')

Notice how one can specify the data type and the device from the above code snippet. The value of cuda implies the NVidia GPU device.

To display the details about the scalar, execute the following code snippet:


print(f'Scalar: {scalar}, Shape: {scalar.shape}, Type: {scalar.dtype}, Device: {scalar.device}')

The following would be a typical output:

Output.4

Scalar: 11, Shape: torch.Size([]), Type: torch.int64, Device: cpu

To display the details about the vector, execute the following code snippet:


print(f'Vector: {vector}, Shape: {vector.shape}, Type: {vector.dtype}, Device: {vector.device}')

The following would be a typical output:

Output.5

Vector: tensor([13., 15.], dtype=torch.float64), Shape: torch.Size([2]), Type: torch.float64, Device: cpu

To display the details about the matrix, execute the following code snippet:


print(f'Matrix: {matrix}, Shape: {matrix.shape}, Type: {matrix.dtype}, Device: {matrix.device}')

The following would be a typical output:

Output.6

Matrix: tensor([[17., 19.],
  [21., 23.]]), Shape: torch.Size([2, 2]), Type: torch.float32, Device: cpu

To display the details about the tensor, execute the following code snippet:


print(f'Tensor: {tensor}, Shape: {tensor.shape}, Type: {tensor.dtype}, Device: {tensor.device}')

The following would be a typical output:

Output.7

Tensor: tensor([[[25., 27., 29.],
  [31., 33., 35.],
  [37., 39., 41.]],

  [[43., 49., 55.],
  [45., 51., 57.],
  [47., 53., 59.]]], device='cuda:0'), Shape: torch.Size([2, 3, 3]), Type: torch.float32, Device: cuda:0


*** CAUTION ***

The default float data type in PyTorch is *float32*, while in numpy it is *float64*

To access the individual elements of a Tensor, execute the following code snippet:


print(f'vector[1] = {vector[1]}, matrix[1][0] = {matrix[1][0]}, matrix[1, 0] = {matrix[1, 0]},'
  f'tensor[0][1][2] = {tensor[0][1][2]}, tensor[0, 1, 2] = {tensor[0, 1, 2]}')

The following would be a typical output:

Output.8

vector[1] = 15.0, matrix[1][0] = 21.0, matrix[1, 0] = 21.0,tensor[0][1][2] = 35.0, tensor[0, 1, 2] = 35.0

To access the sub-Tensors within a Tensor, execute the following code snippet:

print(f'matrix[0] = {matrix[0]}, matrix[:, 1] = {matrix[:, 1]}, tensor[0] = {tensor[0]}, tensor[0][1] = {tensor[0][1]}, '
  f'tensor[:, :, 1] = {tensor[:, :, 1]}')

The following would be a typical output:

Output.9

matrix[0] = tensor([17., 19.]), matrix[:, 1] = tensor([19., 23.]), tensor[0] = tensor([[25., 27., 29.],
  [31., 33., 35.],
  [37., 39., 41.]], device='cuda:0'), tensor[0][1] = tensor([31., 33., 35.], device='cuda:0'), tensor[:, :, 1] = tensor([[27., 33., 39.],
  [49., 51., 53.]], device='cuda:0')

To create a vector Tensor of a specific type within a range in steps, execute the following code snippet:

vector1 = torch.arange(1, 101, step=11, dtype=torch.float32)
vector1

The following would be a typical output:

Output.10

tensor([  1.,  12.,  23.,  34.,  45.,  56.,  67.,  78.,  89., 100.])

To create a Tensor of shape 3x3 with random values, execute the following code snippet:

tensor1 = torch.rand(size=(3, 3))
tensor1

The following would be a typical output:

Output.11

tensor([[0.1980, 0.4503, 0.0909],
  [0.8872, 0.2894, 0.0186],
  [0.9095, 0.3406, 0.4309]])

To create a Tensor of shape 3x3x3 with zero values, execute the following code snippet:

zeros_tensor = torch.zeros(size=(3, 3, 3))
zeros_tensor

The following would be a typical output:

Output.12

tensor([[[0., 0., 0.],
   [0., 0., 0.],
   [0., 0., 0.]],

  [[0., 0., 0.],
   [0., 0., 0.],
   [0., 0., 0.]],

  [[0., 0., 0.],
   [0., 0., 0.],
   [0., 0., 0.]]])

To create a Tensor of shape 3x3x3 with all one values, execute the following code snippet:

ones_tensor = torch.ones(size=(3, 3, 3))
ones_tensor

The following would be a typical output:

Output.13

tensor([[[1., 1., 1.],
   [1., 1., 1.],
   [1., 1., 1.]],

  [[1., 1., 1.],
   [1., 1., 1.],
   [1., 1., 1.]],

  [[1., 1., 1.],
   [1., 1., 1.],
   [1., 1., 1.]]])

We will now move onto the next section on Tensors related to mathematical operations.


Tensor Mathematical Operations


To create a vector of shape 1x3 and a matrix of shape 3x3, execute the following code snippet:

vector2 = torch.rand(size=(1, 3))
matrix1 = torch.rand(size=(3, 3))
print(f'vector2 = {vector2}, matrix1 = {matrix1}')

The following would be a typical output:

Output.14

vector2 = tensor([[0.6389, 0.3944, 0.2462]]), matrix1 = tensor([[0.7276, 0.8310, 0.6744],
   [0.0299, 0.6592, 0.3304],
   [0.6563, 0.5190, 0.0596]])

To multiply the vector by the matrix, execute the following code snippet:

vector2 * matrix1

The following would be a typical output:

Output.15

tensor([[0.4649, 0.3277, 0.1661],
   [0.0191, 0.2600, 0.0814],
   [0.4193, 0.2047, 0.0147]])

To multiply two matrices of shapes 2x3 and 3x2 (note the inner dimensions must match), execute the following code snippet:

matrix2 = torch.ones(size=(2, 3))
matrix2 *= 5
matrix3 = torch.ones(size=(3, 2))
matrix2 *= 2
matrix2 @ matrix3

The following would be a typical output:

Output.16

tensor([[30., 30.],
   [30., 30.]])

The @ operator is for matrix multiplication. One could also use the following two methods to perform the same operation.

torch.matmul(matrix2, matrix3)
torch.mm(matrix2, matrix3)

To perform the transpose operation on the matrix of shape 3x2, execute the following code snippet:

matrix3.T

The following would be a typical output:

Output.17

tensor([[2., 2., 2.],
   [2., 2., 2.]])

For the next set of operations, let us consider the following Tensor of shape 3x2x3:

tensor2 = torch.tensor([
  [
    [10, 11, 12],
    [13, 14, 15]
  ],
  [
    [20, 21, 22],
    [23, 24, 25]
  ],
  [
    [30, 31, 32],
    [33, 34, 35]
  ]
], dtype=torch.float)

Dimension 0 is each of the 3 sub-tensors (matrices), dimension 1 are the rows, and dimension 2 are the columns.

To perform a data type conversion of tensor2 elements to int32 type, execute the following code snippet:

tensor2.to(dtype=torch.int32)

The following would be a typical output:

Output.18

tensor([[[10, 11, 12],
   [13, 14, 15]],

  [[20, 21, 22],
   [23, 24, 25]],

  [[30, 31, 32],
   [33, 34, 35]]], dtype=torch.int32)

To perform the a sum operation on tensor2 along dimension 0, execute the following code snippet:

tensor2.sum(dim=0)

The following would be a typical output:

Output.19

tensor([[60., 63., 66.],
  [69., 72., 75.]])

The following illustration depicts the sum operation visually:


Dimension 0 Sum
Figure.1

To perform the a sum operation on tensor2 along dimension 1, execute the following code snippet:

tensor2.sum(dim=1)

The following would be a typical output:

Output.20

tensor([[23., 25., 27.],
  [43., 45., 47.],
  [63., 65., 67.]])

The following illustration depicts the sum operation visually:


Dimension 0 Sum
Figure.2

To perform the a sum operation on tensor2 along dimension 2, execute the following code snippet:

tensor2.sum(dim=2)

The following would be a typical output:

Output.21

tensor([[ 33.,  42.],
  [ 63.,  72.],
  [ 93., 102.]])

The following illustration depicts the sum operation visually:


Dimension 0 Sum
Figure.3

To perform the a mean operation on tensor2 along dimension 1, execute the following code snippet:

tensor2.mean(dim=1)

The following would be a typical output:

Output.22

tensor([[11.5000, 12.5000, 13.5000],
  [21.5000, 22.5000, 23.5000],
  [31.5000, 32.5000, 33.5000]])

There are more than 300+ mathematical functions defined in PyTorch.


References

PyTorch Documentation

Introduction to Deep Learning - Part 3

Introduction to Deep Learning - Part 2

Introduction to Deep Learning - Part 1


© PolarSPARC