web-dev-qa-db-fra.com

PyTorch: Test avec torchvision.datasets.ImageFolder et DataLoader

Je suis un débutant qui essaie de faire fonctionner ce PyTorch CNN avec le jeu de données Cats & Dogs de kaggle . Comme il n'y a pas de cibles pour les images de test, j'ai manuellement classé certaines des images de test et mis la classe dans le nom du fichier, pour pouvoir tester (vous devriez peut-être simplement utiliser certaines images de train).

J'ai utilisé la classe torchvision.datasets.ImageFolder pour charger le train et tester des images. La formation semble fonctionner.

Mais que dois-je faire pour que la routine de test fonctionne? Je ne sais pas comment connecter mon test_data_loader à la boucle de test en bas, via test_x et test_y. 

Le code est basé sur cet exemple de MNIST CNN. Là, quelque chose comme ceci est utilisé juste après la création des chargeurs. Mais je n'ai pas réussi à le réécrire pour mon jeu de données:

test_x = Variable(torch.unsqueeze(test_data.test_data, dim=1), volatile=True).type(torch.FloatTensor)[:2000]/255.   # shape from (2000, 28, 28) to (2000, 1, 28, 28), value in range(0,1)
test_y = test_data.test_labels[:2000]

Le code:

import os
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.autograd import Variable
import torch.utils.data as data
import torchvision
from torchvision import transforms

EPOCHS = 2
BATCH_SIZE = 10
LEARNING_RATE = 0.003
TRAIN_DATA_PATH = "./train_cl/"
TEST_DATA_PATH = "./test_named_cl/"
TRANSFORM_IMG = transforms.Compose([
    transforms.Resize(256),
    transforms.CenterCrop(256),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406],
                         std=[0.229, 0.224, 0.225] )
    ])

train_data = torchvision.datasets.ImageFolder(root=TRAIN_DATA_PATH, transform=TRANSFORM_IMG)
train_data_loader = data.DataLoader(train_data, batch_size=BATCH_SIZE, shuffle=True,  num_workers=4)
test_data = torchvision.datasets.ImageFolder(root=TEST_DATA_PATH, transform=TRANSFORM_IMG)
test_data_loader  = data.DataLoader(test_data, batch_size=BATCH_SIZE, shuffle=True, num_workers=4) 

class CNN(nn.Module):
    # omitted...

if __== '__main__':

    print("Number of train samples: ", len(train_data))
    print("Number of test samples: ", len(test_data))
    print("Detected Classes are: ", train_data.class_to_idx) # classes are detected by folder structure

    model = CNN()    
    optimizer = torch.optim.Adam(model.parameters(), lr=LEARNING_RATE)
    loss_func = nn.CrossEntropyLoss()    

    # Training and Testing
    for Epoch in range(EPOCHS):        
        for step, (x, y) in enumerate(train_data_loader):
            b_x = Variable(x)   # batch x (image)
            b_y = Variable(y)   # batch y (target)
            output = model(b_x)[0]          
            loss = loss_func(output, b_y)   
            optimizer.zero_grad()           
            loss.backward()                 
            optimizer.step()

            # Test -> this is where I have no clue
            if step % 50 == 0:
                test_x = Variable(test_data_loader)
                test_output, last_layer = model(test_x)
                pred_y = torch.max(test_output, 1)[1].data.squeeze()
                accuracy = sum(pred_y == test_y) / float(test_y.size(0))
                print('Epoch: ', Epoch, '| train loss: %.4f' % loss.data[0], '| test accuracy: %.2f' % accuracy)
3
kett

En regardant les données de Kaggle et votre code, il semble que le chargement de vos données, qu’il s’agisse du train ou du test, pose des problèmes. Tout d’abord, les données doivent figurer dans un dossier différent par étiquette pour que PyTorch ImageFolder par défaut soit chargé correctement. Dans votre cas, étant donné que toutes les données de formation se trouvent dans le même dossier, PyTorch les charge en tant que classe et que l'apprentissage semble donc fonctionner. Vous pouvez corriger cela en utilisant une structure de dossiers telle que - train/dog, - train/cat, - test/dog, - test/cat, puis en transmettant le train et le dossier de test au train et à tester ImageFolder respectivement. Le code de formation semble bien, il suffit de changer la structure du dossier et vous devriez être bon. Consultez la documentation officielle de ImageFolder qui présente un exemple similaire. 

4
Monster

Selon le commentaire de @ Monster ci-dessus, voici la structure de mon dossier pour ImageFolder.

 enter image description here

Et voici comment je charge le jeu de données:

    train_dataset=datasets.ImageFolder(root="./root/",transform=train_transforms)
0
Mo-Gang