[PYTHON] [Tutoriel PyTorch ④] FORMATION D'UN CLASSIFICATEUR

introduction

Ceci est le 4ème volet de PyTorch Tutoriel officiel après Dernière fois. Cette fois, nous allons procéder avec FORMATION D'UN CLASSIFIER.

Classification des classes d'apprentissage

La dernière fois a vu comment définir un réseau neuronal pour calculer les pertes et mettre à jour les poids du réseau. Cette fois, nous examinerons le problème de classification à l'aide de données d'image. PyTorch fournit une bibliothèque torchvision pour la gestion des données d'image. torchvision est également fourni avec des jeux de données d'image de base tels que Imagenet, CIFAR-10 et MNIST. Ce didacticiel utilise le jeu de données CIFAR-10.

CIFAR-10

Le CIFAR-10 est une image couleur 32x32 pixels avec 3 canaux RVB dans la forme (3,32,32). Les cours sont classés en 10 catégories: "Avion", "Voiture", "Oiseau", "Chat", "Cerf", "Chien", "Grenouille", "Cheval", "Bateau", "Camion" ..

cifar10.png

Apprentissage de la classification des images

Voyons le flux d'apprentissage avec CIFAR-10. Apprendre à classer les images implique les étapes suivantes dans l'ordre:

  1. Utilisez torchvision pour charger et normaliser l'ensemble de données de formation et de test CIFAR10
  2. Définition du réseau neuronal convolutif
  3. Définir la fonction de perte et l'algorithme d'optimisation
  4. Apprenez avec les données d'entraînement
  5. Vérifiez le résultat appris avec les données de test

1. Chargement et normalisation de CIFAR-10

Il est pratique d'utiliser ** Dataset ** et ** DataLoader ** pour charger des données avec PyTorch. L'ensemble de données contient l'image et l'étiquette de réponse correcte (une donnée d'apprentissage). DataLoader Un utilitaire pour acquérir à plusieurs reprises des données d'entraînement (données de test).

import torch
import torchvision
import torchvision.transforms as transforms

#Définition de la transformation
#Convertir en Tensor avec ToTensor
#Standardisation( X - 0.5) / 0.5 
transform = transforms.Compose([
     transforms.ToTensor(),
     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])

#Ensemble de données de formation
trainset = torchvision.datasets.CIFAR10(root='./data', train=True,
                                        download=True, transform=transform)

#Chargeur de données d'entraînement
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4,
                                          shuffle=False, num_workers=2)

#Jeu de données de test
testset = torchvision.datasets.CIFAR10(root='./data', train=False,
                                       download=True, transform=transform)

#Chargeur de données de test
testloader = torch.utils.data.DataLoader(testset, batch_size=4,
                                         shuffle=False, num_workers=2)

#Liste des classifications
classes = ('plane', 'car', 'bird', 'cat',
           'deer', 'dog', 'frog', 'horse', 'ship', 'truck')

Tout d'abord, la transformation définit la méthode de conversion de l'ensemble de données. Compose connecte plusieurs transformations en séquence. Ici, nous exécutons ToTensor et Normalize. ToTensor convertit les données d'image en Tensor. Dans ToTensor, les valeurs RVB sont représentées par le type de fload [0, 1]. Normaliser calcule (X --0,5) / 0,5 et convertit la plage RVB en [-1, 1].

Certaines images sont affichées avec le code suivant. Puisque le batch_size du trainloader est 4, 4 images sont traitées ensemble.

import matplotlib.pyplot as plt
import numpy as np

#Fonction pour afficher une image
def imshow(img):
    img = img / 2 + 0.5     #Revenir à la normalisation
    npimg = img.numpy()
    plt.imshow(np.transpose(npimg, (1, 2, 0)))


#Obtenir des images à partir des données d'entraînement (aléatoires)
dataiter = iter(trainloader)
images, labels = dataiter.next()

#Afficher l'image
imshow(torchvision.utils.make_grid(images))
#Afficher l'étiquette
print(' '.join('%5s' % classes[labels[j]] for j in range(4)))

frog truck truck deer imshow.png

2. Définition du réseau neuronal convolutif

