The order of the elements in memory in python, pytorch, numpy, c++ etc. are in row-major ordering:

[ first, second
  third, forth  ]

While in matlab, fortran, etc. the order is column major:

[ first,  third
  second, fourth ]

For higher dimensional tensors, this means elements are ordered from the last dimension to the first.

You can easily visualize it using torch.arange followed by .view:

a = torch.arange(24)
a.view(2,3,4)

Results with

tensor([[[ 0,  1,  2,  3],
    [ 4,  5,  6,  7],
    [ 8,  9, 10, 11]],

   [[12, 13, 14, 15],
    [16, 17, 18, 19],
    [20, 21, 22, 23]]])

As you can see the elements are ordered first by row (last dimension), then by column, and finally by the first dimension.

When you reshape a tensor, you do not change the underlying order of the elements, only the shape of the tensor. However, if you permute a tensor - you change the underlying order of the elements.

Look at the difference between a.view(3,2,4) and a.permute(0,1,2) - the shape of the resulting two tensors is the same, but not the ordering of elements:

In []: a.view(3,2,4)
Out[]:
tensor([[[ 0,  1,  2,  3],
         [ 4,  5,  6,  7]],

        [[ 8,  9, 10, 11],
         [12, 13, 14, 15]],

        [[16, 17, 18, 19],
         [20, 21, 22, 23]]])

In []: a.permute(1,0,2)
Out[]:
tensor([[[ 0,  1,  2,  3],
         [12, 13, 14, 15]],

        [[ 4,  5,  6,  7],
         [16, 17, 18, 19]],

        [[ 8,  9, 10, 11],
         [20, 21, 22, 23]]])
Answer from Shai on Stack Overflow
Top answer
1 of 3
8

The order of the elements in memory in python, pytorch, numpy, c++ etc. are in row-major ordering:

[ first, second
  third, forth  ]

While in matlab, fortran, etc. the order is column major:

[ first,  third
  second, fourth ]

For higher dimensional tensors, this means elements are ordered from the last dimension to the first.

You can easily visualize it using torch.arange followed by .view:

a = torch.arange(24)
a.view(2,3,4)

Results with

tensor([[[ 0,  1,  2,  3],
    [ 4,  5,  6,  7],
    [ 8,  9, 10, 11]],

   [[12, 13, 14, 15],
    [16, 17, 18, 19],
    [20, 21, 22, 23]]])

As you can see the elements are ordered first by row (last dimension), then by column, and finally by the first dimension.

When you reshape a tensor, you do not change the underlying order of the elements, only the shape of the tensor. However, if you permute a tensor - you change the underlying order of the elements.

Look at the difference between a.view(3,2,4) and a.permute(0,1,2) - the shape of the resulting two tensors is the same, but not the ordering of elements:

In []: a.view(3,2,4)
Out[]:
tensor([[[ 0,  1,  2,  3],
         [ 4,  5,  6,  7]],

        [[ 8,  9, 10, 11],
         [12, 13, 14, 15]],

        [[16, 17, 18, 19],
         [20, 21, 22, 23]]])

In []: a.permute(1,0,2)
Out[]:
tensor([[[ 0,  1,  2,  3],
         [12, 13, 14, 15]],

        [[ 4,  5,  6,  7],
         [16, 17, 18, 19]],

        [[ 8,  9, 10, 11],
         [20, 21, 22, 23]]])
2 of 3
1

