How do I resample dataset with data augmentation to make dataloader larger?

vanstorm9: <p>Hello everyone,<br>
I am working with a Pytorch dataset that I want to make bigger by taking the entire dataset and duplicate it multiple times to have a larger dataloader (using for one-shot learning purposes). For example I have 10 classes containing 1 image each, leaving a total of 10 images (dataloader of length 10 for 1 batch). I want to resample the entire dataset multiple times (duplicate each image 20 times to have total of 200 images) and make each duplication different through data augmentation.</p>
<hr>
<p>So (dataset of 1 cat, 1 dog)  →  (resample/duplicate dataset 20 times) → (data augmention) → (dataset of 20 cats, 20 dogs with variations from their original image) = (dataloader of size 40 for 1 batch)</p>
<hr>
<p>What would be an effective way to accomplish this?</p>
<pre><code class="lang-auto">vis_dataloader = DataLoader(sample_dataset,
                        shuffle=True,
                        num_workers=8,
                        #num_workers=0,
                        batch_size=1)
dataiter = iter(vis_dataloader)
</code></pre>

ptrblck: <p>I’m not sure if you would really need to duplicate the images, since the data augmentation methods would be applied on each sample separately while loading the image.<br>
I.e. keeping the 10 initial images (1 image per class) or duplicating them would only increase the number of iterations in an epoch (assuming the batch size is constant), but each images will be transformed randomly in both cases.</p>

vanstorm9: <p>So keeping the initial 10 images of batch size 1 would have the dataloader’s length be 10. I want to essentially have my model have more instances of the initial images for my model to train on.</p>
<p>For example, maybe within the 10 initial images (dataloader of size 10), the model preformed transformation on one class (shift to the right), and that’s it for that class. But I want to add more instances of the same image, but transformed differently. I want there to instances of the class where it has been shifted to the left, or maybe upward, etc.</p>
<p>My ultimate goal is to make the training data larger than just 1 image per class so that there will be more variety for my network to work with per class. Would there be any way I can increase the amount of image per class, but with the data augmentation being randomized/different on those duplicate images from the same class?</p>

ptrblck: <p>I don’t see what the difference would be between duplicating images vs. using more epochs.<br>
In both cases random transformations would be applied on the original data (in the first case you would just create copies of the original data and apply the transformations on them).</p>
<p>I’ll try to “visualize” it:</p>
<pre><code class="lang-python"># duplicating data
initial_dataset = [0, 1, 2, 3]
dataset = [0, 1, 2, 3, 0, 1, 2, 3] # one epoch would contain 2*initial_dataset = 8 samples
loader = [trans(0), trans(1), trans(2), trans(3), trans(0), trans(1), trans(2), trans(3)] # each sample will be randomly transformed in this epoch

# keeping the original data
initial_dataset = [0, 1, 2, 3]
dataset = initial_dataset # one epoch would contain initial_dataset = 4 samples
loader = [trans(0), trans(1), trans(2), trans(3)] # each sample will be randomly transformed in this epoch
# train for 2 epochs
data_seen_in_2_epochs = [trans(0), trans(1), trans(2), trans(3), trans(0), trans(1), trans(2), trans(3)]
</code></pre>

vanstorm9: <p>I was under the impression that once you initialize your dataloader on your dataset, the dataset and images inside the dataloader have effectively locked until you reinitialize the dataloader again.</p>
<p>I see what you are saying, but I am not sure how preforming the random and different transforms per epoch</p>
<p>What would be a proper way to reformat this code so that I have different transformations per epoch?</p>
<pre><code class="lang-auto">
sample_dataset = sampleDataset(imageFolderDataset=folder_dataset,
                                        transform=transforms.Compose([
                                                    transforms.Grayscale(num_output_channels=3),
                                                    transforms.Resize((244,244)),
                                                    transforms.ColorJitter(brightness=(0.2,1.0),contrast=(0.1,1.1),hue=.05, saturation=(.0,.15)),
                                                    transforms.ToTensor()
                                                ]),
                                        should_invert=False)

vis_dataloader = DataLoader(sample_dataset,
                        shuffle=True,
                        num_workers=8,
                        #num_workers=0,
                        batch_size=1)
dataiter = iter(vis_dataloader)

epochs = 100

for i in range(0,epochs):
  print('epoch ',i)
  for inputImg, posAnc, negAnc, pathList in dataiter:
    concatenated = torch.cat((inputImg, posAnc,negAnc),0)
    imshow(torchvision.utils.make_grid(concatenated))
</code></pre>
<p>Also if I want to use the same transformation from one epoch, wait a few epochs, and use that same transform (for example, the same data-augmented-transformed image from epoch 1 reappears in epoch 10), how would I do that?</p>

ptrblck: <aside class="quote no-group" data-username="vanstorm9" data-post="6" data-topic="130776">
<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/vanstorm9/48/39468_2.png" class="avatar"> vanstorm9:</div>
<blockquote>
<p>What would be a proper way to reformat this code so that I have different transformations per epoch?</p>
</blockquote>
</aside>
<p>Tansformations are usually applied in the <code>__getitem__</code> method of the <code>Datset</code> (I don’t know if you are using a custom <code>Dataset</code> or a pre-defined one) and random transformations will be random by default. In your case <code>ColorJitter</code> will use random values for each call and thus each sample (the same applies to e.g. <code>RandomCrop</code>).</p>
<aside class="quote no-group" data-username="vanstorm9" data-post="6" data-topic="130776">
<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/vanstorm9/48/39468_2.png" class="avatar"> vanstorm9:</div>
<blockquote>
<p>Also if I want to use the same transformation from one epoch, wait a few epochs, and use that same transform (for example, the same data-augmented-transformed image from epoch 1 reappears in epoch 10), how would I do that?</p>
</blockquote>
</aside>
<p>One way would be to seed the code (I wouldn’t recommend using this approach, if you are not familiar with how seeing and the pseudo random number generator works) or to use the functional API via <code>torchvision.transforms.functional</code> and apply the transformations by creating the parameters for each transformation manually.</p>