Skip to content

← Shapes and Strides step 9 of 9

Easy Primitives

Move one axis, not all of them

Jump to the task

Suppose axis 1 represents channels and you want it last. For a 4-D tensor, either expression gives the same axis order:

x.permute(0, 2, 3, 1)
x.movedim(1, -1)

permute lists the original axes in their new order. movedim names the axis to move and its destination; the other axes keep their relative order. For this task, movedim expresses the intent directly.

Handle different ranks

A fixed four-axis permutation raises if the input has three or five axes. Moving axis 1 to the end works for any rank of at least two:

import torch

x = torch.arange(24).reshape(2, 3, 4)
y = x.movedim(1, -1)
print(list(y.shape))  # [2, 4, 3]
print(y[0, 0].tolist())  # [0, 4, 8]
print(y.untyped_storage().data_ptr() == x.untyped_storage().data_ptr())  # True

For a 2-D input, axis 1 is already last, so the axis order stays the same. A dynamically constructed permute order could also support different ranks; it is simply more work to express this single move.

A view, not a data rearrangement

For strided tensors, both operations return views sharing the input's storage. They update shape and stride metadata without copying values. That does not make them cost-free, and the resulting layout can affect operations that follow.

Moving the channel axis is also different from PyTorch's torch.channels_last memory format. That format changes strides for a 4-D image tensor while retaining its logical (N, C, H, W) shape. This exercise changes the logical axis order instead.

Related operations

Use transpose(a, b) to swap two axes. Use permute when you want to specify a complete ordering. movedim can also move several axes at once: x.movedim((0, 1), (-2, -1)) moves the first two axes to the last two positions, retaining the relative order of all remaining axes.

Your task

def channels_last(x: torch.Tensor) -> torch.Tensor

For a strided tensor with at least two dimensions, move axis 1 to the end without copying its storage. Preserve the relative order of all other axes. The starter works only for 4-D inputs.