La tua prima rete neurale sulla GPU. Guida per principianti

La tua prima rete neurale sulla GPU. Guida per principianti
In questo articolo, spiegherò come configurare un ambiente per l'apprendimento automatico in 30 minuti, creare una rete neurale per il riconoscimento delle immagini e poi eseguire la stessa rete su una scheda grafica (GPU).

Cominciamo definendo cosa sia una rete neurale.

Nel nostro caso, si tratta di un modello matematico e della sua implementazione software o hardware, costruito secondo il principio di organizzazione e funzionamento delle reti neurali biologiche — le reti di cellule nervose di un organismo vivo. Questo concetto è emerso durante lo studio dei processi che avvengono nel cervello e nel tentativo di modellare tali processi.

Le reti neurali non vengono programmate nel senso tradizionale del termine, ma vengono addestrate. La possibilità di apprendimento è uno dei principali vantaggi delle reti neurali rispetto agli algoritmi tradizionali. Dal punto di vista tecnico, l'addestramento consiste nel trovare i coefficienti delle connessioni tra i neuroni. Durante il processo di apprendimento, la rete neurale è in grado di identificare dipendenze complesse tra i dati in ingresso e quelli in uscita, nonché di eseguire generalizzazioni.

Dal punto di vista del machine learning, una rete neurale è un caso specifico dei metodi di riconoscimento di pattern, analisi discriminante, metodi di clustering e altri approcci simili.

Attrezzature

Iniziamo dall'hardware. Abbiamo bisogno di un server con un sistema operativo Linux installato. L'hardware per i sistemi di machine learning deve essere piuttosto potente e, di conseguenza, costoso. Per chi non ha a disposizione una buona macchina, consiglio di considerare l'offerta dei provider cloud. È possibile noleggiare il server necessario rapidamente e pagare solo per il tempo di utilizzo.

Nei progetti che richiedono la creazione di reti neurali, utilizzo server di uno dei fornitori di cloud russi. L'azienda offre server cloud in affitto specificamente per il machine learning, dotati di potenti GPU Tesla V100 di NVIDIA. In breve: l'uso di un server con GPU può essere decine di volte più efficiente (veloce) rispetto a un server con CPU simile per costo (il ben noto processore centrale). Questo è possibile grazie alle caratteristiche dell'architettura GPU, che gestisce i calcoli più rapidamente.

Per eseguire gli esempi descritti di seguito, abbiamo noleggiato un tale server per alcuni giorni:

  • Disco SSD da 150 GB
  • RAM da 32 GB
  • Processore Tesla V100 da 16 Gb con 4 core

Sul server abbiamo installato Ubuntu 18.04.

Installiamo l'ambiente

Ora installeremo sul server tutto il necessario per lavorare. Poiché il nostro articolo è principalmente per principianti, tratterò alcuni aspetti che saranno utili a loro.

La configurazione dell'ambiente richiede molto lavoro attraverso la riga di comando. La maggior parte degli utenti utilizza Windows come sistema operativo. La console standard di questo sistema lascia molto a desiderare. Pertanto, utilizzeremo uno strumento più comodo. Cmder/. Scarichiamo la mini versione e avviamo Cmder.exe. Successivamente, dobbiamo collegarci al server tramite il protocollo SSH:

ssh root@server-ip-or-hostname

Al posto di server-ip-or-hostname, inserite l'indirizzo IP o il nome DNS del vostro server. Inseriamo quindi la password e, se la connessione ha successo, dovremmo ricevere un messaggio simile.

Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-74-generic x86_64)

Il linguaggio principale per lo sviluppo di modelli ML è Python. E la piattaforma più popolare per il suo utilizzo su Linux è Anaconda.

Installiamola sul nostro server.

Iniziamo aggiornando il gestore locale dei pacchetti:

sudo apt-get update

Installiamo curl (strumento a riga di comando):

sudo apt-get install curl

