Vaša prva neuronska mreža na grafičkoj procesorskoj jedinici (GPU). Vodič za početnike

Vaša prva neuronska mreža na grafičkoj procesorskoj jedinici (GPU). Vodič za početnike
U ovom ću vam članku reći kako postaviti okruženje za strojno učenje u 30 minuta, stvoriti neuronsku mrežu za prepoznavanje slike, a zatim pokrenuti istu mrežu na grafičkom procesoru (GPU).

Prvo, definirajmo što je neuronska mreža.

U našem slučaju, to je matematički model, kao i njegova softverska ili hardverska izvedba, izgrađena na principu organizacije i funkcioniranja bioloških neuronskih mreža - mreža živčanih stanica živog organizma. Ovaj koncept nastao je tijekom proučavanja procesa koji se odvijaju u mozgu i pokušaja modeliranja tih procesa.

Neuronske mreže nisu programirane u uobičajenom smislu te riječi, one se treniraju. Sposobnost učenja jedna je od glavnih prednosti neuronskih mreža u odnosu na tradicionalne algoritme. Tehnički, učenje se sastoji od pronalaženja koeficijenata veza između neurona. Tijekom procesa obuke, neuronska mreža je u stanju identificirati složene ovisnosti između ulaznih i izlaznih podataka, kao i izvesti generalizaciju.

Sa stajališta strojnog učenja, neuronska mreža je poseban slučaj metoda prepoznavanja uzoraka, diskriminativne analize, metoda klasteriranja i drugih metoda.

Оборудование

Prvo, pogledajmo opremu. Trebamo poslužitelj s instaliranim operativnim sustavom Linux. Oprema potrebna za upravljanje sustavima strojnog učenja prilično je moćna i, kao rezultat toga, skupa. Za one koji nemaju dobar stroj pri ruci, preporučujem da obratite pozornost na ponude pružatelja usluga oblaka. Traženi server možete brzo unajmiti i platiti samo vrijeme korištenja.

U projektima u kojima je potrebno izraditi neuronske mreže koristim poslužitelje jednog od ruskih pružatelja usluga oblaka. Tvrtka nudi poslužitelje u oblaku za najam posebno za strojno učenje sa snažnim Tesla V100 grafičkim procesorima (GPU) tvrtke NVIDIA. Ukratko: korištenje poslužitelja s GPU-om može biti desetke puta učinkovitije (brže) u usporedbi s poslužiteljem slične cijene koji za izračune koristi CPU (dobro poznata središnja procesorska jedinica). To se postiže zahvaljujući značajkama GPU arhitekture, koja se brže nosi s izračunima.

Za implementaciju dolje opisanih primjera kupili smo sljedeći poslužitelj na nekoliko dana:

  • SSD disk 150 GB
  • RAM 32 GB
  • Tesla V100 16 Gb procesor sa 4 jezgre

Instalirali smo Ubuntu 18.04 na našem računalu.

Postavljanje okoline

Sada idemo instalirati sve što je potrebno za rad na poslužitelju. Budući da je naš članak prvenstveno za početnike, govorit ću o nekim točkama koje će im biti korisne.

Velik dio posla pri postavljanju okruženja obavlja se putem naredbenog retka. Većina korisnika koristi Windows kao radni OS. Standardna konzola u ovom OS-u ostavlja mnogo želja. Stoga ćemo koristiti prikladan alat Cmder/. Preuzmite mini verziju i pokrenite Cmder.exe. Zatim se morate spojiti na poslužitelj putem SSH-a:

ssh root@server-ip-or-hostname

Umjesto server-ip-or-hostname, navedite IP adresu ili DNS naziv vašeg poslužitelja. Zatim unesite lozinku i ako je veza uspješna, trebali bismo primiti poruku sličnu ovoj.

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

Glavni jezik za razvoj ML modela je Python. A najpopularnija platforma za njegovu upotrebu na Linuxu je anakonda.

Instalirajmo ga na naš poslužitelj.

Počinjemo s ažuriranjem lokalnog upravitelja paketa:

sudo apt-get update

Instalirajte curl (uslužni program naredbenog retka):

sudo apt-get install curl

Preuzmite najnoviju verziju Anaconda Distribution:

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

Započnimo instalaciju:

bash Anaconda3-2019.10-Linux-x86_64.sh

Tijekom postupka instalacije od vas će se tražiti da potvrdite licencni ugovor. Nakon uspješne instalacije trebali biste vidjeti ovo:

Thank you for installing Anaconda3!

Sada su stvoreni mnogi okviri za razvoj ML modela; radimo s najpopularnijima: PyTorch и Tenzor protok.

Korištenje okvira omogućuje vam povećanje brzine razvoja i korištenje gotovih alata za standardne zadatke.

