Flatten, Reshape, and Squeeze Explained - Tensors for Deep Learning with PyTorch (2024)

Reshaping operations - Tensors for deep learning

Welcome back to this series on neural network programming. Starting with this post in this series, we'll begin using the knowledge we've learned about tensors up to this point and start covering essential tensor operations for neural networks and deep learning.

Flatten, Reshape, and Squeeze Explained - Tensors for Deep Learning with PyTorch (1)

We'll kick things off with reshaping operations. Without further ado, let's get started.

Tensor operation types

Before we dive in with specific tensor operations, let's get a quick overview of the landscape by looking at the main operation categories that encompass the operations we'll cover. We have the following high-level categories of operations:

  1. Reshaping operations
  2. Element-wise operations
  3. Reduction operations
  4. Access operations

There are a lot of individual operations out there, so much so that it can sometimes be intimidating when you're just beginning, but grouping similar operations into categories based on their likeness can help make learning about tensor operations more manageable.

The reason for showing these categories is to give you the goal of understanding all four of these by the end of this section in the series.

Flatten, Reshape, and Squeeze Explained - Tensors for Deep Learning with PyTorch (2)

The goal of these posts on tensor operations is to not only showcase specific tensor operations commonly used, but to also describe the operation landscape. Having knowledge of the types of operations that exist can stay with us longer than just knowing or memorizing individual operations.

Keep this in mind and work towards understanding these categories as we explore each of them. Let's jump in now with reshaping operations.

Reshaping operations for tensors

Reshaping operations are perhaps the most important type of tensor operations. This is because, like we mentioned in the post where we introduced tensors, the shape of a tensor gives us something concrete we can use to shape an intuition for our tensors.

An analogy for tensors

Suppose we are neural network programmers, and as such, we typically spend our days building neural networks. To do our job, we use various tools.

We use math tools like calculus and linear algebra, computer science tools like Python and PyTorch, physics and engineering tools like CPUs and GPUs, and machine learning tools like neural networks, layers, activation functions, etc.

Flatten, Reshape, and Squeeze Explained - Tensors for Deep Learning with PyTorch (3)

Our task is to build neural networks that can transform or map input data to the correct output we are seeking.

The primary ingredient we use to produce our product, a function that maps inputs to correct outputs, is data.

Data is somewhat of an abstract concept, so when we want to actually use the concept of data to implement something, we use a specific data structure called a tensor that can be efficiently implemented in code. Tensors have properties, mathematical and otherwise, that allow us to do our work.

Tensors are the primary ingredient that neural network programmers use to produce their product, intelligence.

This is very similar to how a baker uses dough to produce, say, a pizza. The dough is the input used to create an output, but before the pizza is produced there is usually some form of reshaping of the input that is required.

Flatten, Reshape, and Squeeze Explained - Tensors for Deep Learning with PyTorch (4)

As neural network programmers, we have to do the same with our tensors, and usually shaping and reshaping our tensors is a frequent task.

Our networks operate on tensors, after all, and this is why understanding a tensor's shape and the available reshaping operations are super important.

Instead of producing pizzas, we are producing intelligence! This may be lame, but whatever. Let's jump in with reshaping operations.

Tensor shape review

Suppose that we have the following tensor:

> t = torch.tensor([ [1,1,1,1], [2,2,2,2], [3,3,3,3]], dtype=torch.float32)

To determine the shape of this tensor, we look first at the rows 3 and then the columns 4, and so this tensor is a 3 x 4 rank 2 tensor. Remember, rank is a word that is commonly used and just means the number of dimensions present within the tensor.

In PyTorch, we have two ways to get the shape:

> t.size()torch.Size([3, 4])> t.shapetorch.Size([3, 4])

In PyTorch the size and shape of a tensor mean the same thing.

Typically, after we know a tensor's shape, we can deduce a couple of things. First, we can deduce the tensor's rank. The rank of a tensor is equal to the length of the tensor's shape.

> len(t.shape)2