Scarichiamo l'ultima versione di Anaconda Distribution:

cd /tmp
curl –O https://repo.anaconda.com/archive/Anaconda3-2019.10-Linux-x86_64.sh

Avviamo l'installazione:

bash Anaconda3-2019.10-Linux-x86_64.sh

Durante l'installazione sarà necessario confermare il contratto di licenza. Dopo un'installazione avvenuta con successo, dovresti vedere questo:

Grazie per aver installato Anaconda3!

Per lo sviluppo di modelli ML sono stati creati molti framework, noi lavoriamo con i più popolari: PyTorch e Tensorflow.

L'utilizzo del framework consente di aumentare la velocità di sviluppo e di sfruttare strumenti già pronti per compiti standard.

In questo esempio lavoreremo con PyTorch. Installiamolo:

conda install pytorch torchvision cudatoolkit=10.1 -c pytorch

Ora dobbiamo avviare Jupyter Notebook, uno strumento popolare tra i professionisti del ML. Permette di scrivere codice e vedere immediatamente i risultati della sua esecuzione. Jupyter Notebook è incluso in Anaconda ed è già installato sul nostro server. È necessario collegarsi ad esso dalla nostra macchina desktop.

Per fare ciò, prima avvieremo Jupyter sul server indicando la porta 8080:

jupyter notebook --no-browser --port=8080 --allow-root

Poi, aprendo un'altra scheda nella nostra console Cmder (menù in alto — New console dialog), ci collegheremo alla porta 8080 del server tramite SSH:

ssh -L 8080:localhost:8080 root@server-ip-or-hostname

Dopo aver inserito il primo comando, ci verranno fornite le link per aprire Jupyter nel nostro browser:

Per accedere al notebook, apri questo file in un browser:
        file:///root/.local/share/jupyter/runtime/nbserver-18788-open.html
    Oppure copia e incolla uno di questi URL:
        http://localhost:8080/?token=cca0bd0b30857821194b9018a5394a4ed2322236f116d311
     o http://127.0.0.1:8080/?token=cca0bd0b30857821194b9018a5394a4ed2322236f116d311

Utilizziamo il link per localhost:8080. Copia il percorso completo e incollalo nella barra degli indirizzi del browser locale del tuo PC. Si aprirà Jupyter Notebook.

Creiamo un nuovo notebook: New — Notebook — Python 3.

Verifichiamo il corretto funzionamento di tutti i componenti che abbiamo installato. Inseriamo in Jupyter un esempio di codice PyTorch e avviamo l'esecuzione (pulsante Run):

from __future__ import print_function
import torch
x = torch.rand(5, 3)
print(x)

Il risultato dovrebbe essere più o meno così:

La tua prima rete neurale sulla GPU. Guida per principianti

Se ottieni un risultato simile, significa che abbiamo configurato tutto correttamente e possiamo iniziare a sviluppare la rete neurale!

Creiamo una rete neurale

Stiamo per creare una rete neurale per il riconoscimento delle immagini. Prenderemo come base questo la guida.

Per addestrare la rete utilizzeremo il set di dati pubblico CIFAR10. Esso include le classi: «aereo», «automobile», «uccello», «gatto», «cervo», «cane», «rana», «cavallo», «nave», «camion». Le immagini in CIFAR10 hanno una dimensione di 3x32x32, ovvero immagini colorate a 3 canali di 32×32 pixel.

La tua prima rete neurale sulla GPU. Guida per principianti
Per il lavoro utilizzeremo il pacchetto PyTorch creato per la gestione delle immagini — torchvision.

Eseguiranno i seguenti passaggi in ordine:

  • Caricamento e normalizzazione dei set di dati di addestramento e test
  • Definizione della rete neurale
  • Addestramento della rete sui dati di addestramento
  • Test della rete sui dati di test
  • Ripeteremo l'addestramento e il test utilizzando la GPU

