# Get Started with PyTorch

PyTorch has gained significant popularity as an open-source deep learning framework with a Python and C++ interface. It allows developers to build and train neural networks that mimic the functioning of the human brain. With its powerful capabilities and extensive library support, PyTorch has become a preferred choice for many machine learning practitioners.

In this article, we will explore the various aspects of PyTorch, including its installation, tensor operations, restructuring tensors, mathematical operations, PyTorch modules, dataset handling, and building neural networks. We will delve into each topic, providing a comprehensive understanding of PyTorch and its applications.

## Installing PyTorch

To begin using PyTorch, you need to install it on your system. If you already have Anaconda Python Package manager installed, you can install PyTorch by running the following command in the terminal:

```
conda install pytorch torchvision cpuonly -c pytorch
```

This command will install the latest stable version of PyTorch, which is currently 1.12.1. If you prefer not to install PyTorch locally, you can use Google Colab, a cloud-based platform that provides a Jupyter notebook environment.

## PyTorch Tensors

Tensors are the fundamental data structures used in PyTorch for processing data. They are multidimensional arrays, similar to n-dimensional NumPy arrays. However, tensors have the advantage of being used on GPUs as well. PyTorch offers various built-in functions for efficiently computing and manipulating tensors.

A tensor can be thought of as a one-dimensional vector or a two-dimensional matrix, depending on its shape. It can only contain numeric data types, and all columns in each dimension must have the same size. The two fundamental attributes of a tensor are its shape and rank.

```
import torch
t1 = torch.tensor([1, 2, 3, 4]) # 1D tensor (vector)
t2 = torch.tensor([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]) # 2D tensor (matrix)
print("Tensor t1: \n", t1)
print("\nTensor t2: \n", t2)
print("\nRank of t1: ", len(t1.shape))
print("Rank of t2: ", len(t2.shape))
print("\nShape of t1: ", t1.shape)
print("Shape of t2: ", t2.shape)
```

Output:

```
Tensor t1:
tensor([1, 2, 3, 4])
Tensor t2:
tensor([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
Rank of t1: 1
Rank of t2: 2
Shape of t1: torch.Size([4])
Shape of t2: torch.Size([3, 4])
```

## Creating Tensors in PyTorch

PyTorch provides several methods for creating tensors. Tensors can be created using Python lists, NumPy arrays, or by copying existing tensors. The choice of method depends on the desired data type and whether you want to copy the data or share it.

Here are some ways to create tensors in PyTorch:

`torch.Tensor()`

: This method copies the data and creates a tensor. It is an alias for`torch.FloatTensor()`

.`torch.tensor()`

: This method also copies the data to create a tensor but automatically infers the data type.`torch.as_tensor()`

: This method shares the data instead of copying it and accepts any type of array for tensor creation.`torch.from_numpy()`

: This method is similar to`torch.as_tensor()`

but only accepts NumPy arrays.

```
import torch
import numpy as np
data1 = [1, 2, 3, 4, 5, 6]
data2 = np.array([1.5, 3.4, 6.8, 9.3, 7.0, 2.8])
t1 = torch.tensor(data1)
t2 = torch.Tensor(data1)
t3 = torch.as_tensor(data2)
t4 = torch.from_numpy(data2)
print("Tensor: ",t1, "Data type: ", t1.dtype,"\n")
print("Tensor: ",t2, "Data type: ", t2.dtype,"\n")
print("Tensor: ",t3, "Data type: ", t3.dtype,"\n")
print("Tensor: ",t4, "Data type: ", t4.dtype,"\n")
```

Output:

```
Tensor: tensor([1, 2, 3, 4, 5, 6]) Data type: torch.int64
Tensor: tensor([1., 2., 3., 4., 5., 6.]) Data type: torch.float32
Tensor: tensor([1.5000, 3.4000, 6.8000, 9.3000, 7.0000, 2.8000]) Data type: torch.float64
Tensor: tensor([1.5000, 3.4000, 6.8000, 9.3000, 7.0000, 2.8000], dtype=torch.float64) Data type: torch.float64
```

## Restructuring Tensors in PyTorch

PyTorch allows you to modify the shape and size of tensors as desired. You can reshape tensors, resize them, or create transposed versions of tensors. These operations are useful for rearranging data or preparing it for specific computations.

Here are three common ways to change the structure of tensors in PyTorch:

`reshape(a, b)`

: This method returns a new tensor with the specified shape`(a, b)`

.`resize(a, b)`

: This method resizes the tensor to the specified shape`(a, b)`

and returns the same tensor.`transpose(a, b)`

: This method returns a tensor transposed in the dimensions specified by`(a, b)`

.

```
import torch
t = torch.tensor([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print("Reshaping")
print(t.reshape(6, 2))
print("\nResizing")
print(t.resize(2, 6))
print("\nTransposing")
print(t.transpose(1, 0))
```

Output:

```
Reshaping
tensor([[ 1, 2],
[ 3, 4],
[ 5, 6],
[ 7, 8],
[ 9, 10],
[11, 12]])
Resizing
tensor([[ 1, 2, 3, 4, 5, 6],
[ 7, 8, 9, 10, 11, 12]])
Transposing
tensor([[ 1, 5, 9],
[ 2, 6, 10],
[ 3, 7, 11],
[ 4, 8, 12]])
```

## Mathematical Operations on Tensors in PyTorch

PyTorch allows you to perform various mathematical operations on tensors, similar to NumPy arrays. The code for performing mathematical operations in PyTorch is intuitive and concise. PyTorch provides functions for addition, subtraction, multiplication, and division of tensors.

```
import torch
t1 = torch.tensor([1, 2, 3, 4])
t2 = torch.tensor([5, 6, 7, 8])
print("tensor2 + tensor1")
print(torch.add(t2, t1))
print("\ntensor2 - tensor1")
print(torch.sub(t2, t1))
print("\ntensor2 * tensor1")
print(torch.mul(t2, t1))
print("\ntensor2 / tensor1")
print(torch.div(t2, t1))
```

Output:

```
tensor2 + tensor1
tensor([ 6, 8, 10, 12])
tensor2 - tensor1
tensor([4, 4, 4, 4])
tensor2 * tensor1
tensor([ 5, 12, 21, 32])
tensor2 / tensor1
tensor([5., 3., 2., 2.])
```

## PyTorch Modules

PyTorch provides several modules that are essential for creating and training neural networks. These modules simplify the implementation of various tasks, such as gradient calculation, optimization algorithms, and construction of neural network layers.

### Autograd Module

The Autograd module in PyTorch enables automatic calculation of gradients without the need for manually implementing forward and backward passes for all layers. Backpropagation, an essential step in training any neural network, involves calculating gradients. By calling the `.backward()`

function, you can calculate gradients from the root to the leaf.

```
import torch
t1 = torch.tensor(1.0, requires_grad=True)
t2 = torch.tensor(2.0, requires_grad=True)
z = 100 * t1 * t2
z.backward()
print("dz/dt1 : ", t1.grad.data)
print("dz/dt2 : ", t2.grad.data)
```

Output:

```
dz/dt1 : tensor(200.)
dz/dt2 : tensor(100.)
```

### Optim Module

The Optim module in PyTorch provides various optimization algorithms for training neural networks. It includes commonly used algorithms such as Adam, SGD, and RMS-Prop. To use `torch.optim`

, you need to construct an Optimizer object that keeps track of the parameters and updates them accordingly.

```
import torch
optimizer = torch.optim.Adam(model.parameters(), lr=0.01) # Define optimizer
optimizer.zero_grad() # Set gradients to zero
# Perform forward and backward passes
optimizer.step() # Update parameters
```

### nn Module

The nn module in PyTorch helps in the construction of neural networks. It provides a wide range of functions for building layers, defining activation functions, and connecting different layers. For simple models with a single layer, you can use `nn.Sequential()`

to define the model. For more complex models, you can subclass the `nn.Module`

class.

```
import torch
import torch.nn as nn
# Model with a single layer using nn.Sequential()
model = nn.Sequential(
nn.Linear(in_features, out_features),
nn.Sigmoid(),
nn.Linear(in_features, out_features),
nn.Sigmoid()
)
# Model with multiple layers using nn.Module subclassing
class Model(nn.Module):
def __init__(self):
super(Model, self).__init__()
self.linear = torch.nn.Linear(1, 1)
def forward(self, x):
y_pred = self.linear(x)
return y_pred
```

## PyTorch Dataset and Dataloader

PyTorch provides the `torch.utils.data.Dataset`

class to handle custom datasets. To create your own dataset class, you need to implement two methods: `__len__()`

and `__getitem__()`

. The `torch.utils.data.DataLoader`

class supports automatic batching and parallel data loading, reducing the time required to load datasets.

The PyTorch DataLoader supports two types of datasets:

- Map-style datasets: In these datasets, data items are mapped to indexes. The
`__getitem__()`

method is used to retrieve the index of each item. - Iterable-style datasets: In these datasets, the
`__iter__()`

protocol is implemented to retrieve data samples in sequence.

## Building Neural Networks with PyTorch

Building neural networks with PyTorch involves several steps, including dataset preparation, defining the model architecture, forward propagation, loss computation, and backpropagation for weight optimization. Let’s walk through the process step by step:

### Dataset Preparation

Before training a neural network, you need to prepare the dataset. In PyTorch, everything is represented in the form of tensors, so you should convert your data to tensors. For example, if you have input data `X`

and target data `y`

, you can convert them to tensors using `torch.Tensor()`

.

```
import torch
X = torch.Tensor([[1], [2], [3], [4], [5], [6]])
y = torch.Tensor([[5], [10], [15], [20], [25], [30]])
```

### Building the Model

To build a neural network, you need to define the number of input layers, hidden layers, and output layers. You also need to initialize the weights. PyTorch provides functions like `torch.randn()`

to generate random values for weight matrices.

```
import torch
import torch.nn as nn
model = nn.Linear(in_features, out_features)
```

### Forward Propagation

Forward propagation involves feeding the input data to the neural network and performing matrix multiplication between the weights and inputs. This can be easily done using `torch.nn.functional`

functions like `torch.sigmoid()`

or `torch.relu()`

.

### Loss Computation

PyTorch provides various loss functions in the `torch.nn`

module. These loss functions are used to measure the error between the predicted values and the target values. Commonly used loss functions include mean squared error (MSE), cross-entropy loss, and L1 loss.

```
import torch
import torch.nn as nn
loss_fn = nn.L1Loss()
loss = loss_fn(y_pred, y)
```

### Backpropagation

Backpropagation is used to optimize the weights of the neural network. It involves calculating the gradients and updating the weights such that the loss is minimized. PyTorch’s Autograd module automatically calculates gradients, so you don’t need to compute them manually.

```
import torch
optimizer = torch.optim.Adam(model.parameters(), lr=0.01) # Define optimizer
optimizer.zero_grad() # Set gradients to zero
# Perform forward and backward passes
optimizer.step() # Update parameters
```

Now that we have covered the basics of PyTorch, you are ready to dive deeper into the world of deep learning and explore more advanced concepts and techniques. PyTorch provides extensive documentation and a vibrant community that can help you along your journey. So, grab your coding gloves and start building amazing neural networks with PyTorch!

## Conclusion

In this article, we explored the fundamentals of PyTorch, including tensor operations, tensor creation, restructuring tensors, mathematical operations, PyTorch modules, dataset handling, and building neural networks. We covered the installation process, various tensor operations, and the importance of PyTorch modules like Autograd, Optim, and nn. We also discussed the Dataset and Dataloader classes for efficient handling of datasets. Building neural networks with PyTorch involves dataset preparation, model architecture definition, forward propagation, loss computation, and backpropagation for weight optimization.

PyTorch offers a user-friendly and powerful platform for deep learning, enabling developers to create and train complex neural networks effortlessly. With its extensive library support and vibrant community, PyTorch continues to be a top choice for machine learning practitioners. So, unleash your creativity, explore the possibilities, and embark on your journey of deep learning with PyTorch!

Are you interested in AI but don’t know where to start? Want to understand the role of an AI Architect? Check out our page and watch our informative video.