We can also deduce the number of elements contained within the tensor. The number of elements inside a tensor (12 in our case) is equal to the product of the shape's component values.

> torch.tensor(t.shape).prod()tensor(12)

In PyTorch, there is a dedicated function for this:

> t.numel()12

The number of elements contained within a tensor is important for reshaping because the reshaping must account for the total number of elements present. Reshaping changes the tensor's shape but not the underlying data. Our tensor has 12 elements, so any reshaping must account for exactly 12 elements.

Reshaping a tensor in PyTorch

Let's look now at all the ways in which this tensor t can be reshaped without changing the rank:

> t.reshape([1,12])tensor([[1., 1., 1., 1., 2., 2., 2., 2., 3., 3., 3., 3.]])> t.reshape([2,6])tensor([[1., 1., 1., 1., 2., 2.], [2., 2., 3., 3., 3., 3.]])> t.reshape([3,4])tensor([[1., 1., 1., 1.], [2., 2., 2., 2.], [3., 3., 3., 3.]])> t.reshape([4,3])tensor([[1., 1., 1.], [1., 2., 2.], [2., 2., 3.], [3., 3., 3.]])> t.reshape(6,2)tensor([[1., 1.], [1., 1.], [2., 2.], [2., 2.], [3., 3.], [3., 3.]])> t.reshape(12,1)tensor([[1.], [1.], [1.], [1.], [2.], [2.], [2.], [2.], [3.], [3.], [3.], [3.]])

Using the reshape() function, we can specify the row x column shape that we are seeking. Notice how all of the shapes have to account for the number of elements in the tensor. In our example this is:

rows * columns = 12 elements

We can use the intuitive words rows and columns when we are dealing with a rank 2 tensor. The underlying logic is the same for higher dimensional tenors even though we may not be able to use the intuition of rows and columns in higher dimensional spaces. For example:

> t.reshape(2,2,3)tensor([ [ [1., 1., 1.], [1., 2., 2.] ], [ [2., 2., 3.], [3., 3., 3.] ]])

In this example, we increase the rank to 3, and so we lose the rows and columns concept. However, the product of the shape's components (2,2,3) still has to be equal to the number of elements in the original tensor ( 12).

Note that PyTorch has another function that you may see called view() that does the same thing as the reshape() function, but don't let these names throw you off. No matter which deep learning framework we are using, these concepts will be the same.

Changing shape by squeezing and unsqueezing

The next way we can change the shape of our tensors is by squeezing and unsqueezing them.

  • Squeezing a tensor removes the dimensions or axes that have a length of one.
  • Unsqueezing a tensor adds a dimension with a length of one.

These functions allow us to expand or shrink the rank (number of dimensions) of our tensor. Let's see this in action.

> print(t.reshape([1,12]))> print(t.reshape([1,12]).shape)tensor([[1., 1., 1., 1., 2., 2., 2., 2., 3., 3., 3., 3.]])torch.Size([1, 12])> print(t.reshape([1,12]).squeeze())> print(t.reshape([1,12]).squeeze().shape)tensor([1., 1., 1., 1., 2., 2., 2., 2., 3., 3., 3., 3.])torch.Size([12])> print(t.reshape([1,12]).squeeze().unsqueeze(dim=0))> print(t.reshape([1,12]).squeeze().unsqueeze(dim=0).shape)tensor([[1., 1., 1., 1., 2., 2., 2., 2., 3., 3., 3., 3.]])torch.Size([1, 12])

Notice how the shape changes as we squeeze and unsqueeze the tensor.

Let's look at a common use case for squeezing a tensor by building a flatten function.

Flatten a tensor

A flatten operation on a tensor reshapes the tensor to have a shape that is equal to the number of elements contained in the tensor. This is the same thing as a 1d-array of elements.

Flattening a tensor means to remove all of the dimensions except for one.

Let's create a Python function called flatten():

def flatten(t): t = t.reshape(1, -1) t = t.squeeze() return t

The flatten() function takes in a tensor t as an argument.