Your example, using numpy methods (I don't have tensorflow installed):

In [559]: x = np.array([
     ...:     [
     ...:         [[0.4495, 0.2356],
     ...:           [0.4069, 0.2361],
     ...:           [0.4224, 0.2362]],
     ...: 
     ...:          [[0.4357, 0.6762],
     ...:           [0.4370, 0.6779],
     ...:           [0.4406, 0.6663]]
     ...:     ],
     ...:     [
     ...:         [[0.5796, 0.4047],
     ...:           [0.5655, 0.4080],
     ...:           [0.5431, 0.4035]],
     ...: 
     ...:          [[0.5338, 0.6255],
     ...:           [0.5335, 0.6266],
     ...:           [0.5204, 0.6396]]
     ...:     ]
     ...: ])
In [560]: x.shape
Out[560]: (2, 2, 3, 2)

In [562]: s1=np.concatenate((x[0,0],x[0,1]), axis=1)
In [563]: s2=np.concatenate((x[1,0],x[1,1]), axis=1)
In [564]: s1.shape
Out[564]: (3, 4)

In [565]: new =np.concatenate((s1,s2), axis=0)
In [566]: new.shape
Out[566]: (6, 4)
In [567]: new.reshape(2,3,4)
Out[567]: 
array([[[0.4495, 0.2356, 0.4357, 0.6762],
        [0.4069, 0.2361, 0.437 , 0.6779],
        [0.4224, 0.2362, 0.4406, 0.6663]],

       [[0.5796, 0.4047, 0.5338, 0.6255],
        [0.5655, 0.408 , 0.5335, 0.6266],
        [0.5431, 0.4035, 0.5204, 0.6396]]])

numpy has a stack that joins arrays on a new axis, so we can skip the last concatenate and reshape with

np.stack((s1,s2))    # or
np.array((s1,s2))

The direct way to get there is to swap the middle 2 dimensions:

In [569]: x.transpose(0,2,1,3).shape
Out[569]: (2, 3, 2, 2)

In [571]: x.transpose(0,2,1,3).reshape(2,3,4)
Out[571]: 
array([[[0.4495, 0.2356, 0.4357, 0.6762],
        [0.4069, 0.2361, 0.437 , 0.6779],
        [0.4224, 0.2362, 0.4406, 0.6663]],

       [[0.5796, 0.4047, 0.5338, 0.6255],
        [0.5655, 0.408 , 0.5335, 0.6266],
        [0.5431, 0.4035, 0.5204, 0.6396]]])

reshape can be used to combine 'adjacent' dimensions, but doesn't reorder the underlying data. That is x.ravel() remains the same with reshape. While reshape of (2,2,3,2) to (2,3,4) is allowed, the apparent order of values probably is not what you want. That might be easier to see if you try to reshape

In [572]: np.arange(6).reshape(2,3)
Out[572]: 
array([[0, 1, 2],
       [3, 4, 5]])
In [573]: _.reshape(3,2)
Out[573]: 
array([[0, 1],
       [2, 3],
       [4, 5]])

compare that with a transpose:

In [574]: np.arange(6).reshape(2,3).transpose(1,0)
Out[574]: 
array([[0, 3],
       [1, 4],
       [2, 5]])

The transpose/swap that I did in [569] may be hard to understand. There are enough different ways of reordering dimensions, that it's hard to generalize.

🌐
GitHub
github.com › pytorch › pytorch › issues › 2013
Documentation for how pytorch tensor.view() rearranges dimensions? · Issue #2013 · pytorch/pytorch
July 8, 2017 - @mhgump torch.view only changes the sizes of the tensor, while the underlying content remains the same, pretty much like numpy reshape, so the order is the same as the order in the underlying tensor.
People also ask

What does view() do in PyTorch?
It returns a tensor with a different shape that shares the original's data, without copying it.
🌐
pythonguides.com
pythonguides.com › pytorch-view
PyTorch view(): Reshape Tensors Without Copying
Where is Tensor.view documented?
See torch.Tensor.view in the PyTorch docs.
🌐
pythonguides.com
pythonguides.com › pytorch-view
PyTorch view(): Reshape Tensors Without Copying
Does changing a view change the original tensor?
Yes, they share memory. Use .clone() to get an independent copy.
🌐
pythonguides.com
pythonguides.com › pytorch-view
PyTorch view(): Reshape Tensors Without Copying
🌐
Medium
medium.com › analytics-vidhya › pytorch-contiguous-vs-non-contiguous-tensor-view-understanding-view-reshape-73e10cdfa0dd
[Pytorch] Contiguous vs Non-Contiguous Tensor / View — Understanding view(), reshape()…
February 26, 2024 - Then, the data is consumed from the beginning of the 1D data sequence, and is filled into these boxes from the innermost spots, one-by-one until the box is full, it moves to the next dimension (box). This follows a contiguous order.
🌐
jdhao's digital space
jdhao.github.io › 2019 › 07 › 10 › pytorch_view_reshape_transpose_permute
Difference between view, reshape, transpose and permute in PyTorch · jdhao's digital space
January 9, 2022 - if you need a copy use clone() if you need the same storage use view(). The semantics of reshape() are that it may or may not share the storage and you don’t know beforehand. As a side note, I found that torch version 0.4.1 and 1.0.1 behaves differently when you print the id of original tensor and viewing tensor:
🌐
Python Guides
pythonguides.com › pytorch-view
PyTorch view(): Reshape Tensors Without Copying
June 18, 2025 - view() needs the elements laid out in row order in memory (contiguous). Operations like t(), transpose() and permute() only change strides, so a following view() fails: import torch x = torch.arange(6).view(2, 3) t = x.t() # transpose: same ...
🌐
GeeksforGeeks
geeksforgeeks.org › how-does-the-view-method-work-in-python-pytorch
How Does the "View" Method Work in Python PyTorch? - GeeksforGeeks
August 23, 2024 - Original Tensor: tensor([[1, 2, 3], [4, 5, 6]]) torch.Size([2, 3]) Reshaped Tensor: tensor([1, 2, 3, 4, 5, 6]) torch.Size([6]) In this example, .view(6) reshapes the 2x3 tensor into a 1D tensor with 6 elements.
🌐
PyTorch Forums
discuss.pytorch.org › uncategorized
Torch reshape order - Uncategorized - PyTorch Forums
June 28, 2018 - Hello, When you do torch.reshape() or .view() and, say, you flatten a matrix into an array, is there a guaranteed order the elements will be in? In numpy you have an order argument that can specify a C/F/A order? I am…
Find elsewhere
🌐
GeeksforGeeks
geeksforgeeks.org › reshaping-a-tensor-in-pytorch
Reshaping a Tensor in Pytorch - GeeksforGeeks
September 1, 2021 - Example 2: Python code to change the view of a tensor into 10 rows and one column and vice versa. ... # importing torch module import torch # create one dimensional tensor 10 elements a = torch.FloatTensor([24, 56, 10, 20, 30, 40, 50, 1, 2, 3]) # view tensor in 10 rows and 1 column print(a.view(10, 1)) # view tensor in 1 row and 10 columns print(a.view(1, 10))
🌐
Clay-Technology World
clay-atlas.com › home › [pytorch] use view() and permute() to change dimension shape
[PyTorch] Use view() and permute() To Change Dimension Shape - Clay-Technology World
August 11, 2021 - In addition, view() can not only replace the order of dimensions, but also directly change the dimensions. For example, we can put all the elements just now in the same dimension: # coding: utf-8 import torch inputs = [[[1, 2 ,3], [4, 5, 6]], ...
🌐
MyScale
myscale.com › blog › torch-reshape-vs-torch-view-pytorch
Mastering PyTorch Reshape: A Comprehensive Guide
April 24, 2024 - Whether adjusting channel orders or rearranging pixel values, this functionality streamlines image preprocessing workflows with minimal computational overhead. By mastering the art of pytorch reshape, practitioners can unlock new possibilities in customizing tensor structures tailored to diverse machine learning applications. ... In the realm of PyTorch, torch.view emerges as a powerful tool for reshaping tensors with precision and efficiency.
🌐
Medium
mr-amit.medium.com › pytorch-view-vs-reshape-a-practical-guide-74bf31eec210
PyTorch view() vs reshape(): A Practical Guide | by It's Amit | Medium
March 6, 2025 - If the tensor isn’t contiguous — perhaps due to slicing, transposing, or other operations — view() will throw an error. ... You need to reshape a tensor quickly. The tensor is already contiguous in memory (or you’re confident about its contiguity). ... import torch # Create a contiguous tensor tensor = torch.arange(6) # Reshape the tensor using view() reshaped = tensor.view(2, 3) print("Original tensor:") print(tensor) print("\nReshaped tensor using view():") print(reshaped)
🌐
APXML
apxml.com › courses › getting-started-with-pytorch › chapter-2-advanced-tensor-manipulations › reshaping-rearranging-tensors
Reshape PyTorch Tensors | View, Permute
However, view() requires the tensor to be contiguous in memory. A contiguous tensor is one whose elements are stored sequentially in memory without gaps, following the dimension order. Most freshly created tensors are contiguous, but some operations (like slicing or transposing with t()) can create non-contiguous tensors. ... import torch ...
🌐
GeeksforGeeks
geeksforgeeks.org › change-view-of-tensor-in-pytorch
Change view of Tensor in PyTorch - GeeksforGeeks
October 18, 2022 - # importing torch module import torch # create one dimensional tensor 10 elements a = torch.FloatTensor([10, 20, 30, 40, 50, 1, 2, 3, 4, 5]) # view tensor in 5 rows print(a.view(5, -1)) # view tensor in 5 columns print(a.view(-1, 5))
🌐
Medium
medium.com › @sfarrukhm › demystifying-pytorch-tensors-the-complete-guide-to-views-memory-layout-and-gradient-tracking-865197664ee4
Demystifying PyTorch Tensors: The Complete Guide to Views, Memory Layout, and Gradient Tracking | by Muhammad Farrukh Mehmood | Medium
September 25, 2025 - Every operation either reinterprets the memory (view), rearranges it (permute/transpose), or copies it (clone/contiguous). Once you internalize this mental model, the PyTorch API stops feeling like a collection of arbitrary rules and starts feeling inevitable. You’ll find yourself naturally reaching for the right method because you understand what each one is actually doing at the memory level. Before we wrap up, try predicting what this code will output: x = torch...
🌐
Codemia
codemia.io › home › knowledge hub › what does view do in pytorch?
What does view do in PyTorch? | Codemia
September 23, 2025 - 1import torch 2import torch.nn as nn 3 4batch = torch.randn(8, 16, 4, 4) 5 6# Flatten all dimensions except batch 7flat = batch.view(batch.size(0), -1) 8 9layer = nn.Linear(16 * 4 * 4, 10) 10out = layer(flat) 11print(out.shape) # torch.Size([8, 10]) This pattern is common in convolutional networks between convolution blocks and classifier heads. When a view call fails, check these in order: total element count compatibility ·
🌐
Sprintchase
sprintchase.com › home › how to use pytorch view() method
How to Use PyTorch view() Method
May 12, 2025 - The data in the normal tensor and the viewed tensor look like this: import torch tensor = torch.arange(4) print(tensor) # Output: tensor([0, 1, 2, 3]) # Reshape 1D to 2D viewed_tensor = tensor.view(2, 2) print(viewed_tensor) # Output: tensor([[0, 1], # [2, 3]]) Use view(-1) when you need to collapse all the dimensions into a single one.
🌐
DEV Community
dev.to › hyperkai › reshape-and-view-in-pytorch-40n5
reshape and view in PyTorch - DEV Community
November 5, 2024 - reshape() may create the copy of a tensor, taking more memory while view() doesn't create the copy of a tensor so view() can be ligher and faster than reshape(). import torch my_tensor = torch.tensor([[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]]) torch.reshape(input=my_tensor, shape=(12,)) torch.reshape(input=my_tensor, shape=(-1,)) my_tensor.reshape(shape=(12,)) my_tensor.reshape(shape=(-1,)) my_tensor.reshape(12) my_tensor.reshape(-1) my_tensor.view((12,)) my_tensor.view((-1,)) my_tensor.view(12) my_tensor.view(-1) # tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) torch.reshape(input=my_tens
Top answer
1 of 6
71

Yes, it does behave like -1 in numpy.reshape(), i.e. the actual value for this dimension will be inferred so that the number of elements in the view matches the original number of elements.

For instance:

import torch

x = torch.arange(6)

print(x.view(3, -1))      # inferred size will be 2 as 6 / 3 = 2
# tensor([[ 0.,  1.],
#         [ 2.,  3.],
#         [ 4.,  5.]])

print(x.view(-1, 6))      # inferred size will be 1 as 6 / 6 = 1
# tensor([[ 0.,  1.,  2.,  3.,  4.,  5.]])

print(x.view(1, -1, 2))   # inferred size will be 3 as 6 / (1 * 2) = 3
# tensor([[[ 0.,  1.],
#          [ 2.,  3.],
#          [ 4.,  5.]]])

# print(x.view(-1, 5))    # throw error as there's no int N so that 5 * N = 6
# RuntimeError: invalid argument 2: size '[-1 x 5]' is invalid for input with 6 elements

print(x.view(-1, -1, 3))  # throw error as only one dimension can be inferred
# RuntimeError: invalid argument 1: only one dimension can be inferred
2 of 6
8

I love the answer that Benjamin gives https://stackoverflow.com/a/50793899/1601580

Yes, it does behave like -1 in numpy.reshape(), i.e. the actual value for this dimension will be inferred so that the number of elements in the view matches the original number of elements.

but I think the weird case edge case that might not be intuitive for you (or at least it wasn't for me) is when calling it with a single -1 i.e. tensor.view(-1). My guess is that it works exactly the same way as always except that since you are giving a single number to view it assumes you want a single dimension. If you had tensor.view(-1, Dnew) it would produce a tensor of two dimensions/indices but would make sure the first dimension to be of the correct size according to the original dimension of the tensor. Say you had (D1, D2) you had Dnew=D1*D2 then the new dimension would be 1.

For real examples with code you can run:

import torch

x = torch.randn(1, 5)
x = x.view(-1)
print(x.size())

x = torch.randn(2, 4)
x = x.view(-1, 8)
print(x.size())

x = torch.randn(2, 4)
x = x.view(-1)
print(x.size())

x = torch.randn(2, 4, 3)
x = x.view(-1)
print(x.size())

output:

torch.Size([5])
torch.Size([1, 8])
torch.Size([8])
torch.Size([24])

History/Context

I feel a good example (common case early on in pytorch before the flatten layer was official added was this common code):

class Flatten(nn.Module):
    def forward(self, input):
        # input.size(0) usually denotes the batch size so we want to keep that
        return input.view(input.size(0), -1)

for sequential. In this view x.view(-1) is a weird flatten layer but missing the squeeze (i.e. adding a dimension of 1). Adding this squeeze or removing it is usually important for the code to actually run.


Example2

if you are wondering what x.view(-1) does it flattens the vector. Why? Because it has to construct a new view with only 1 dimension and infer the dimension -- so it flattens it. In addition it seems this operation avoids the very nasty bugs .resize() brings since the order of the elements seems to be respected. Fyi, pytorch now has this op for flattening: https://pytorch.org/docs/stable/generated/torch.flatten.html

#%%
"""
Summary: view(-1, ...) keeps the remaining dimensions as give and infers the -1 location such that it respects the
original view of the tensor. If it's only .view(-1) then it only has 1 dimension given all the previous ones so it ends
up flattening the tensor.

ref: my answer https://stackoverflow.com/a/66500823/1601580
"""
import torch

x = torch.arange(6)
print(x)

x = x.reshape(3, 2)
print(x)

print(x.view(-1))

output

tensor([0, 1, 2, 3, 4, 5])
tensor([[0, 1],
        [2, 3],
        [4, 5]])
tensor([0, 1, 2, 3, 4, 5])

see the original tensor is returned!

🌐
PyTorch Forums
discuss.pytorch.org › t › different-between-permute-transpose-view-which-should-i-use › 32916
Different between permute, transpose, view? Which should I use? - PyTorch Forums
December 24, 2018 - Hello all, what is different among permute, transpose and view? If I have a feature size of BxCxHxW, I want to reshape it to BxCxHW where HW is a number of channels likes (H=3, W=4 then HW=3x4=12). Which one is a good …
🌐
GeeksforGeeks
geeksforgeeks.org › deep learning › whats-the-difference-between-reshape-and-view-in-pytorch
What's the Difference Between Reshape and View in PyTorch? - GeeksforGeeks
July 23, 2025 - PyTorch, a popular deep learning framework, offers two methods for reshaping tensors: torch.reshape and torch.view. While both methods can be used to change the shape of tensors, they have distinct differences in their behavior, constraints, and implications for memory usage.