Datasets.ImageFolder() targets one hot encoded?

username: wilhelmberghammer
cooked: <p>Hi guys,</p>
<p>I’m loading my image dataset (3 classes) with datasets.ImageFolder(), unfortunately the labels are then integers. So for the first class the label is 0, for the second it is 1 and for the last it is 2. I’d like the labels to be one hot encoded tho. Is there a way I can do this with the target_transform property when loading the data?</p>
<p>I’ve tried nn.functinal.one_hot() for example but I always need an input for this functions but I don’t know what to use as an input.</p>
<p>I also tried to use torch.eye(3)[i] where i is the label (0, 1 or 2) but again, i need the target as an input.</p>
<p>Is there a way to do this?</p>
<p>Thank you</p>

username: wilhelmberghammer
cooked: <h2>My provisional fix:</h2>
<p>example training loop:</p>
<pre><code class="lang-python">
for epoch in range(EPOCHS):
    for i, (images, labels) in tqdm(enumerate(train_dl)):
        images = images.to(device)
        labels = torch.eye(3)[labels].to(device)
        
        preds = model(images)
        loss = loss_func(preds, labels)

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

</code></pre>
<p>During every iteration, when pushing the labels to the device (‘cuda’ or ‘cpu’ etc.), a one hot vector is created.<br>
<code>labels = torch.eye(3)[labels].to(device)</code></p>
<pre><code class="lang-python">torch.eye(3)

'''output:

[[1, 0, 0]
 [0, 1, 0]
 [0, 0, 1]]

'''

torch.eye(3)[0]

'''output:

[1, 0, 0]

'''
</code></pre>
<p>So when the label is 0 the one hot vector is [1, 0, 0], for 1 it is [0, 1, 0] and so on.</p>
<p><strong>Still, I’d like a fix using the target_transform attribute tho!</strong></p>

username: Alexey_Demyanchuk
cooked: <p>According to the docs target_transform should be callable. Assuming you know the number of classes in advance, something like this should work:</p>
<pre><code class="lang-auto">def target_to_oh(target: int) -&gt; List[int]:
    NUM_CLASS = 5  # hard code here, can do partial
    one_hot = [0] * NUM_CLASS
    one_hot[target] = 1
    return one_hot

# Use here
ds = ImageFolder('some/path', target_transform=target_to_oh)
</code></pre>
<p>I didn’t try it. May have some errors but conceptually should work</p>

username: Henry_Chibueze
cooked: <p>Whether u encode them one-hot style (pun intended) or not it’ll still give u the same or similar results.</p>
<p>Still let me tell u what I usually do:<br>
I created a small block of code that iterates through my dataset and assign each label to them as one hot encoded <code>np.eye(3)[Idx]</code> given the directory it belonged to.<br>
Then I saved the entire dataset as a .npy file, then after I load it I convert the numpy instances to tensors (u can also make them tensors from start tho)</p>
<p>I would have posted the sample code here, but I’m currently out and not with my PC at the moment so u’ll have to wait till evening (about 5 hrs from now).</p>

username: wilhelmberghammer
cooked: <p><strong>Thank you,</strong> <a class="mention" href="/u/alexey_demyanchuk">@Alexey_Demyanchuk</a><br>
I got an error when trying your code, but then I changed it a bit and it worked like that:</p>
<pre><code class="lang-python">def target_to_oh(target):
    NUM_CLASS = 3  # hard code here, can do partial
    one_hot = torch.eye(NUM_CLASS)[target]
    return one_hot
</code></pre>