U ovom primjeru radit ćemo s PyTorchom. Instalirajmo ga:

conda install pytorch torchvision cudatoolkit=10.1 -c pytorch

Sada moramo pokrenuti Jupyter Notebook, popularan razvojni alat za stručnjake za ML. Omogućuje vam da napišete kod i odmah vidite rezultate njegovog izvršenja. Jupyter Notebook uključen je u Anacondu i već je instaliran na našem poslužitelju. Morate se spojiti na njega s našeg desktop sustava.

Da bismo to učinili, prvo ćemo pokrenuti Jupyter na poslužitelju navodeći port 8080:

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

Zatim, otvaranjem druge kartice u našoj Cmder konzoli (gornji izbornik - dijaloški okvir Nova konzola) spojit ćemo se preko porta 8080 na poslužitelj putem SSH-a:

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

Kada unesemo prvu naredbu, ponudit će nam se linkovi za otvaranje Jupytera u našem pregledniku:

To access the notebook, open this file in a browser:
        file:///root/.local/share/jupyter/runtime/nbserver-18788-open.html
    Or copy and paste one of these URLs:
        http://localhost:8080/?token=cca0bd0b30857821194b9018a5394a4ed2322236f116d311
     or http://127.0.0.1:8080/?token=cca0bd0b30857821194b9018a5394a4ed2322236f116d311

Iskoristimo vezu za localhost:8080. Kopirajte cijeli put i zalijepite ga u adresnu traku lokalnog preglednika vašeg računala. Otvorit će se Jupyter Notebook.

Kreirajmo novu bilježnicu: Novo - Bilježnica - Python 3.

Provjerimo ispravan rad svih komponenti koje smo instalirali. Unesite primjer PyTorch koda u Jupyter i pokrenite izvršenje (gumb Pokreni):

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

Rezultat bi trebao biti nešto poput ovoga:

Vaša prva neuronska mreža na grafičkoj procesorskoj jedinici (GPU). Vodič za početnike

Ako imate sličan rezultat, onda smo sve ispravno konfigurirali i možemo početi razvijati neuronsku mrežu!

Stvaranje neuronske mreže

Napravit ćemo neuronsku mrežu za prepoznavanje slike. Uzmimo ovo kao osnovu rukovodstvo.

Koristit ćemo javno dostupan skup podataka CIFAR10 za obuku mreže. Ima klase: "avion", "auto", "ptica", "mačka", "jelen", "pas", "žaba", "konj", "brod", "kamion". Slike u CIFAR10 su 3x32x32, odnosno 3-kanalne slike u boji od 32x32 piksela.

Vaša prva neuronska mreža na grafičkoj procesorskoj jedinici (GPU). Vodič za početnike
Za rad ćemo koristiti paket koji je kreirao PyTorch za rad sa slikama - torchvision.

Napravit ćemo sljedeće korake redom:

  • Učitavanje i normaliziranje skupova podataka za obuku i testiranje
  • Definicija neuronske mreže
  • Mrežna obuka na podacima o obuci
  • Mrežno testiranje na testnim podacima
  • Ponovimo obuku i testiranje koristeći GPU

Izvršit ćemo sav donji kod u Jupyter Notebooku.

Učitavanje i normaliziranje CIFAR10

Kopirajte i pokrenite sljedeći kod u Jupyteru:


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 = ('plane', 'car', 'bird', 'cat',
           'deer', 'dog', 'frog', 'horse', 'ship', 'truck')

Odgovor bi trebao biti:

Downloading https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz to ./data/cifar-10-python.tar.gz
Extracting ./data/cifar-10-python.tar.gz to ./data
Files already downloaded and verified

Prikažimo nekoliko slika treninga za testiranje:


import matplotlib.pyplot as plt
import numpy as np

# functions to show an image

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

# get some random training images
dataiter = iter(trainloader)
images, labels = dataiter.next()

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

Vaša prva neuronska mreža na grafičkoj procesorskoj jedinici (GPU). Vodič za početnike

Definicija neuronske mreže

Razmotrimo prvo kako funkcionira neuronska mreža za prepoznavanje slika. Ovo je jednostavna mreža od točke do točke. Uzima ulazne podatke, prolazi ih kroz nekoliko slojeva jedan po jedan, a zatim konačno proizvodi izlazne podatke.

Vaša prva neuronska mreža na grafičkoj procesorskoj jedinici (GPU). Vodič za početnike

Kreirajmo sličnu mrežu u našem okruženju:


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

Također definiramo funkciju gubitka i optimizator


import torch.optim as optim

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

Mrežna obuka na podacima o obuci