Since the argument t can be any tensor, we pass -1 as the second argument to the reshape() function. In PyTorch, the -1 tells the reshape() function to figure out what the value should be based on the number of elements contained within the tensor. Remember, the shape must equal the product of the shape's component values. This is how PyTorch can figure out what the value should be, given a 1 as the first argument.

Since our tensor t has 12 elements, the reshape() function is able to figure out that a 12 is required for the length of the second axis.

After squeezing, the first axis (axis-0) is removed, and we obtain our desired result, a 1d-array of length 12.

Here's an example of this in action:

> t = torch.ones(4, 3)> ttensor([[1., 1., 1.], [1., 1., 1.], [1., 1., 1.], [1., 1., 1.]])> flatten(t)tensor([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])

In a future post when we begin building a convolutional neural network, we will see the use of this flatten() function. We'll see that flatten operations are required when passing an output tensor from a convolutional layer to a linear layer.

In these examples, we have flattened the entire tensor, however, it is possible to flatten only specific parts of a tensor. For example, suppose we have a tensor of shape [2,1,28,28] for a CNN. This means that we have a batch of 2 grayscale images with height and width dimensions of 28 x 28, respectively.

Here, we can specifically flatten the two images. To get the following shape: [2,1,784]. We could also squeeze off the channel axes to get the following shape: [2,784].

Concatenating tensors

We combine tensors using the cat() function, and the resulting tensor will have a shape that depends on the shape of the two input tensors.

Suppose we have two tensors:

> t1 = torch.tensor([ [1,2], [3,4]])> t2 = torch.tensor([ [5,6], [7,8]])

We can combine t1 and t2 row-wise (axis-0) in the following way:

> torch.cat((t1, t2), dim=0)tensor([[1, 2], [3, 4], [5, 6], [7, 8]])

We can combine them column-wise (axis-1) like this:

> torch.cat((t1, t2), dim=1)tensor([[1, 2, 5, 6], [3, 4, 7, 8]])

When we concatenate tensors, we increase the number of elements contained within the resulting tensor. This causes the component values within the shape (lengths of the axes) to adjust to account for the additional elements.

> torch.cat((t1, t2), dim=0).shapetorch.Size([4, 2])> torch.cat((t1, t2), dim=1).shapetorch.Size([2, 4])

Conclusion about reshaping tensors

We should now have a good understanding of what it means to reshape a tensor. Any time we change a tensor's shape, we are said to be reshaping the tensor.

Remember the analogy. Bakers work with dough and neural network programmers work with tensors. Even though the concept of shaping is the same, instead of creating baked goods, we are creating intelligence. I'll see you in the next one.

Flatten, Reshape, and Squeeze Explained - Tensors for Deep Learning with PyTorch (2024)

FAQs

How do you reshape a flattened tensor in PyTorch? ›

A tensor can be flattened into a one-dimensional tensor by reshaping it using the method torch. flatten(). This method supports both real and complex-valued input tensors. It takes a torch tensor as its input and returns a torch tensor flattened into one dimension.

