Tutorial PyTorch: regressione, esempio di classificazione delle immagini

Riepilogo del tutorial di Pytorch

In questo tutorial di Pytorch imparerai tutti i concetti da zero. Questo tutorial copre argomenti da base ad avanzati come la definizione di Pytorch, i vantaggi e gli svantaggi di Pytorch, il confronto, l'installazione, il framework Pytorch, la regressione e la classificazione delle immagini. Questo tutorial su Python è assolutamente gratuito.

Cos'è PyTorch?

PyTorch è una libreria di machine learning open source basata su Torch per l'utilizzo dell'elaborazione del linguaggio naturale Python. È simile a NumPy ma con un potente supporto GPU. Offre grafici computazionali dinamici che puoi modificare mentre sei in movimento con l'aiuto di autograd. PyTorch è anche più veloce di altri framework. È stato sviluppato dall'AI Research Group di Facebook nel 2016.

PyTorch Vantaggi e svantaggi

Di seguito sono riportati i vantaggi e gli svantaggi di PyTorch:

Vantaggi di PyTorch

  1. Biblioteca semplice
    Il codice PyTorch è semplice. È facile da capire e utilizzi immediatamente la libreria. Ad esempio, dai un'occhiata allo snippet di codice seguente:
class Net(torch.nn.Module):
   def __init__(self):
       super(Net, self).__init__()
       self.layer = torch.nn.Linear(1, 1)

   def forward(self, x):
       x = self.layer(x)      
       return x

Come accennato in precedenza, è possibile definire facilmente il modello di rete e comprendere rapidamente il codice senza molta formazione.

  1. Grafico computazionale dinamico

Grafico computazionale dinamico

Fonte immagine: esplorazione del deep learning con PyTorch

Pytorch offre il grafico computazionale dinamico (DAG). I grafici computazionali sono un modo per esprimere espressioni matematiche in modelli di grafici o teorie come nodi e spigoli. Il nodo eseguirà l'operazione matematica e il bordo è un tensore che verrà immesso nei nodi e trasporterà l'output del nodo in Tensore.

DAG è un grafico che ha una forma arbitraria ed è in grado di eseguire operazioni tra diversi grafici di input. Ad ogni iterazione viene creato un nuovo grafico. Quindi, è possibile avere la stessa struttura del grafico o creare un nuovo grafico con un'operazione diversa, oppure possiamo chiamarlo grafico dinamico.

  1. migliori prestazioni

Comunità e ricercatori confrontano e confrontano i framework per vedere quale è più veloce. Un repository GitHub Benchmark su framework e GPU per il deep learning ha riferito che PyTorch è più veloce dell'altro framework in termini di immagini elaborate al secondo.

Come puoi vedere di seguito, i grafici di confronto con vgg16 e resnet152

Vantaggi di PyTorch

Vantaggi di PyTorch

  1. Native Python

PyTorch è più basato su Python. Ad esempio, se desideri addestrare un modello, puoi utilizzare il flusso di controllo nativo come il looping e le ricorsioni senza la necessità di aggiungere ulteriori variabili o sessioni speciali per poterli eseguire. Questo è molto utile per il processo di formazione.

Pytorch implementa anche la programmazione imperativa ed è decisamente più flessibile. Quindi è possibile stampare il valore del tensore nel bel mezzo di un processo di calcolo.

Svantaggio di PyTorch

PyTorch richiede applicazioni di terze parti per la visualizzazione. Richiede inoltre un server API per la produzione.

Successivamente in questo tutorial su PyTorch, impareremo la differenza tra PyTorch e TensorFlow.

PyTorch vs. Tensorflusso

Parametro PyTorch tensorflow
Definizione del modello Il modello è definito in una sottoclasse e offre un pacchetto facile da usare Il modello è definito con molti ed è necessario comprenderne la sintassi
Supporto GPU Si Si
Tipo di grafico Dinamico statica
Strumenti Nessuno strumento di visualizzazione È possibile utilizzare lo strumento di visualizzazione Tensorboard
Comunità La comunità continua a crescere Grandi comunità attive

Installazione di PyTorch

Linux

È semplice installarlo su Linux. Puoi scegliere di utilizzare un ambiente virtuale o installarlo direttamente con accesso root. Digita questo comando nel terminale

pip3 install --upgrade torch torchvision

AWS SageMaker