Počnimo trenirati našu neuronsku mrežu. Imajte na umu da ćete nakon pokretanja ovog koda morati pričekati neko vrijeme dok se posao ne završi. Trebalo mi je 5 minuta. Potrebno je vrijeme za treniranje mreže.

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

    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        # get the inputs; data is a list of [inputs, labels]
        inputs, labels = data

        # zero the parameter gradients
        optimizer.zero_grad()

        # forward + backward + optimize
        outputs = net(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        # print statistics
        running_loss += loss.item()
        if i % 2000 == 1999:    # print every 2000 mini-batches
            print('[%d, %5d] loss: %.3f' %
                  (epoch + 1, i + 1, running_loss / 2000))
            running_loss = 0.0

print('Finished Training')

Dobivamo sljedeći rezultat:

Vaša prva neuronska mreža na grafičkoj procesorskoj jedinici (GPU). Vodič za početnike

Spremamo naš trenirani model:

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

Mrežno testiranje na testnim podacima

Istrenirali smo mrežu pomoću skupa podataka za obuku. Ali moramo provjeriti je li mreža uopće nešto naučila.

To ćemo testirati predviđanjem oznake klase koju neuronska mreža isporučuje i testiranjem da vidimo je li točna. Ako je predviđanje točno, dodajemo uzorak na popis točnih predviđanja.
Pokažimo sliku iz testnog skupa:

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

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

Vaša prva neuronska mreža na grafičkoj procesorskoj jedinici (GPU). Vodič za početnike

Sada zamolimo neuronsku mrežu da nam kaže što je na ovim slikama:


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

outputs = net(images)

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

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

Vaša prva neuronska mreža na grafičkoj procesorskoj jedinici (GPU). Vodič za početnike

Rezultati se čine prilično dobrima: mreža je točno identificirala tri od četiri slike.

Pogledajmo kako se mreža ponaša u cijelom skupu podataka.


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

Vaša prva neuronska mreža na grafičkoj procesorskoj jedinici (GPU). Vodič za početnike

Čini se da mreža nešto zna i radi. Kad bi nasumce odredio klase, točnost bi bila 10%.

Sada da vidimo koje klase mreža bolje identificira:

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

Vaša prva neuronska mreža na grafičkoj procesorskoj jedinici (GPU). Vodič za početnike

Čini se da je mreža najbolja u identificiranju automobila i brodova: 71% točnosti.

Dakle, mreža radi. Pokušajmo sada prenijeti njegov rad na grafički procesor (GPU) i vidjeti što se mijenja.

Obuka neuronske mreže na GPU-u

Prvo ću ukratko objasniti što je CUDA. CUDA (Compute Unified Device Architecture) je paralelna računalna platforma koju je razvila NVIDIA za općenito računalstvo na grafičkim procesorskim jedinicama (GPU). Uz CUDA programeri mogu dramatično ubrzati računalne aplikacije iskorištavanjem snage GPU-a. Ova platforma je već instalirana na našem serveru koji smo kupili.

Najprije definirajmo naš GPU kao prvi vidljivi cuda uređaj.

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

Vaša prva neuronska mreža na grafičkoj procesorskoj jedinici (GPU). Vodič za početnike

Slanje mreže na GPU:

net.to(device)

Također ćemo morati poslati ulaze i ciljeve u svakom koraku GPU-u:

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

Idemo ponovno uvježbati mrežu na GPU-u:

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):
        # get the inputs; data is a list of [inputs, labels]
    inputs, labels = data[0].to(device), data[1].to(device)

        # zero the parameter gradients
        optimizer.zero_grad()

        # forward + backward + optimize
        outputs = net(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        # print statistics
        running_loss += loss.item()
        if i % 2000 == 1999:    # print every 2000 mini-batches
            print('[%d, %5d] loss: %.3f' %
                  (epoch + 1, i + 1, running_loss / 2000))
            running_loss = 0.0

print('Finished Training')

Ovoga puta mrežni trening je trajao oko 3 minute. Podsjetimo, ista faza na konvencionalnom procesoru trajala je 5 minuta. Razlika nije značajna, to se događa jer naša mreža nije tako velika. Kada koristite velike nizove za obuku, razlika između brzine GPU-a i tradicionalnog procesora će se povećati.

Čini se da je to sve. Što smo uspjeli napraviti:

  • Pogledali smo što je GPU i odabrali poslužitelj na kojem je instaliran;
  • Postavili smo softversko okruženje za stvaranje neuronske mreže;
  • Napravili smo neuronsku mrežu za prepoznavanje slika i istrenirali je;
  • Ponovili smo mrežnu obuku pomoću GPU-a i dobili povećanje brzine.

Rado ću odgovoriti na pitanja u komentarima.

Izvor: www.habr.com

Dodajte komentar