What is the difference between view (- 1 and flatten PyTorch? ›

view() works only on contiguous data, while . flatten() works on both contiguous and non contiguous data.

What is the difference between PyTorch reshape and Unsqueeze? ›

Use view (or reshape ) when you want to generically reshape a tensor. If you want to specifically add a superficial dimension (e.g. for treating a single element like a batch, or to concatenate with another tensor), unsqueeze is a more convenient (and explicit) synonym, but the underlying operation is the same.

What is the difference between torch flatten and nn flatten? ›

Important difference: A notable distinction is that torch. flatten() always returns an 1D tensor as result, provided that the input is at least 1D or greater, whereas nn. Flatten() always returns a 2D tensor, provided that the input is at least 2D or greater (With 1D tensor as input, it will throw an IndexError).

How does reshape () work? ›

reshape() function allows us to reshape an array in Python. Reshaping basically means, changing the shape of an array. And the shape of an array is determined by the number of elements in each dimension. Reshaping allows us to add or remove dimensions in an array.

What is the difference between Unsqueeze and squeeze? ›

Squeezing a tensor removes the dimensions or axes that have a length of one. Unsqueezing a tensor adds a dimension with a length of one.

How does PyTorch flatten work? ›

Flattens input by reshaping it into a one-dimensional tensor. If start_dim or end_dim are passed, only dimensions starting with start_dim and ending with end_dim are flattened. The order of elements in input is unchanged.

What is the purpose of flatten? ›

Flatten layer is used to make the multidimensional input one-dimensional, commonly used in the transition from the convolution layer to the full connected layer. Based on whether TensorSpace Model load a pre-trained model before initialization, configure Layer in different ways.

Why flatten is used in CNN? ›

Flattening is used to convert all the resultant 2-Dimensional arrays from pooled feature maps into a single long continuous linear vector. The flattened matrix is fed as input to the fully connected layer to classify the image.

Why PyTorch is better than TensorFlow? ›

PyTorch vs TensorFlow: Debugging

As PyTorch uses a standard python debugger, the user does not need to learn another debugger. Since PyTorch uses immediate execution (i.e., eager mode), it is said to be easier to use than TensorFlow when it comes to debugging.

Which is the best loss function in PyTorch? ›

Binary Cross-Entropy Loss / Log Loss

This is the most common loss function used in classification problems. The cross-entropy loss decreases as the predicted probability converges to the actual label. It measures the performance of a classification model whose predicted output is a probability value between 0 and 1 .

Is PyTorch more efficient than TensorFlow? ›

In general, TensorFlow and PyTorch implementations show equal accuracy. However, the training time of TensorFlow is substantially higher, but the memory usage was lower. PyTorch allows quicker prototyping than TensorFlow, but TensorFlow may be a better option if custom features are needed in the neural network.

Why use flatten before dense? ›

Flatten layers are used when you got a multidimensional output and you want to make it linear to pass it onto a Dense layer.

What is the difference between flatten and fully connected layer? ›

Flattening is converting the data into a 1-dimensional array for inputting it to the next layer. We flatten the output of the convolutional layers to create a single long feature vector. And it is connected to the final classification model, which is called a fully-connected layer.

What is the difference between layers flatten and layers dense? ›

The Flatten layer converts the 28x28x50 output of the convolutional layer into a single one-dimensional vector, that can be used as input for a dense layer. The last dense layer has the most parameters. This layer connects every single output 'pixel' from the convolutional layer to the 10 output classes.

How do you change the shape of a tensor? ›

How to reshape a tensor? This is possible by using "reshape" function available in the tensorflow, the function will return a new tensor which will have same values as tensor in the same order, except the shape will be different.

What is the difference between reshape () and flatten ()? ›

Use flatten() when you want to create 1-D array where performing changes will not affect your original array. Use reshape() when you need to create different shapes of an array and changing any of those will affect other arrays.

Which function is used to change the shape of a tensor? ›

reshape(t, []) reshapes a tensor t with one element to a scalar.

What is the PyTorch flatten shape? ›

PyTorch Flatten is used to reshape any tensor with different dimensions to a single dimension so that we can do further operations on the same input data. The shape of the tensor will be the same as that of the number of elements in the tensor.

Top Articles
Latest Posts
Article information

Author: Msgr. Refugio Daniel

Last Updated:

Views: 5463

Rating: 4.3 / 5 (54 voted)

Reviews: 85% of readers found this page helpful

Author information

Name: Msgr. Refugio Daniel

Birthday: 1999-09-15

Address: 8416 Beatty Center, Derekfort, VA 72092-0500

Phone: +6838967160603

Job: Mining Executive

Hobby: Woodworking, Knitting, Fishing, Coffee roasting, Kayaking, Horseback riding, Kite flying

Introduction: My name is Msgr. Refugio Daniel, I am a fine, precious, encouraging, calm, glamorous, vivacious, friendly person who loves writing and wants to share my knowledge and understanding with you.