Cannot combine [compose?] transforms

username: farazk86
cooked: <p>Hi,</p>
<p>Im trying to combine a couple transforms together using <code>torchvision.transforms.Compose</code> but I get the error:</p>
<blockquote>
<p>TypeError: batch must contain tensors, numbers, dicts or lists; found &lt;class ‘torchvision.transforms.Compose’&gt;</p>
</blockquote>
<p>At first I wrote the transform as simple functions but after reading here: <a href="https://pytorch.org/tutorials/beginner/data_loading_tutorial.html#transforms" class="inline-onebox" rel="noopener nofollow ugc">Writing Custom Datasets, DataLoaders and Transforms — PyTorch Tutorials 2.1.1+cu121 documentation</a> that they have to be callable objects for the Compose to work I rewrote them as callable classes but am still getting the error.</p>
<p>This is my line for Compose:</p>
<pre><code class="lang-auto">normalize = Normalize(mean, std)
random_flip = RandomFlip(random_state)
rotate_90 = RandomRotate90(num_rotate)
to_tensor = ToTensor(expand_dims=True, dtype=self.label_dtype)

img_transform = Compose([normalize(img),
                                 random_flip(img),
                                 rotate_90(img),
                                 to_tensor(img)
                                 ])
</code></pre>
<p>And here is <code>Normalize</code></p>
<pre><code class="lang-auto">class Normalize:

    def __init__(self, mean, std, eps=1e-4):
        self.mean = mean
        self.std = std
        self.eps = eps

    def __call__(self, m):
        return (m - self.mean) / (self.std + self.eps)
</code></pre>
<p>Why is it not returning the images after transformations applied, rather than the Compose class?</p>
<p>Thanks</p>

username: ptrblck
cooked: <p>Could you try to pass just the classes without calling them, e.g. <code>normalize</code> instead of <code>normalize(img)</code>.<br>
Also, normalization should come after the <code>ToTensor</code> transformation.</p>

username: farazk86
cooked: <p>To be honest I dont think I am using this the right way. Are you suggesting that I do the following:</p>
<pre><code class="lang-auto">img_transform = Compose([Normalize(mean, std),
                                 RandomFlip(random_state),
                                 RandomRotate90(num_rotate),
                                 ToTensor(expand_dims=True, dtype=self.label_dtype)
                                 ])
</code></pre>
<p>Then at what stage would I pass the actual image or sample on which the transformations are to be applied?</p>
<blockquote>
<p>Also, normalization should come after the  <code>ToTensor</code>  transformation.</p>
</blockquote>
<p>Noted. Can you please explain why it makes a difference to normalize after ToTensor.</p>
<p>Thanks</p>

username: ptrblck
cooked: <p>Usually you would apply the transformations on each sample in the <code>__getitem__</code> method of your <code>Dataset</code>. Have a look at the <a href="https://pytorch.org/tutorials/beginner/data_loading_tutorial.html#dataset-class">data loading tutorial</a> for an example.</p>
<p>If you wrap your <code>Dataset</code> in a <code>DataLoader</code> with multiple workers, the loading and processing will be applied using multiprocessing in the background while your GPU is busy with the training.</p>
<p>While a lot of <code>torchvision.transforms</code> are applied on <code>PIL.Images</code>, <code>Normalize</code> is applied on a tensor which is why I suggested to call it after <code>ToTensor</code>.<br>
Note that <code>ToTensor</code> will return a tensor image with values in the range [0, 1]. Your mean and std in <code>Normalize</code> should therefore also be relative to this range.</p>

username: Ashima_Garg
cooked: <p>Hi <a class="mention" href="/u/ptrblck">@ptrblck</a> ,</p>
<p>Is it possible to insert a new transform to an already composed transform.<br>
For example: if I have <code>train_transform =  transforms.Compose(                 [transforms.ToTensor(),                  transforms.Normalize(mean=mean, std=std)]) </code><br>
And later I want to add <code>RandomFlip</code> to this <code>train_transform</code>.</p>
<p>Is it possible to insert this in <code>train_transform</code>?</p>
<p>Thanks,</p>

username: ptrblck
cooked: <p><code>transforms.Compose</code> holds an internal <code>list</code>, which is passed as the initial argument to it and iterates all transformations in this list.<br>
You could thus manipulate this <code>list</code> object directly via e.g. <code>insert</code>:</p>
<pre><code class="lang-python">train_transform.transforms.insert(1,transforms.ToPILImage())
train_transform.transforms.insert(2,transforms.ToTensor())
</code></pre>

username: Ashima_Garg
cooked: <p>Thanks for the quick response.</p>