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 članku ću vam reći kako postaviti okruženje za strojno učenje za 30 minuta, kreirati neuronsku mrežu za prepoznavanje slika, a zatim pokrenuti istu mrežu na grafičkom procesoru (GPU).

Prvo, hajde da definišemo šta je neuronska mreža.

U našem slučaju radi se o matematičkom modelu, kao io njegovom softverskom ili hardverskom oličenju, izgrađenom na principu organizacije i funkcioniranja bioloških neuronskih mreža - mreža nervnih ćelija živog organizma. Ovaj koncept je nastao tokom proučavanja procesa koji se odvijaju u mozgu i pokušaja modeliranja ovih procesa.

Neuronske mreže nisu programirane u uobičajenom smislu te riječi, one su obučene. 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. Tokom procesa obuke, neuronska mreža je u stanju da identifikuje složene zavisnosti između ulaznih i izlaznih podataka, kao i da izvrši generalizaciju.

Sa stanovišta mašinskog učenja, neuronska mreža je poseban slučaj metoda prepoznavanja obrazaca, diskriminantne analize, metoda grupisanja i drugih metoda.

Oprema

Prvo, pogledajmo opremu. Potreban nam je server sa instaliranim Linux operativnim sistemom. Oprema potrebna za rad sistema mašinskog učenja je prilično moćna i, kao rezultat, skupa. Za one koji nemaju dobru mašinu pri ruci, preporučujem da obrate pažnju na ponude cloud provajdera. Potreban server možete iznajmiti brzo i platiti samo vrijeme korištenja.

U projektima gdje je potrebno kreirati neuronske mreže koristim servere jednog od ruskih provajdera oblaka. Kompanija nudi cloud servere za iznajmljivanje posebno za mašinsko učenje sa moćnim Tesla V100 grafičkim procesorima (GPU) iz NVIDIA-e. Ukratko: korištenje servera sa GPU-om može biti desetine puta efikasnije (brže) u poređenju sa serverom slične cijene koji koristi CPU (dobro poznatu centralnu procesorsku jedinicu) za proračune. To se postiže zahvaljujući karakteristikama GPU arhitekture, koja se brže nosi sa proračunima.

Da bismo implementirali dolje opisane primjere, kupili smo sljedeći server na nekoliko dana:

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

Instalirali smo Ubuntu 18.04 na našu mašinu.

Postavljanje okruženja

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

Veliki dio posla prilikom postavljanja okruženja obavlja se preko komandne linije. Većina korisnika koristi Windows kao operativni OS. Standardna konzola u ovom OS-u ostavlja mnogo da se poželi. Stoga ćemo koristiti pogodan alat Cmder/. Preuzmite mini verziju i pokrenite Cmder.exe. Zatim se trebate povezati na server preko SSH:

ssh root@server-ip-or-hostname

Umjesto server-ip-or-hostname, navedite IP adresu ili DNS ime vašeg servera. Zatim unesite lozinku i ako je veza uspješna, trebali bismo dobiti 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.

Hajde da ga instaliramo na naš server.

Počinjemo ažuriranjem lokalnog upravitelja paketa:

sudo apt-get update

Instalirajte curl (uslužni program komandne linije):

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

Tokom procesa instalacije, od vas će se tražiti da potvrdite ugovor o licenci. Nakon uspješne instalacije trebali biste vidjeti ovo:

Thank you for installing Anaconda3!

Sada su kreirani mnogi okviri za razvoj ML modela; radimo sa najpopularnijim: PyTorch и tenzorski tok.

Korištenje okvira vam omogućava da povećate brzinu razvoja i koristite gotove alate za standardne zadatke.

U ovom primjeru radit ćemo sa PyTorch-om. Hajde da ga instaliramo:

conda install pytorch torchvision cudatoolkit=10.1 -c pytorch