Sagemaker è una delle piattaforme in Amazon Servizio web che offre un potente motore di machine learning con configurazioni di deep learning preinstallate per consentire a data scientist o sviluppatori di creare, addestrare e distribuire modelli su qualsiasi scala.

Prima apri il file Amazon Sagemaker console e clicca su Crea istanza notebook e compila tutti i dettagli per il tuo notebook.

AWS SageMaker

Passaggio successivo: fai clic su Apri per avviare l'istanza del tuo notebook.

AWS SageMaker

Infine, In Jupyter, Fai clic su Nuovo e scegli conda_pytorch_p36 e sei pronto per utilizzare l'istanza del tuo notebook con Pytorch installato.

Successivamente in questo tutorial su PyTorch, impareremo le nozioni di base sul framework PyTorch.

Nozioni di base sul framework PyTorch

Impariamo i concetti di base di PyTorch prima di approfondire. PyTorch utilizza Tensor per ogni variabile simile a ndarray di Numpy ma con supporto per il calcolo GPU. Qui spiegheremo il modello di rete, la funzione di perdita, Backprop e Optimizer.

Modello di rete

La rete può essere costruita sottoclassando torch.nn. Ci sono 2 parti principali,

  1. La prima parte è definire i parametri e i livelli che utilizzerai
  2. La seconda parte è l'attività principale chiamata processo di inoltro che prenderà un input e prevederà l'output.
Import torch
import torch.nn as nn
import torch.nn.functional as F

class Model(nn.Module):
 def __init__(self):
        super(Model, self).__init__()
        self.conv1 = nn.Conv2d(3, 20, 5)
        self.conv2 = nn.Conv2d(20, 40, 5)
self.fc1 = nn.Linear(320, 10)

def forward(self, x):
       x = F.relu(self.conv1(x))
       x = F.relu(self.conv2(x))
       x = x.view(-1, 320)
       x = F.relu(self.fc1(x))
       return F.log_softmax(x)

net = Model()

Come puoi vedere sopra, crei una classe di nn.Module chiamata Model. Contiene 2 livelli Conv2d e un livello Lineare. Il primo strato conv2d prende un input di 3 e una forma di output di 20. Il secondo strato prenderà un input di 20 e produrrà una forma di output di 40. L'ultimo strato è uno strato completamente connesso nella forma di 320 e produrrà un'uscita di 10.

Il processo di inoltro prenderà un input di X e lo inserirà nel livello conv1 ed eseguirà la funzione ReLU,

Allo stesso modo, alimenterà anche il livello conv2. Successivamente, la x verrà rimodellata in (-1, 320) e inserita nello strato FC finale. Prima di inviare l'output, utilizzerai la funzione di attivazione di softmax.

Il processo all'indietro viene definito automaticamente da autograd, quindi è necessario definire solo il processo in avanti.

Funzione di perdita

La funzione di perdita viene utilizzata per misurare quanto bene il modello di previsione è in grado di prevedere i risultati attesi. PyTorch ha già molte funzioni di perdita standard nel modulo torch.nn. Ad esempio, puoi utilizzare la perdita di entropia incrociata per risolvere un problema di classificazione PyTorch multiclasse. È facile definire la funzione di perdita e calcolare le perdite:

loss_fn = nn.CrossEntropyLoss()

#training process
loss = loss_fn(out, target)

È facile utilizzare il calcolo della funzione di perdita con PyTorch.

Backprop

Per eseguire la propagazione all'indietro, chiami semplicemente los.backward(). L'errore verrà calcolato ma ricorda di cancellare il gradiente esistente con zero_grad()

net.zero_grad() # to clear the existing gradient
loss.backward() # to perform backpropragation

Optimizer

torch.optim fornisce algoritmi di ottimizzazione comuni. Puoi definire un ottimizzatore con un semplice passaggio:

optimizer = torch.optim.SGD(net.parameters(), lr = 0.01, momentum=0.9)

È necessario passare i parametri del modello di rete e la velocità di apprendimento in modo che ad ogni iterazione i parametri vengano aggiornati dopo il processo backprop.

Regressione semplice con PyTorch

Impariamo la semplice regressione con gli esempi PyTorch:

Passaggio 1) Creazione del nostro modello di rete

Il nostro modello di rete è un semplice livello lineare con una forma di input e output pari a 1.

from __future__ import print_function

