PyTorch `permute` vs `transpose`: What's the Difference (and the `reshape` Bug That Scrambles Your Images)
You loaded an image, got a tensor shaped (batch, height, width, channels) , and your convolution wants (batch, channels, height, width) . Stack Overflow says permute . Someone else says transpose . And reshape(2, 3, 28, 28) gives you the right shape too — so why is everyone making this complicated? Because two of those three are the same tool, and the third one silently destroys your data. The short answer transpose(dim0, dim1) swaps exactly two dimensions. permute(...) reorders all of them in one call, and you must list every dimension. transpose is a special case of permute . Both return a view — no data is copied, only the strides change — which also means both leave you with a non-contiguous tensor. reshape is not in this family at all. It reinterprets the flat memory under a new shape without moving anything, so it can produce the shape you asked for while completely scrambling what the numbers mean. import torch t = torch . arange ( 24 ). reshape ( 2 , 3 , 4 ) print ( t . transpose ( 0 , 1 ). shape ) # torch.Size([3, 2, 4]) — swapped dims 0 and 1 print ( t . permute ( 2 , 0 , 1 ). shape ) # torch.Size([4, 2, 3]) — full reorder transpose — swap two axes transpose(dim0, dim1) takes two dimension indices and swaps them. Everything else stays put. t = torch . arange ( 24 ). reshape ( 2 , 3 , 4 ) print ( t . shape ) # torch.Size([2, 3, 4]) print ( t . transpose ( 0 , 1 ). shape ) # torch.Size([3, 2, 4]) print ( t . transpose ( 1 , 2 ). shape ) # torch.Size([2, 4, 3]) The order of the two arguments doesn't matter — t.transpose(0, 1) and t.transpose(1, 0) are the same thing. A swap is a swap. On a 2-D tensor this is the matrix transpose you already know, and .T is the shorthand: m = torch . arange ( 6 ). reshape ( 2 , 3 ) print ( m . T . shape ) # torch.Size([3, 2]) print ( m . transpose ( 0 , 1 ). shape ) # torch.Size([3, 2]) — identical One caution on .T : on tensors with more than two dimensions, .T reverses every dimension, and modern PyTorch has deprecated that