Copiez le réseau de neurones du didacticiel de réseau de neurones précédent et modifiez-le pour obtenir une image à 3 canaux (plutôt que l'image à 1 canal définie).

import torch.nn as nn
import torch.nn.functional as F


class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1, 16 * 5 * 5)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x

net = Net()

3. Définir la fonction de perte et l'algorithme d'optimisation

Dans les problèmes de classification, la fonction de perte utilise principalement la fonction d'erreur d'entropie croisée. Pour les problèmes de classification binaire, torch.nn.BCEWithLogitsLoss Pour les problèmes de classification multiclasse, torch.nn.CrossEntropyLoss Est souvent utilisé. Cette fois, nous avons 10 classifications d'étiquettes (classification multi-classes), nous allons donc utiliser CrossEntropyLoss. L'algorithme d'optimisation doit être la «méthode probabiliste de descente de gradient» (SGD) la plus élémentaire.

import torch.optim as optim

criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

4. Apprenez avec les données d'entraînement

Parcourez le chargeur de données et diffusez les données d'entraînement sur le réseau pour optimiser les paramètres.

for epoch in range(2):  #Boucle à plusieurs reprises

    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        #Obtenez des données d'entraînement
        inputs, labels = data

        #Initialiser le dégradé
        optimizer.zero_grad()

        #Passer des données à travers un réseau neuronal et calculer la propagation vers l'avant
        outputs = net(inputs)
        #Calcul d'erreur
        loss = criterion(outputs, labels)
        #Calcul de rétropropagation
        loss.backward()
        #Calcul du poids
        optimizer.step()

        #Afficher le statut
        running_loss += loss.item()
        if i % 2000 == 1999:    # 2,000 données chacun
            print('[%d, %5d] loss: %.3f' %
                  (epoch + 1, i + 1, running_loss / 2000))
            running_loss = 0.0

print('Finished Training')

L'apprentissage sera terminé dans environ 2 minutes.

[1,  2000] loss: 2.153
[1,  4000] loss: 1.830
[1,  6000] loss: 1.654
[1,  8000] loss: 1.556
[1, 10000] loss: 1.524
[1, 12000] loss: 1.511
[2,  2000] loss: 1.441
[2,  4000] loss: 1.380
[2,  6000] loss: 1.384
[2,  8000] loss: 1.358
[2, 10000] loss: 1.335
[2, 12000] loss: 1.320
Finished Training

5. Vérifiez les résultats tirés des données de test

Vérifiez le résultat appris avec les données de test. Jetons un coup d'œil à certaines des données de test.

dataiter = iter(testloader)
images, labels = dataiter.next()

# print images
imshow(torchvision.utils.make_grid(images))
print('Données des enseignants: ', ' '.join('%5s' % classes[labels[j]] for j in range(4)))

Données de l'enseignant: avion de bateau de bateau de chat imshow.png

Voyons comment le modèle (classificateur) qui a formé ces quatre images juge. Transmettez les données de test au réseau formé et vous obtiendrez les résultats.

outputs = net(images)
print(outputs[0,:])
tensor([-1.0291, -3.1352,  0.5837,  3.7728, -1.3638,  3.4090,  0.4094,  0.3352,
        -0.6388, -1.4808], grad_fn=<SliceBackward>)

Le poids de chaque étiquette (10 pièces) est renvoyé en sortie.

_, predicted = torch.max(outputs, 1)

print('Predicted: ', ' '.join('%5s' % classes[predicted[j]]
                              for j in range(4)))

Obtenez l'indice maximum avec max. Si vous spécifiez deux valeurs de retour pour max, l'index avec la valeur maximale est renvoyé en premier et l'index avec la valeur maximale est renvoyé en second.

Predicted:    cat  ship  ship plane

Il a été confirmé que cela correspond aux données des enseignants.

Vérifions le résultat avec toutes les données de test.

