Exploring Tensor functions in Pytorch
Published:
I am fairly comfortable building Deep Neural Networks (DNN) with Keras library and infact I built a CNN model - Plantmd to predict plant diseases as part of Insight Data Science fellowship program. However as people often say, it’s always important to learn a new language/program to see how it differs from the language/program that you are comfortable. So with this in mind, I have decided to take spend time to do the exciting Deep Learning with PyTorch: Zero to GANs workshop on Jovian.ml.
As part of the first assignment, we were asked to pick out five torch.Tensor functions in Pytorch and use them with examples. So here are my five ‘torch.Tensor` functions.
- torch.as_tensor()
- torch.arange()
- torch.reshape()
- torch.abs()
- torch.is_leaf()
1. torch.as_tensor()
In Pytorch the recommended way to build tensors are either using torch.tensor() and torch.as_tensor(). So what is the difference? torch.tensor() always copies the data whereas torch.as_tensor() always tries to avoid copies of the data. This is especially useful if you have a numpy array and want to avoid copying the numpy array into a tensor.
1.1 Let’s understand this by creating a numpy array first
1.2 Create a tensor using torch.tensor() function
1.3 Create a tensor using torch.as_tensor() function
As you can see, there is no difference in the outputs between torch.tensor(arr) or torch.as_tensor(arr)
1.4 Now let’s create a sligtly complicated numpy array
The tensor creation failed with torch.as_tensor() function here because the numpy array that was created is a 2-D array with rows that have different lengths which works for numpy arrays but fails during conversion from numpy to a tensor.
To summarize, torch.tensor() copies the numpy array whereas torch.as_tensor() shares the memory with the numpy array
2. torch.arange()
This function returns a 1-D tensor of size (end-start/step) with values from the intervals start, end taken with common difference step from start.
2.1 Let’s first create a tensor
In the above example, torch.arange() function returns numbers 0, 1, 2, 3, 4, 5 with an interval of 1. Instead of specifiying the start (the default is 0) and the step size (the default is 1), you can just give the end number (in this example 5) and torch.arange() will generate numbers 0-5 similar to example 1.
2.2 Now let’s see an example where things can go wrong
In this example, the function assumes that start is 0, end is -5 and step size is 1 and it is not able to return the numbers from 0, -5 with a step size of 1. This can be fixed by giving an upper bound (for example 0).
To summarize torch.arange() is a very convenient function to generate a sequence of numbers from start to end with a user specified step size.
3. torch.reshape()
This function returns a tensor with the same data and number of elements as input but with the specified shape.
3.1 Let’s see this with an example
As can be seen in the above example, torch.reshape() has returned a tensor with the same data but with a specified shape of 2 x 2 for earlier shape of 1 * 4.
What if you want to convert the input tensor of shape 4 x 1 into an array of 1 x 4, then you can just specify (-1, 1) as shown in this example. Infact you can leave the second number and just specify (-1,)
3.2 Specifying wrong reshape parameter
This is the frequent mistake that people often do with torch.reshape() function. The above error indicates that the original input is a size of 4 x 1 whereas, we ask it to generate a tensor of shape 2 x 3 which is not possible. This is because 2 x 3 = 6 whereas the original size is 4 x 1 = 4.
To summarize, reshaping a tensor using torch.reshape() is quite important in matrix multiplication and other functionalities.
4. torch.abs()
The function torch.abs() computes element wise absolute value of an input tensor.
4.1 Let’s see an simple example
As can be seen, torch.abs() was able to convert all the negative values into positive values from an input tensor consisting of 3 elements.
torch.abs() not only works on the 1-D tensor but also can also work on 2-D tensors such as matrices as show in this example.
4.2 Using torch.abs() on a wrong tensor type
The error here indicates the the torch.abs() only works on tensors that have numbers (floats, integers etc.,) and not on boolean values (TRUE/FALSE, Yes/No etc.,). So make sure to check the tensor type before using torch.abs() function.
To summarize torch.abs() is a nice little functionality in Pytorch that returns the absolute value of a numerical tensor that is of any dimension.
5. torch.is_leaf()
A leaf node/variable is a variable that is at the beginning of the graph. That means that no operation is tracked by the autograd engine created it. All tensors that have requires_grad set to False will be leaf tensors by convention.
5.1 Let’s understand this with an example
Here the a tensor is a leaf variable
Let’s create another example where a tensor is not a leaf variable.
As can be seen in the above example, the tensor b was not created by the user but was created by an operation that cast a float tensor into a double tensor. So the tensor b is not a leaf variable.
5.2 Creating a tensor with gradient that has wrong data type
In this example, we tried to check if the tensor is a leaf variable or not, but before we can check that out, we get an error as shown here.
If you want to create gradients for an tensor, floating point data type are only acceptable. So make sure you fix that before you can use is_leaf() function.
To summarize is_leaf() is a convenient function to check if the variable is at the beginning of the graph or not so that you don’t have to keep a track of it manually.
Conclusion
This notebook explores five Tensor functions in Pytorch with detailed examples including the cases where things go wrong. Understanding Tensor functions in Pytroch is very important so that they can be applied correctly in downstream analysis.
If you want to try these functions by yourself, visit this notebook, fork/clone and press Run.
Reference Links
Official documentation for torch.Tensor
My Jovian notebook
