PyTorch `permute` vs `transpose`: What's the Difference (and the `reshape` Bug That Scrambles Your Images)

2026年8月2日1 次浏览来源:Dev.to阅读原文

You loaded an image, got a tensor shaped , and your convolution wants .

Stack Overflow says .

Someone else says .

And 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 swaps exactly two dimensions. reorders all of them in one call, and you must list every dimension. is a special case of .

Both return a view — no data is copied, only the strides change — which also means both leave you with a non-contiguous tensor. 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. — swap two axes takes two dimension indices and swaps them.

Everything else stays put.

The order of the two arguments doesn't matter — and are the same thing.

A swap is a swap.

On a 2-D tensor this is the matrix transpose you already know, and is the shorthand: One caution on : on tensors with more than two dimensions, reverses every dimension, and modern PyTorch has deprecated that behaviour — it warns now and is slated to become an error.

If you want the "transpose the last two axes" behaviour on a batch of matrices, use , which is explicit and safe: Reserve plain for 2-D matrices.

On anything higher, say what you mean with or . — state the whole new order doesn't swap; it rewrites the dimension order in full.

You pass the old index of each dimension in the position you want it to end up.

Read as: "new dim 0 is old dim 2, new dim 1 is old dim 0, new dim 2 is old dim 1." Not "move dim 2 somewhere" — you are writing out the destination order, left to right.

Two consequences worth internalising: You must list every dimension.

Miss one and you get .

Any reorder you can do with a chain of transposes, you can do in one : Same result.

The version says the destination shape out loud; the chained version makes the reader simulate two swaps in their head.

Prefer for anything beyond a single swap.

The one that actually bites: is not Here is the bug this article exists for.

You have a batch of images in — the layout you get from OpenCV, PIL, TensorFlow, and most image files — and PyTorch convolutions need .

Both of these produce a tensor of the right shape: Same shape.

No error.

No warning.

Now look at what's actually inside the first channel: The version collected the red channel: pixels are stored as , so the reds are elements 0, 3, 6,

9.

That's a real red channel.

The version just took the first four numbers in memory and called them "channel 0" — that's one whole pixel plus a third of the next one.

Your "red channel" is now a mixture of red, green and blue from different pixels.

The tensor is the right shape, the model trains, the loss goes down a little, and the accuracy is quietly terrible.

Nothing on screen ever tells you.

The rule: moves dimensions. re-cuts the same flat sequence of numbers into new brackets.

If you want to change what an axis means, you need — always.

If you want the full picture on how re-cuts memory, that's covered in Reshape vs View in PyTorch.

Real code: the two reorders you'll actually write Images — channels-last to channels-first: Attention — splitting into heads.

This is the one place where and correctly appear back-to-back, and seeing why makes the distinction click: The is legitimate here because it only splits the last axis — the 8 embedding values were already laid out contiguously, so cutting them into 2 groups of 4 doesn't reorder anything.

The then genuinely moves the head axis in front of the sequence axis.

Splitting an axis is work; moving an axis is work.

Both of them break contiguity and never touch the underlying data.

They change the tensor's strides — the step size PyTorch takes through memory for each dimension: That's why they're free.

It's also why the very next you call will blow up: Two fixes, and the choice matters: Use by default.

Reach for an e

分享
Baike.dev

baike.dev helps you discover great languages, frameworks, databases, DevOps and cloud-native tools.

Quick links

About

Contribute

Found a great developer tool? Share it with the community.

Submit a tool
© 2026 baike.dev Developer EncyclopediaUpdated daily · Discover great developer tools