correct = 0
total = 0
with torch.no_grad():
    for data in testloader:
        images, labels = data
        outputs = net(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

print('Accuracy of the network on the 10000 test images: %d %%' % (
    100 * correct / total))
Accuracy of the network on the 10000 test images: 52 %

Avec 10 000 données de test, le taux de réponse correcte était de 52%. Si vous n'avez pas appris, c'est 1/10 (10%), donc vous pouvez apprendre quelque chose, mais ce n'est pas très précis. Regardons le taux de réponse correct pour chaque étiquette.

class_correct = list(0. for i in range(10))
class_total = list(0. for i in range(10))
with torch.no_grad():
    for data in testloader:
        images, labels = data
        outputs = net(images)
        _, predicted = torch.max(outputs, 1)
        c = (predicted == labels).squeeze()
        for i in range(4):
            label = labels[i]
            class_correct[label] += c[i].item()
            class_total[label] += 1


for i in range(10):
    print('Accuracy of %5s : %2d %%' % (
        classes[i], 100 * class_correct[i] / class_total[i]))
Accuracy of plane : 65 %
Accuracy of   car : 51 %
Accuracy of  bird : 33 %
Accuracy of   cat : 22 %
Accuracy of  deer : 39 %
Accuracy of   dog : 64 %
Accuracy of  frog : 66 %
Accuracy of horse : 70 %
Accuracy of  ship : 53 %
Accuracy of truck : 61 %

Il semble qu'il y ait des cas comme le chat que je n'ai pas beaucoup appris.

Apprendre sur GPU

Enfin, regardons l'apprentissage sur le GPU. Si vous disposez d'un environnement compatible GPU, vous pouvez l'utiliser pour entraîner votre réseau neuronal. Si vous utilisez Google Colaboratory, vous pouvez utiliser le GPU en sélectionnant "Runtime" ⇒ "Change Runtime Type" ⇒ "GPU".

Vous pouvez vérifier l'utilisation du GPU avec le code suivant.

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
# Assume that we are on a CUDA machine, then this should print a CUDA device:
print(device)

Si l'appareil est "cuda", vous pouvez utiliser le GPU. Si vous utilisez un GPU, vous devez écrire du code pour transférer le modèle vers le GPU.

net.to(device)

De même, les données d'entraînement doivent être transférées vers le GPU.

inputs, labels = inputs.to(device), labels.to(device)

J'ai vérifié le temps nécessaire pour étudier ce tutoriel sur Google Colaboratory Si vous n'utilisez pas de GPU: 2 minutes 10 secondes Lors de l'utilisation du GPU: 1 minute 40 secondes était. Si les dimensions des données d'apprentissage ne sont pas si complexes, l'effet semble faible.

À la fin

C'est le contenu du quatrième tutoriel de PyTorch, "FORMATION D'UN CLASSIFIER". J'ai pu comprendre le flux de base de l'apprentissage.

La prochaine fois, j'aimerais continuer avec le cinquième tutoriel "APPRENDRE PYTORCH AVEC précision".

Histoire

2020/04/29 Première édition publiée

Recommended Posts

[Tutoriel PyTorch ④] FORMATION D'UN CLASSIFICATEUR
Tutoriel [PyTorch] (version japonaise) ④ ~ FORMATION D'UN CLASSIFICATEUR (classification d'images) ~
[Tutoriel PyTorch ①] Qu'est-ce que PyTorch?
[Tutoriel PyTorch ③] RÉSEAUX NEURAUX
[Tutoriel PyTorch ⑦] Visualisation des modèles, des données et de la formation avec Tensorboard
Apprenez librosa avec un tutoriel 1
Tutoriel [PyTorch] (version japonaise) ② ~ AUTOGRAD ~
Tutoriel Pepper (5): Utilisation d'une tablette
Tutoriel [PyTorch] (version japonaise) ① ~ Tensol ~
[Tutoriel PyTorch ②] Autograd: différenciation automatique
Tutoriel sur le réseau neuronal (CNN) de Pytorch 1.3.1.
Créer un identifiant Santa à partir d'une image du Père Noël
[Tutoriel PyTorch ⑤] Apprentissage de PyTorch avec des exemples (Partie 2)
[Tutoriel PyTorch ⑤] Apprentissage de PyTorch avec des exemples (Partie 1)
Détection de visage à l'aide d'un classificateur en cascade
[Tutoriel PyTorch ⑥] Qu'est-ce que torch.nn?