Sada moramo pokrenuti Jupyter Notebook, popularan razvojni alat za stručnjake za ML. Omogućava vam da napišete kod i odmah vidite rezultate njegovog izvršenja. Jupyter Notebook je uključen uz Anaconda i već je instaliran na našem serveru. Morate se povezati na njega sa našeg desktop sistema.

Da bismo to uradili, prvo ćemo pokrenuti Jupyter na serveru koji navodi port 8080:

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

Zatim, otvarajući još jednu karticu u našoj Cmder konzoli (gornji meni - dijalog Nova konzola) spojit ćemo se preko porta 8080 na server preko SSH:

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

Kada unesemo prvu komandu, biće nam ponuđene veze za otvaranje Jupytera u našem pretraživaču:

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

Koristimo vezu za localhost:8080. Kopirajte punu putanju i zalijepite je u adresnu traku lokalnog pretraživača vašeg računara. Jupyter Notebook će se otvoriti.

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

Provjerimo ispravan rad svih komponenti koje smo instalirali. Unesimo primjer PyTorch koda u Jupyter i pokrenimo izvršenje (dugme Run):

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

Rezultat bi trebao biti otprilike ovako:

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!

Kreiranje neuronske mreže

Napravićemo neuronsku mrežu za prepoznavanje slika. Uzmimo ovo kao osnovu vodič.

Koristit ćemo javno dostupni skup podataka CIFAR10 za obuku mreže. Ima klase: "avion", "automobil", "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.

Uradićemo sledeće korake po redosledu:

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

Izvršit ćemo sav donji kod u Jupyter Notebook-u.

Učitavanje i normalizacija 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 tačke do tačke. Uzima ulazne podatke, prenosi 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

Hajde da napravimo 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 o podacima o obuci

Počnimo da treniramo našu neuronsku mrežu. Imajte na umu da ćete nakon što pokrenete ovaj kod morati pričekati neko vrijeme dok se posao ne završi. Trebalo mi je 5 minuta. Potrebno je vrijeme za obuku 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')

Dobijamo sljedeći rezultat:

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

Mi čuvamo naš obučeni model:

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

Mrežno testiranje na testnim podacima

Trenirali smo mrežu koristeći skup podataka o obuci. Ali moramo provjeriti da li je mreža uopće nešto naučila.

Mi ćemo to testirati predviđanjem oznake klase koju neuronska mreža daje i testirati je da vidimo da li je istinita. Ako je predviđanje tačno, uzorak dodajemo na listu tač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 šta 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 dobrim: mreža je tačno identifikovala 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

Izgleda da mreža nešto zna i radi. Kada bi nasumično odredio klase, tač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 identifikaciji automobila i brodova: 71% tač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 šta je CUDA. CUDA (Compute Unified Device Architecture) je platforma za paralelno računarstvo koju je razvila NVIDIA za opšte računarstvo na grafičkim procesorskim jedinicama (GPU). Uz CUDA, programeri mogu dramatično ubrzati računarske aplikacije koristeći snagu GPU-a. Ova platforma je već instalirana na našem serveru koji smo kupili.

Hajde da prvo definišemo 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 ulazne podatke i ciljeve na svakom koraku GPU-u:

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

Hajde da ponovo obučimo mrežu na 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):
        # 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')

Ovaj put mrežni trening je trajao oko 3 minute. Podsjetimo da je ista faza na konvencionalnom procesoru trajala 5 minuta. Razlika nije bitna, to se dešava 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. Šta smo uspeli da uradimo:

  • Pogledali smo šta je GPU i odabrali server na kojem je instaliran;
  • Postavili smo softversko okruženje za kreiranje neuronske mreže;
  • Napravili smo neuronsku mrežu za prepoznavanje slika i obučili je;
  • Ponovili smo mrežni trening koristeći GPU i dobili smo povećanje brzine.

Rado ću odgovoriti na pitanja u komentarima.

izvor: www.habr.com

Dodajte komentar