A view is a tensor that presents existing data through a different shape or indexing pattern. It shares the underlying storage instead of copying its numbers. That makes operations such as selecting a subtensor or changing its shape inexpensive—but it also means edits through one tensor can affect another. section 3.8 section 3.9.1
A tensor finds its values using a shape, a storage offset, and a stride for each dimension. The shape says how many indices fit along each axis; a stride says how far to move in storage when an index increases by one. For a two-dimensional tensor, element (i, j) lives at storage_offset + stride[0] × i + stride[1] × j. A view can change this indexing information while leaving the stored numbers in place. section 3.9.1
Selecting a point without copying it
Given points = torch.tensor([[4.0, 1.0], [5.0, 3.0], [2.0, 1.0]]), second_point = points[1] has shape (2,), offset 2, and stride (1,). Assigning second_point[0] = 10.0 also changes points[1, 0]. If the point needs independent storage, use points[1].clone() instead. section 3.9.1 section 3.9.1
The view method gives the same stored data a requested shape. For example, a = torch.tensor(list(range(9))) and b = a.view(3, 3) provide one-dimensional and three-by-three ways to index the same storage. A -1 in the requested shape lets PyTorch infer that dimension from the number of elements and the other dimensions. section 3.15 section 4.4.2
# In[4]: daily_bikes = bikes.view(-1, 24, bikes.shape[1]) daily_bikes.shape, daily_bikes.stride() # Out[4]: (torch.Size([730, 24, 17]), (408, 17, 1))
The bike-sharing reshape turns 17,520 hourly rows with 17 columns into 730 days × 24 hours × 17 columns. The changed shape and strides show how view groups existing rows into daily sequences without copying them. section 4.4.2
Check layout before relying on view: it requires a compatible contiguous tensor here. A transpose can be noncontiguous; calling contiguous() makes a tensor with rearranged values in new storage, after which view can be used. Unlike a view alone, that step may copy data. section 3.9.4
# In[27]:
class Net(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(3, 16, kernel_size=3, padding=1)
self.act1 = nn.Tanh()
self.pool1 = nn.MaxPool2d(2)
self.conv2 = nn.Conv2d(16, 8, kernel_size=3, padding=1)
self.act2 = nn.Tanh()
self.pool2 = nn.MaxPool2d(2)
self.fc1 = nn.Linear(8 * 8 * 8, 32)
self.act3 = nn.Tanh()
self.fc2 = nn.Linear(32, 2)
def forward(self, x):
out = self.pool1(self.act1(self.conv1(x)))
out = self.pool2(self.act2(self.conv2(out)))
out = out.view(-1, 8 * 8 * 8) #1
out = self.act3(self.fc1(out))
out = self.fc2(out)
return out
In a convolutional network’s forward method, out.view(-1, 8 * 8 * 8) turns each pooled 8-channel, 8 × 8 result into a 512-element vector for a linear layer. The -1 leaves batch size to be inferred. section 8.3.1