import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.autograd import Variable

class Net(nn.Module):
   def __init__(self):
       super(Net, self).__init__()
       self.layer = torch.nn.Linear(1, 1)

   def forward(self, x):
       x = self.layer(x)      
       return x

net = Net()
print(net)

E l'output della rete dovrebbe essere così

Net(
  (hidden): Linear(in_features=1, out_features=1, bias=True)
)

Passaggio 2) Testare i dati

Prima di iniziare il processo di formazione, devi conoscere i nostri dati. Crea una funzione casuale per testare il nostro modello. Y = x3 peccato(x)+ 3x+0.8 rand(100)

# Visualize our data
import matplotlib.pyplot as plt
import numpy as np

x = np.random.rand(100)
y = np.sin(x) * np.power(x,3) + 3*x + np.random.rand(100)*0.8

plt.scatter(x, y)
plt.show()

Ecco il grafico a dispersione della nostra funzione:

Grafico a dispersione di regressione semplice con PyTorch

Prima di iniziare il processo di training, è necessario convertire l'array Numpy in variabili supportate da Torch e autograd, come mostrato nell'esempio di regressione PyTorch riportato di seguito.

# convert numpy array to tensor in shape of input size
x = torch.from_numpy(x.reshape(-1,1)).float()
y = torch.from_numpy(y.reshape(-1,1)).float()
print(x, y)

Passaggio 3) Ottimizzatore e perdita

Successivamente, dovresti definire l'ottimizzatore e la funzione di perdita per il nostro processo di formazione.

# Define Optimizer and Loss Function
optimizer = torch.optim.SGD(net.parameters(), lr=0.2)
loss_func = torch.nn.MSELoss()

Passaggio 4) Formazione

Ora iniziamo il nostro processo di formazione. Con un'epoca di 250, iterarai i nostri dati per trovare il valore migliore per i nostri iperparametri.

inputs = Variable(x)
outputs = Variable(y)
for i in range(250):
   prediction = net(inputs)
   loss = loss_func(prediction, outputs) 
   optimizer.zero_grad()
   loss.backward()        
   optimizer.step()       

   if i % 10 == 0:
       # plot and show learning process
       plt.cla()
       plt.scatter(x.data.numpy(), y.data.numpy())
       plt.plot(x.data.numpy(), prediction.data.numpy(), 'r-', lw=2)
       plt.text(0.5, 0, 'Loss=%.4f' % loss.data.numpy(), fontdict={'size': 10, 'color':  'red'})
       plt.pause(0.1)

plt.show()

Passaggio 5) Risultato

Come puoi vedere di seguito, hai eseguito con successo la regressione PyTorch con una rete neurale. In realtà, ad ogni iterazione, la linea rossa nel grafico si aggiornerà e cambierà la sua posizione per adattarsi ai dati. Ma in questa immagine mostra solo il risultato finale, come mostrato nell'esempio PyTorch qui sotto:

Grafico a dispersione del risultato della regressione semplice

Esempio di classificazione delle immagini con PyTorch

Uno dei metodi popolari per apprendere le basi di apprendimento profondo è con il set di dati MNIST. È il “Hello World” nel deep learning. Il set di dati contiene numeri scritti a mano da 0 a 9 con un totale di 60,000 campioni di addestramento e 10,000 campioni di test già etichettati con la dimensione di 28×28 pixel.

Classificazione delle immagini con PyTorch

Passaggio 1) Preelaborare i dati

Nel primo passaggio di questo esempio di classificazione PyTorch, caricherai il set di dati utilizzando il modulo torchvision.

Prima di iniziare il processo di formazione, è necessario comprendere i dati. Torchvision caricherà il set di dati e trasformerà le immagini con i requisiti appropriati per la rete come la forma e la normalizzazione delle immagini.

import torch
import torchvision
import numpy as np
from torchvision import datasets, models, transforms

# This is used to transform the images to Tensor and normalize it
transform = transforms.Compose(
   [transforms.ToTensor(),
    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])

training = torchvision.datasets.MNIST(root='./data', train=True,
                                       download=True, transform=transform)
train_loader = torch.utils.data.DataLoader(training, batch_size=4,
                                         shuffle=True, num_workers=2)

testing = torchvision.datasets.MNIST(root='./data', train=False,
                                      download=True, transform=transform)