Tutto il codice qui sotto lo eseguiremo in Jupyter Notebook.

Caricamento e normalizzazione di CIFAR10

Copia e incolla il seguente codice in Jupyter:


import torch
import torchvision
import torchvision.transforms as transforms

transform = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])

trainset = torchvision.datasets.CIFAR10(root='./data', train=True,
                                        download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4,
                                          shuffle=True, num_workers=2)

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

classes = ('aereo', 'auto', 'uccello', 'gatto',
           'cervo', 'cane', 'rana', 'cavallo', 'nave', 'camion')

La risposta deve essere così:

Scaricando https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz in ./data/cifar-10-python.tar.gz
Estraendo ./data/cifar-10-python.tar.gz in ./data
File già scaricati e verificati

Mostriamo alcune immagini di addestramento per verifica:


import matplotlib.pyplot as plt
import numpy as np

# funzioni per mostrare un'immagine

def imshow(img):
    img = img / 2 + 0.5     # denormalizza
    npimg = img.numpy()
    plt.imshow(np.transpose(npimg, (1, 2, 0)))
    plt.show()

# ottieni alcune immagini di addestramento casuali
dataiter = iter(trainloader)
images, labels = dataiter.next()

# mostra le immagini
imshow(torchvision.utils.make_grid(images))
# stampa le etichette
print(' '.join('%5s' % classes[labels[j]] for j in range(4)))

La tua prima rete neurale sulla GPU. Guida per principianti

Definizione della rete neurale

Iniziamo a vedere come funziona una rete neurale per il riconoscimento delle immagini. Si tratta di una rete semplice a connessione diretta. Accetta i dati di input, li elabora attraverso diversi strati uno dopo l'altro e, infine, fornisce l'output.

La tua prima rete neurale sulla GPU. Guida per principianti

Creiamo una rete simile nel nostro ambiente:


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

Definiamo anche la funzione di perdita e l'ottimizzatore


import torch.optim as optim

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

Addestramento della rete sui dati di addestramento

Iniziamo l'addestramento della nostra rete neurale. Tieni presente che dopo aver eseguito questo codice, dovrai attendere un po' fino al termine dell'esecuzione. A me è servito circa 5 minuti. L'addestramento della rete richiede tempo.

 per epoch in range(2): # loop over the dataset multiple times

 running_loss = 0.0
 for i, data in enumerate(trainloader, 0):
 # ottieni gli input; data è una lista di [input, etichette]
 inputs, labels = data

 # azzera i gradienti dei parametri
 optimizer.zero_grad()

 # avanti + indietro + ottimizza
 outputs = net(inputs)
 loss = criterion(outputs, labels)
 loss.backward()
 optimizer.step()

 # stampa statistiche
 running_loss += loss.item()
 if i % 2000 == 1999: # stampa ogni 2000 mini-lotti
 print('[%d, ] loss: %.3f' %
 (epoch + 1, i + 1, running_loss / 2000))
 running_loss = 0.0

print('Formazione completata')

Otterremo questo risultato:

La tua prima rete neurale sulla GPU. Guida per principianti

Salviamo il nostro modello addestrato:

PATH = './cifar_net.pth'
torch.save(net.state_dict(), PATH)

Test della rete sui dati di test

Abbiamo addestrato la rete utilizzando un set di dati di addestramento. Ma dobbiamo verificare se la rete ha veramente appreso qualcosa.

Verificheremo questo prevedendo l'etichetta di classe emessa dalla rete neurale e controllandola per la verità. Se la previsione è corretta, aggiungiamo il campione all'elenco delle previsioni corrette.
Mostriamo un'immagine del set di test:

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

# stampa le immagini
imshow(torchvision.utils.make_grid(images))
print('Verità Terrena: ', ' '.join('%5s' % classes[labels[j]] for j in range(4)))

La tua prima rete neurale sulla GPU. Guida per principianti

