Correct order for torchvision.transforms? (inconsistent behaviour for RandAugment)

username: mrdbourke
cooked: <p>Hello,</p>
<p>I’m trying to apply <code>torchvision.transforms.RandAugment</code> to some images, however it seems to be inconsistent in its results (I know the transforms will be random so it’s a different type of inconsistency).</p>
<p>The <a href="https://pytorch.org/vision/master/generated/torchvision.transforms.RandAugment.html#torchvision.transforms.RandAugment" rel="noopener nofollow ugc">documentation on RandAugment</a> says the input should be of <code>torch.uint8</code>.</p>
<p>However, I’ve found it to both <em>work with</em> and <em>error with</em> inputs of <code>torch.float32</code>.</p>
<p>My current <code>transforms</code> pipeline looks like this:</p>
<pre><code class="lang-auto">train_transforms = transforms.Compose([
    transforms.Resize((64, 64)),
    transforms.ToTensor(), # it seems the order in where this is placed effects whether the transform works or not
    transforms.RandAugment()
])
</code></pre>
<p>Using the above seems to generate inconsistent results.</p>
<p>But if I change the order:</p>
<pre><code class="lang-auto">train_transforms = transforms.Compose([
    transforms.Resize((64, 64)),
    transforms.RandAugment(),
    transforms.ToTensor()
])
</code></pre>
<p>It seems to work without fail.</p>
<p>So my questions are:</p>
<ol>
<li>Is there a best practice on the order of <code>transforms</code>?</li>
<li>Or do I need to not worry about <code>transforms.ToTensor</code> since <code>transforms.RandAugment</code> returns a <code>torch.Tensor</code>?</li>
</ol>
<p>Example code notebook here: <a href="https://colab.research.google.com/drive/1edkqgfDxry8BNvwdf9wGF7KUbvaEMnQm?usp=sharing" rel="noopener nofollow ugc">https://colab.research.google.com/drive/1edkqgfDxry8BNvwdf9wGF7KUbvaEMnQm?usp=sharing</a></p>

username: mrdbourke
cooked: <p>Update on 2.</p>
<p>It turns out without <code>transforms.ToTensor()</code>, e.g:</p>
<pre><code class="lang-auto">train_transforms = transforms.Compose([
    transforms.Resize((64, 64)),
    transforms.RandAugment(),
    # transforms.ToTensor() 
])
</code></pre>
<p>When trying to use methods such as <code>permute()</code> on the output of the above, it fails with error:</p>
<p><code>AttributeError: 'Image' object has no attribute 'permute'</code></p>
<p>So it seems the ideal order in my case must be:</p>
<pre><code class="lang-auto">train_transforms = transforms.Compose([
    transforms.Resize((64, 64)),
    transforms.RandAugment(),
    transforms.ToTensor()
])
</code></pre>
<p>Is this right? Or should the augmentations be done before resizing?</p>

username: ivan-jgr
cooked: <p>Hi <a class="mention" href="/u/mrdbourke">@mrdbourke</a>  remember that <code>ToTensor()</code> normalize the image between 0 and 1 but RandAugment can be applit to a <code>Tensor</code> (that’s what <code>ToTensor()</code> returns) or can be applied to a  <code>PIL Image</code> (that’s what you have after <code>Resize((64, 64))</code>.</p>
<p>I think that you want this:</p>
<pre><code class="lang-auto">train_transforms = transforms.Compose([
    transforms.Resize((64, 64)),
    transforms.RandAugment(),
    transforms.ToTensor()
])
</code></pre>
<p>Hope it helps.</p>

username: mrdbourke
cooked: <p>Thank you Ivan! You’re right that order works better, still getting used to constructing PyTorch transforms.</p>
<p>Cheers.</p>