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)
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.