Ora chiediamo alla rete neurale di dirci cosa c'è in queste immagini:


net = Net()
net.load_state_dict(torch.load(PATH))

outputs = net(images)

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

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

La tua prima rete neurale sulla GPU. Guida per principianti

I risultati sembrano piuttosto buoni: la rete ha identificato correttamente tre immagini su quattro.

Vediamo come si comporta la rete su tutto il set di dati.


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('Accuratezza della rete sulle 10000 immagini di test: %d %%' % (
    100 * correct / total))

La tua prima rete neurale sulla GPU. Guida per principianti

Sembra che la rete sappia qualcosa e stia funzionando. Se classificasse le classi a caso, l'accuratezza sarebbe del 10%.

Ora vediamo quali classi la rete identifica meglio:

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('Accuratezza di %5s : %%' % (
 classes[i], 100 * class_correct[i] / class_total[i]))

La tua prima rete neurale sulla GPU. Guida per principianti

Sembra che la rete identifichi meglio le auto e le navi: 71% di accuratezza.

Quindi, la rete funziona. Ora proviamo a trasferire il suo funzionamento sulla scheda grafica (GPU) e vediamo cosa cambia.

Addestramento della rete neurale su GPU

Iniziamo con una breve spiegazione di cosa sia CUDA. CUDA (Compute Unified Device Architecture) è una piattaforma di calcolo parallelo sviluppata da NVIDIA, per calcoli generali su schede grafiche (GPU). Grazie a CUDA, gli sviluppatori possono accelerare notevolmente le applicazioni di calcolo sfruttando le potenzialità delle schede grafiche. La piattaforma è già installata sul nostro server che abbiamo acquistato.

Iniziamo definendo la nostra GPU come primo dispositivo visibile CUDA.

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
# Supponendo di essere su una macchina CUDA, questo dovrebbe stampare un dispositivo CUDA:
print(device)

La tua prima rete neurale sulla GPU. Guida per principianti

Inviamo la rete sulla GPU:

net.to(device)

Dovremo anche inviare input e obiettivi ad ogni passaggio sulla GPU:

inputs, labels = data[0].to(device), data[1].to(device)

Avviamo il riaddestramento della rete già sulla GPU:

import torch.optim as optim

criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
for epoch in range(2): # loop over the dataset multiple times

 running_loss = 0.0
 for i, data in enumerate(trainloader, 0):
 # ottieni gli input; data è una lista di [input, etichette]
 inputs, labels = data[0].to(device), data[1].to(device)

 # azzera i gradienti dei parametri
 optimizer.zero_grad()

 # avanti + indietro + ottimizza
 outputs = net(inputs)
 loss = criterion(outputs, labels)
 loss.backward()
 optimizer.step()

 # stampa statistiche
 running_loss += loss.item()
 if i % 2000 == 1999: # stampa ogni 2000 mini-lotti
 print('[%d, ] loss: %.3f' %
 (epoch + 1, i + 1, running_loss / 2000))
 running_loss = 0.0

print('Formazione completata')

Questa volta l'addestramento della rete è durato circa 3 minuti. Ricordiamo che la stessa fase su un normale processore ha impiegato 5 minuti. La differenza non è significativa, poiché la nostra rete non è così grande. Quando si utilizzano grandi set di dati per l'addestramento, la differenza tra la velocità di lavoro della GPU e quella del processore tradizionale aumenterà.

Sembra sia tutto. Cosa siamo riusciti a fare:

  • Abbiamo esaminato cosa sia una GPU e scelto un server su cui è installata;
  • Abbiamo configurato l'ambiente software per creare una rete neurale;
  • Abbiamo creato una rete neurale per il riconoscimento delle immagini e l'abbiamo addestrata;
  • Abbiamo riaddestrato la rete utilizzando la GPU e abbiamo ottenuto un incremento nella velocità.

Sarò lieto di rispondere alle domande nei commenti.

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster