Five tensor operations in PyTorch 
Tags: pytorch, python, deeplearning, datascience
Published: 2020-11-26 02:14:15

## Introduction 
PyTorch is an amazing deep learning library for tensor operations and deep learning, here is a list of 5 amazing functions available in the torch module. This post is part of an assignment from a deep learning course available in [jovian](https://jovian.ai/learn/deep-learning-with-pytorch-zero-to-gans) in collaboration with freecodecamp for free, and part of the assignment was to write a post about tensor operations with PyTorch and I decided to post it here. 
### Content
1. torch.complex
2. torch.polar
3. torch.heaviside
4. torch.chunk
5. torch.where

#### 1. torch.complex 
**parameters:**
* real: a tensor of datatype float or double.
* imag:  a tensor of datatype float

Given a tensor `real` that represents the real part of a complex number, and `imag` that represents the imaginary part, this function will return a new tensor that represents complex number that following rule: 

<a href="https://www.codecogs.com/eqnedit.php?latex=z&space;=&space;real&space;&plus;&space;(imag)j" target="_blank"><img src="https://latex.codecogs.com/gif.latex?z&space;=&space;real&space;&plus;&space;(imag)j" title="z = real + (imag)j" /></a>

**Example:** 


```python
Example 
real = torch.tensor([1,2], dtype=torch.float32)
print(real)
imag = torch.tensor([3,4], dtype=torch.float32)
print(imag)
z = torch.complex(real,imag)
print(z)
```
**Output** 
```bash
tensor([1., 2.])
tensor([3., 4.])
tensor([1.+3.j, 2.+4.j])
```
Giving two tensor of size 2 each, we can create a new complex tensor tensor that follows the following rule: `real[i] + (img[i])j`

#### 2. torch.polar 
**Parameters:** 
* abs: the absolute value of the complex tensor, must be a tensor of datatype float. This is calculated by using the following formula: 
<a href="https://www.codecogs.com/eqnedit.php?latex=absolute&space;=&space;\sqrt{real^{2}&space;&plus;&space;imag^{2}}" target="_blank"><img src="https://latex.codecogs.com/gif.latex?absolute&space;=&space;\sqrt{real^{2}&space;&plus;&space;imag^{2}}" title="absolute = \sqrt{real^{2} + imag^{2}}" /></a>

* angle: the angle of the complex tensor. 

Giving a tensor that represents the absolute value of a complex tensor and a tensor that represents the angle, this function will return the tensor representation in polar coordinates according to the following rule: 

<a href="https://www.codecogs.com/eqnedit.php?latex=out&space;=&space;abs\cdot&space;\cos&space;(angle)&space;&plus;&space;abs\cdot&space;\sin(angle)j" target="_blank"><img src="https://latex.codecogs.com/gif.latex?out&space;=&space;abs\cdot&space;\cos&space;(angle)&space;&plus;&space;abs\cdot&space;\sin(angle)j" title="out = abs\cdot \cos (angle) + abs\cdot \sin(angle)j" /></a>


**Example:** 

```python 
import numpy as np
abs = torch.tensor([1,2], dtype=torch.float64)
print(abs)
angle = torch.tensor([np.pi/2,5*np.pi/4], dtype=torch.float64)
print(angle)
z = torch.polar(abs, angle)
print(z)

```

**Output**
```bash 
tensor([1., 2.], dtype=torch.float64)
tensor([1.5708, 3.9270], dtype=torch.float64)
tensor([ 6.1232e-17+1.0000j, -1.4142e+00-1.4142j], dtype=torch.complex128)
```

this will return a tensor that represents a complex tensor in polar coordinates.

#### 3.torch.heaviside 

**Parameters:** 
* input:an input tensor.
* values: a tensor that will be used when input[i] are zeros. 

for each value in input computes the heaviside step function that is define by the following formula: 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/8vpnm1pkgg61lgnlcmxf.png)

**Example:** 
```python
input = torch.tensor([-1.5,0,2.0])
print(input)
values = torch.tensor([0.5])
print(values)
heaviside = torch.heaviside(input,values)
print(heaviside)
```

**Output**
```bash
tensor([-1.5000,  0.0000,  2.0000])
tensor([0.5000])
tensor([0.0000, 0.5000, 1.0000])
```
As you can see the values are replaced by following the heaviside formula of above. 

#### 4. torch.chunk
**Parameters:** 
* input: the tensor to split
* chunks: number of chunks to return
* dim: dimension along which to split the tensor

Giving a tensor and a number of chunks this function return tensors according to the number of chunks over the specified dimension. 
**Example:** 
```python 
my_tensor = torch.tensor([
                          [5,5,6.,6],
                          [6,5,3.,7], 
                          [6,8,9,0]
                          ])
chunk = torch.chunk(my_tensor, 2,dim=0)
print(chunk)
```
**Output** 
```bash
(tensor([[5., 5., 6., 6.],
        [6., 5., 3., 7.]]), tensor([[6., 8., 9., 0.]]))
```
as you can see the function returns two new tensors based on the number of chunks and the specified dimension. In this case was dimension 0 so the split will be row-wise, the first chunk will be the two first rows and the second the last row. 

#### 5. torch.where 
**Parameters:**
* condition: a tensor where each value is a boolean.
* x: x[i] will be selected if condition[i] is true. 
* y: y[i] will be selected if condition[i] is false. 

Given two tensor x and y and a condition, returns a tensor where x[i] will be selected if condition[i] is true, otherwise y[i] will be selected.

**Example**
```python
x = torch.randn(3,2)
print(x)
y = torch.ones(3,2)
print(y)
result =torch.where(x>0,x,y)
print(result)
```

**Output**
```bash
tensor([[ 0.1014, -1.7573],
        [-1.0143, -0.5330],
        [-1.1203,  1.3897]])
tensor([[1., 1.],
        [1., 1.],
        [1., 1.]])
tensor([[0.1014, 1.0000],
        [1.0000, 1.0000],
        [1.0000, 1.3897]])
```

As we can see if the value x[i] is greater than 0 we kept the value otherwise will be replaced by y[i]

### Conclusion 
As we can see we have many functions available in the torch module, specially to work with tensors, we saw in this post 5 of them an I tried to describe each of them. But the torch documentation is the main resource for this post so I think is better to visit it and read it. 

### References
* Official documentation for tensor operation:[Pytorch](https://pytorch.org/docs/stable/torch.html)
* [jovian deeplearning course](https://jovian.ai/learn/deep-learning-with-pytorch-zero-to-gans)
* some mathematical formulas were written by using [Codecogs project](https://www.codecogs.com/latex/eqneditor.php)
* my [jupyter](https://jovian.ai/alexc957/01-tensor-operations) notebook that contains the code of this post with other examples.