PyTorch view() returns a tensor with a new shape that shares the original’s data, so it copies nothing. The new shape must hold the same number of elements. Pass -1 for one dimension and PyTorch works it out:
x = torch.arange(12)
x.view(4, 3) # 4 rows x 3 columns
x.view(2, -1) # PyTorch fills in 6
I ran these examples with PyTorch 2.14.0+cpu on Python 3.12.5; a CPU build is enough for everything here.
You’ll reshape with view and -1, see why changing a view changes the original, fix the “not contiguous” error, compare view with reshape, and use view inside a model.
Reshape a tensor with PyTorch view()
Here a 12-month sales tensor becomes 4 quarters of 3 months. The only rule is that the element count can’t change:
import torch
sales = torch.arange(12) # 12 monthly sales figures
print(sales.shape)
by_quarter = sales.view(4, 3) # 4 quarters x 3 months
print(by_quarter)
print(sales.view(2, -1).shape, sales.view(-1, 6).shape) # -1 is worked out for you
try:
sales.view(5, 3) # 15 elements don't fit 12
except RuntimeError as err:
print("RuntimeError:", err)
Output:
torch.Size([12])
tensor([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])
torch.Size([2, 6]) torch.Size([2, 6])
RuntimeError: shape '[5, 3]' is invalid for input of size 12

view(4, 3) groups the months by quarter; -1 is inferred, and an impossible shape raises RuntimeError.Only one dimension can be -1. For adding a dimension of size 1 rather than regrouping, unsqueeze() is clearer; see adding a dimension to a PyTorch tensor.
Does PyTorch view() copy the data?
No. A view is a new window onto the same memory, so writing through the view changes the original tensor. data_ptr() proves they point to the same storage:
import torch
prices = torch.tensor([19.99, 5.25, 102.00, 7.50])
grid = prices.view(2, 2)
grid[0, 0] = 0.0 # change the view...
print(prices) # ...and the original changes too
print("same memory:", grid.data_ptr() == prices.data_ptr())
copy = prices.view(2, 2).clone() # clone() when you need an independent copy
copy[1, 1] = 99.0
print(prices)
Output:
tensor([ 0.0000, 5.2500, 102.0000, 7.5000])
same memory: True
tensor([ 0.0000, 5.2500, 102.0000, 7.5000])

prices; the cloned copy left it alone.Call .clone() when you need a separate tensor. The same sharing applies to slicing, so keep it in mind before editing in place, as in creating empty tensors in PyTorch.
Fix: view size is not compatible with input tensor’s size and stride
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 data, different strides
print("contiguous?", x.is_contiguous(), t.is_contiguous())
try:
t.view(6)
except RuntimeError as err:
print("RuntimeError:", str(err).split(".")[0])
print(t.contiguous().view(6)) # copy into row order, then view
r = t.reshape(6) # reshape copies only when it must
print(r, "| reshape shares memory:", r.data_ptr() == t.data_ptr())
print("reshape of contiguous shares memory:", x.reshape(6).data_ptr() == x.data_ptr())
Output:
contiguous? True False
RuntimeError: view size is not compatible with input tensor's size and stride (at least one dimension spans across two contiguous subspaces)
tensor([0, 3, 1, 4, 2, 5])
tensor([0, 3, 1, 4, 2, 5]) | reshape shares memory: False
reshape of contiguous shares memory: True

view() raises; contiguous() or reshape() fixes it.Notice that reshape() copied the transposed data but shared memory with the contiguous one. It’s a view when possible and a copy when it has to be.
PyTorch view vs reshape
view() | reshape() | |
|---|---|---|
| Copies data | Never | Only if needed |
| Works on non-contiguous tensors | No (RuntimeError) | Yes |
| Shares memory with the input | Always | When it can |
| Best for | Guaranteed no-copy reshapes | Code that should just work |
I use view() when I want an error if a copy would happen, and reshape() everywhere else. More shape options are in reshaping tensors in PyTorch.
Use view() to flatten a batch before a Linear layer
The most common real use: image tensors come in as (batch, channels, height, width), and a fully connected layer wants (batch, features). x.view(x.size(0), -1) keeps the batch and flattens the rest:
import torch
from torch import nn
torch.manual_seed(0)
images = torch.rand(8, 3, 32, 32) # a batch of 8 RGB images, 32x32
class TinyClassifier(nn.Module):
def __init__(self):
super().__init__()
self.fc = nn.Linear(3 * 32 * 32, 10)
def forward(self, x):
x = x.view(x.size(0), -1) # keep the batch size, flatten the rest
return self.fc(x)
out = TinyClassifier()(images)
print("input:", tuple(images.shape), "-> flattened:", tuple(images.view(8, -1).shape), "-> output:", tuple(out.shape))
bits = torch.tensor([1.0, -2.0]).view(torch.int32) # view(dtype): same bytes, new type
print(bits)
Output:
input: (8, 3, 32, 32) -> flattened: (8, 3072) -> output: (8, 10)
tensor([ 1065353216, -1073741824], dtype=torch.int32)

torch.flatten(x, 1) and nn.Flatten() do the same job and also handle non-contiguous input; see PyTorch flatten. For the layer itself, see PyTorch nn.Linear.
The last line shows a rarer form, view(dtype), which reinterprets the same bytes as another type. It’s useful for low-level bit tricks, not for normal type conversion; use .to(dtype) for that.
PyTorch view rules to remember
- The total number of elements must stay the same.
- Use
-1for at most one dimension. - The result shares memory with the original; use
clone()for a copy. - It needs a contiguous tensor; after
transpose()orpermute(), usereshape()orcontiguous()first.
Here are more PyTorch tensor guides:
Frequently asked questions
What does view() do in PyTorch?
It returns a tensor with a different shape that shares the original’s data, without copying it.
What does -1 mean in view()?
PyTorch calculates that dimension from the total element count. Only one dimension can be -1.
Why do I get “view size is not compatible with input tensor’s size and stride”?
The tensor isn’t contiguous, usually after transpose or permute. Call .contiguous() first or use reshape().
What’s the difference between view and reshape?
view never copies and fails on non-contiguous tensors; reshape returns a view when possible and copies when needed.
Does changing a view change the original tensor?
Yes, they share memory. Use .clone() to get an independent copy.
Where is Tensor.view documented?
See torch.Tensor.view in the PyTorch docs.

Bijay Kumar is a 13-time Microsoft MVP with more than 18 years in software development, and the founder of Python Guides and TSinfo Technologies. He started out building .NET and SharePoint solutions at HP, TCS and KPIT before moving into Python, machine learning and AI, and he also builds web apps with TypeScript and React. He writes the tutorials here himself, and every example is run before publishing so you see the real output. More about Bijay · Microsoft MVP profile · LinkedIn