How does np.transpose() permute the axis

aleemsidra: <p>I am trying to visualize the images in one batch of the data loader. I got this code snippet from Pytorch official site.</p>
<pre><code class="lang-auto">def imshow(inp, title=None):
    """Imshow for Tensor."""
    inp = inp.numpy().transpose((1,2,0))
    print(inp.shape)
    plt.imshow(inp)
    if title is not None:
         plt.title(title)
    # plt.pause(0.001)  # pause a bit so that plots are updated

# Get a batch of training data
image, label = next(iter(train_loader))
print(image.shape)
#print(label)
# Make a grid from batch
out = torchvision.utils.make_grid(image)
imshow(out, title=[label[x] for x in label])
</code></pre>
<p>However, I am not able to understand <code> inp.numpy().transpose((1,2,0))</code>, what transpose is doing here. I know that it permutes the axis. However, the corresponding tensor shape is <code>torch.Size([4, 3, 224, 224])</code>. In that case (1,2,0) corresponds to 3,224,4.  Then how <code>imshow</code> is correctly displaying images?</p>
<p>Apart from that, the shape of the tensor image is <code>3,224,224</code>. but when it is being transformed to ndarray why the shape is being changed to <code>(228, 906, 3)</code>. Should it become <code>224, 224, 3</code>.</p>

KFrank: <p>Hi Aleemsidra!</p>
<aside class="quote no-group quote-modified" data-username="aleemsidra" data-post="1" data-topic="124085" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/aleemsidra/48/38723_2.png" class="avatar"> aleemsidra:</div>
<blockquote>
<p>However, I am not able to understand <code> inp.numpy().transpose((1,2,0))</code>, what transpose is doing here.<br>
…<br>
However, the corresponding tensor shape is <code>torch.Size([4, 3, 224, 224])</code>.</p>
</blockquote>
</aside>
<p>You should get an error here.  You need to pass <em>four</em> axes to numpy’s<br>
<code>transpose()</code> to transpose a 4-d tensor.</p>
<aside class="quote no-group">
<blockquote>
<p>Apart from that, the shape of the tensor image is <code>3,224,224</code>. but when it is being transformed to ndarray why the shape is being changed to <code>(228, 906, 3)</code>. Should it become <code>224, 224, 3</code>.</p>
</blockquote>
</aside>
<p>I have no idea where your <code>(228, 906, 3)</code> is coming from.  I get<br>
<code>(244, 244, 3)</code>, which is what you expect and want.  (matplotlib’s<br>
<code>imshow()</code> wants the three color channels as the last dimension,<br>
rather than the first.  That’s the purpose of the <code>transpose()</code>.)</p>
<p>Here’s an illustration of these points:</p>
<pre><code class="lang-plaintext">&gt;&gt;&gt; import torch
&gt;&gt;&gt; torch.__version__
'1.7.1'
&gt;&gt;&gt; inp = torch.randn (4, 3, 224, 224)
&gt;&gt;&gt; inp.shape
torch.Size([4, 3, 224, 224])
&gt;&gt;&gt; inp.numpy().transpose ((1, 2, 0))
Traceback (most recent call last):
  File "&lt;stdin&gt;", line 1, in &lt;module&gt;
ValueError: axes don't match array
&gt;&gt;&gt; inp[0].shape
torch.Size([3, 224, 224])
&gt;&gt;&gt; inp[0].numpy().transpose ((1, 2, 0)).shape
(224, 224, 3)
</code></pre>
<p>Best.</p>
<p>K. Frank</p>

aleemsidra: <p>I realized that I am using <code>make_grid</code> function which is changing the dimension from 4d to 3d. It is also changing the the dimension from <code>224, 244,3</code> to<code> 228,906,3</code>. Which is still confusing for me that how it picks up this dimension.</p>

ptrblck: <p>The “grid” of images is created by flattening the images provided as a batch of image tensors (4D) into a single image tensor (3D).<br>
The shapes are created by placing the images next to each other using the specified <code>nrow</code> and <code>padding</code> arguments as described in the <a href="https://pytorch.org/vision/stable/utils.html#torchvision.utils.make_grid">docs</a>.</p>