test_loader = torch.utils.data.DataLoader(testing, batch_size=4,
                                        shuffle=False, num_workers=2)

classes = ('0', '1', '2', '3',
          '4', '5', '6', '7', '8', '9')
         
import matplotlib.pyplot as plt
import numpy as np

#create an iterator for train_loader
# get random training images
data_iterator = iter(train_loader)
images, labels = data_iterator.next()

#plot 4 images to visualize the data
rows = 2
columns = 2
fig=plt.figure()
for i in range(4):
   fig.add_subplot(rows, columns, i+1)
   plt.title(classes[labels[i]])
   img = images[i] / 2 + 0.5     # this is for unnormalize the image
   img = torchvision.transforms.ToPILImage()(img)
   plt.imshow(img)
plt.show()

La funzione di trasformazione converte le immagini in tensore e normalizza il valore. La funzione torchvision.transforms.MNIST scaricherà il set di dati (se non è disponibile) nella directory, imposterà il set di dati per l'addestramento, se necessario, ed eseguirà il processo di trasformazione.

Per visualizzare il set di dati, utilizzi data_iterator per ottenere il batch successivo di immagini ed etichette. Utilizzi matplot per tracciare queste immagini e la loro etichetta appropriata. Come potete vedere qui sotto le nostre immagini e le relative etichette.

Esempio di classificazione delle immagini con PyTorch

Passaggio 2) Configurazione del modello di rete

Ora, in questo esempio PyTorch, creerai una semplice rete neurale per la classificazione delle immagini PyTorch.

Qui ti presentiamo un altro modo per creare il modello di rete in PyTorch. Utilizzeremo nn.Sequential per creare un modello sequenza invece di creare una sottoclasse di nn.Module.

import torch.nn as nn

# flatten the tensor into 
class Flatten(nn.Module):
   def forward(self, input):
       return input.view(input.size(0), -1)

#sequential based model
seq_model = nn.Sequential(
           nn.Conv2d(1, 10, kernel_size=5),
           nn.MaxPool2d(2),
           nn.ReLU(),
           nn.Dropout2d(),
           nn.Conv2d(10, 20, kernel_size=5),
           nn.MaxPool2d(2),
           nn.ReLU(),
           Flatten(),
           nn.Linear(320, 50),
           nn.ReLU(),
           nn.Linear(50, 10),
           nn.Softmax(),
         )

net = seq_model
print(net)

Ecco l'output del nostro modello di rete

Sequential(
  (0): Conv2d(1, 10, kernel_size=(5, 5), stride=(1, 1))
  (1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (2): ReLU()
  (3): Dropout2d(p=0.5)
  (4): Conv2d(10, 20, kernel_size=(5, 5), stride=(1, 1))
  (5): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (6): ReLU()
  (7): Flatten()
  (8): Linear(in_features=320, out_features=50, bias=True)
  (9): ReLU()
  (10): Linear(in_features=50, out_features=10, bias=True)
  (11): Softmax()
)

Spiegazione della rete

  1. La sequenza prevede che il primo livello sia un livello Conv2D con una forma di input pari a 1 e una forma di output pari a 10 con una dimensione del kernel pari a 5
  2. Successivamente, hai un livello MaxPool2D
  3. Una funzione di attivazione ReLU
  4. un livello di eliminazione per eliminare i valori di bassa probabilità.
  5. Quindi un secondo Conv2d con la forma di input pari a 10 dall'ultimo livello e la forma di output pari a 20 con una dimensione del kernel pari a 5
  6. Successivamente un livello MaxPool2d
  7. Funzione di attivazione ReLU.
  8. Successivamente, appiattirai il tensore prima di inserirlo nel livello Lineare
  9. Il livello lineare mapperà il nostro output sul secondo livello lineare con la funzione di attivazione softmax

Passaggio 3) Addestrare il modello

Prima di iniziare il processo di formazione, è necessario impostare il criterio e la funzione di ottimizzazione.

Per il criterio utilizzerai CrossEntropyLoss. Per l'ottimizzatore, utilizzerai l'SGD con un tasso di apprendimento di 0.001 e uno slancio di 0.9 come mostrato nell'esempio PyTorch di seguito.

import torch.optim as optim

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

