How to augment the minority class only in an unbalanced dataset

mohamadal: <p>I have an unbalanced image dataset with the positive class being 1/10 of the entire dataset. Classification models trained on this dataset tend to be biased toward the majority class (small false negative rate and bigger false positive rate). I would like to do some augmentation only on the minority class to deal with this. The way I understand, using transforms (random rotation, etc.) when creating torchvision.dataset will augment all of the data so the imbalance remains the same.<br>
What is the best way to go about only augmenting images from a specific class?</p>

ptrblck: <p>You could write your own <code>Dataset</code> and apply the transformations in the <code>__getitem__</code> method.</p>
<pre><code class="lang-auto">class MyData(Dataset):
    def __init__(self, data, target, transform=None):
        self.data = data
        self.target = target
        self.transform = transform
        
    def __len__(self):
        return len(self.data)
    
    def __getitem__(self, index):
        x = self.data[index]
        y = self.target[index]
        
        if (y == 0) and self.transform: # check for minority class
            x = self.transform(x)
        
        return x, y
</code></pre>
<p>EDIT: Another useful approach is to use the <a href="http://pytorch.org/docs/master/data.html#torch.utils.data.sampler.WeightedRandomSampler" rel="nofollow noopener">WeightedRandomSampler</a> and oversample the minority class.</p>

mohamadal: <p>Thank you very much <a class="mention" href="/u/ptrblck">@ptrblck</a>. This will apply random transformations on the images within the minority class without physically changing the size of the minority class, right? I mean, if my dataset has 100 images, 90 of one class and 10 in the other class, I will get the effect of augmentation by iterating many times over it and not by physically having a 90:90 balanced set where 80 minority images were added through transformations. Am I right?<br>
Also, oversampling through WeightedRandomSampler just adds exact copies of the minority to reach the target balanced weights, correct?</p>

ptrblck: <p>You are correct regarding the transformation. The transformation will be applied on the fly on your minority class data.</p>
<p>You are also correct regarding the <code>WeightedRandomSampler</code>, if you are keeping the default <code>replacement=True</code> argument.</p>

Preet_Khaturia: <p><a class="mention" href="/u/ptrblck">@ptrblck</a> Can you give an example for how to select the weights?</p>

ptrblck: <p>Sure!<br>
I’ve created some examples <a href="https://discuss.pytorch.org/t/some-problems-with-weightedrandomsampler/23242/2?u=ptrblck">here</a> and <a href="https://discuss.pytorch.org/t/is-there-a-limit-on-how-disbalanced-a-train-set-can-be/26334/6?u=ptrblck">here</a>.<br>
Let me know, if you need some more explanation!</p>

Ali_Aghababaei: <p>Dear <a class="mention" href="/u/ptrblck">@ptrblck</a>,<br>
Thank you very much for your explanation.<br>
You mentioned two approaches to overcome the class imbalance, 1) using <code>WeightedRandomSampler</code> and 2) using torchvision transformations on just the minority class. I had a question in this regard:<br>
Unlike the approach1, it is not possible to exactly calculate “the number” of our newly-produced minority class (actually being transformed in each epoch) in the approach 2. Am I right?</p>

ptrblck: <aside class="quote no-group" data-username="Ali_Aghababaei" data-post="7" data-topic="13797">
<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/ali_aghababaei/48/61342_2.png" class="avatar"> Ali_Aghababaei:</div>
<blockquote>
<p>You mentioned two approaches to overcome the class imbalance, 1) using <code>WeightedRandomSampler</code> and 2) using torchvision transformations on just the minority class.</p>
</blockquote>
</aside>
<p>I don’t know how well augmenting the minority class is to counter class imbalance training issues and note that my code snippet was a direct response to the topic question. It could work, but I haven’t run any experiments.</p>
<aside class="quote no-group" data-username="Ali_Aghababaei" data-post="7" data-topic="13797">
<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/ali_aghababaei/48/61342_2.png" class="avatar"> Ali_Aghababaei:</div>
<blockquote>
<p>Unlike the approach1, it is not possible to exactly calculate “the number” of our newly-produced minority class (actually being transformed in each epoch) in the approach 2.</p>
</blockquote>
</aside>
<p>The transformation will be applied in each <code>__getitem__</code> call on the sample if it comes from the minority class. If you are using random transformations I would expect to see no repetitions in these samples and each new epoch will use newly transformed samples for this class.</p>

Ali_Aghababaei: <p>Understood. Thanks a lot for the clarification.</p>