Il processo di inoltro prenderà la forma di input e la passerà al primo livello conv2d. Quindi da lì verrà inserito in maxpool2d e infine inserito nella funzione di attivazione ReLU. Lo stesso processo avverrà nel secondo livello conv2d. Successivamente, l'input verrà rimodellato in (-1,320) e inserito nel livello fc per prevedere l'output.

Ora inizierai il processo di formazione. Itererai il nostro set di dati 2 volte o con un'epoca pari a 2 e stamperai la perdita corrente ogni 2000 batch.

for epoch in range(2): 

#set the running loss at each epoch to zero
   running_loss = 0.0
# we will enumerate the train loader with starting index of 0
# for each iteration (i) and the data (tuple of input and labels)
   for i, data in enumerate(train_loader, 0):
       inputs, labels = data

# clear the gradient
       optimizer.zero_grad()

#feed the input and acquire the output from network
       outputs = net(inputs)

#calculating the predicted and the expected loss
       loss = criterion(outputs, labels)

#compute the gradient
       loss.backward()

#update the parameters
       optimizer.step()

       # print statistics
       running_loss += loss.item()
       if i % 1000 == 0:
           print('[%d, %5d] loss: %.3f' %
                 (epoch + 1, i + 1, running_loss / 1000))
           running_loss = 0.0

Ad ogni epoca, l'enumeratore otterrà la successiva tupla di input e le etichette corrispondenti. Prima di fornire l'input al nostro modello di rete, dobbiamo eliminare il gradiente precedente. Ciò è necessario perché dopo il processo all'indietro (processo di backpropagation), il gradiente verrà accumulato invece di essere sostituito. Quindi, calcoleremo le perdite dalla produzione prevista dalla produzione attesa. Successivamente, faremo una backpropagation per calcolare il gradiente e, infine, aggiorneremo i parametri.

Ecco l'output del processo di formazione

[1, 	1] loss: 0.002
[1,  1001] loss: 2.302
[1,  2001] loss: 2.295
[1,  3001] loss: 2.204
[1,  4001] loss: 1.930
[1,  5001] loss: 1.791
[1,  6001] loss: 1.756
[1,  7001] loss: 1.744
[1,  8001] loss: 1.696
[1,  9001] loss: 1.650
[1, 10001] loss: 1.640
[1, 11001] loss: 1.631
[1, 12001] loss: 1.631
[1, 13001] loss: 1.624
[1, 14001] loss: 1.616
[2, 	1] loss: 0.001
[2,  1001] loss: 1.604
[2,  2001] loss: 1.607
[2,  3001] loss: 1.602
[2,  4001] loss: 1.596
[2,  5001] loss: 1.608
[2,  6001] loss: 1.589
[2,  7001] loss: 1.610
[2,  8001] loss: 1.596
[2,  9001] loss: 1.598
[2, 10001] loss: 1.603
[2, 11001] loss: 1.596
[2, 12001] loss: 1.587
[2, 13001] loss: 1.596
[2, 14001] loss: 1.603

Passaggio 4) Testare il modello

Dopo aver addestrato il nostro modello, devi testarlo o valutarlo con altri set di immagini.

Utilizzeremo un iteratore per test_loader e genererà un batch di immagini ed etichette che verranno passate al modello addestrato. L'output previsto verrà visualizzato e confrontato con l'output previsto.

#make an iterator from test_loader
#Get a batch of training images
test_iterator = iter(test_loader)
images, labels = test_iterator.next()

results = net(images)
_, predicted = torch.max(results, 1)

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

fig2 = plt.figure()
for i in range(4):
   fig2.add_subplot(rows, columns, i+1)
   plt.title('truth ' + classes[labels[i]] + ': predict ' + classes[predicted[i]])
   img = images[i] / 2 + 0.5     # this is to unnormalize the image
   img = torchvision.transforms.ToPILImage()(img)
   plt.imshow(img)
plt.show()

Esempio di classificazione delle immagini con PyTorch

Sommario

  • PyTorch è un software open source basato su Torch machine Learning libreria per elaborazione del linguaggio naturale utilizzando Python.
  • Vantaggi di PyTorch: 1) Libreria semplice, 2) Grafico computazionale dinamico, 3) Prestazioni migliori, 4) Nativo Python
  • PyTorch utilizza Tensor per ogni variabile simile a ndarray di Numpy ma con supporto per il calcolo GPU.
  • Uno dei metodi più diffusi per apprendere le basi del deep learning è il set di dati MNIST.