Teie esimene närvivõrk graafika protsessoril (GPU). Algajate juhend

Teie esimene närvivõrk graafika protsessoril (GPU). Algajate juhend
Selles artiklis räägin, kuidas 30 minutiga seadistada masinõppe keskkond, luua pildituvastusneuraalvõrk ja käivitada see seejärel graafikaprotessoril (GPU).

Alustame määratlemisest, mis on neuraalvõrk.

Meie juhul on see matemaatiline mudel, samuti selle programmiline või riistvaraline kehastus, mis on loodud bioloogiliste neuraalvõrkude — elusorganismi närvirakkude — organisatsiooni ja toimimise põhimõtete alusel. See mõiste tekkis aju protsesside uurimise käigus ja nende protsesside modelleerimise katsete käigus.

Neuraalvõrke ei programmeerita traditsioonilises tähenduses, vaid need õpivad. Õppimisvõime on üks peamisi eelistest, mille neuraalvõrgud saavad traditsiooniliste algoritmide ees. Tehniliselt tähendab õppimine sidemete koefitsientide leidmist neuronite vahel. Õppimise käigus suudab neuraalvõrk tuvastada keerukaid seoseid sisendandmete ja väljundite vahel ning teha üldistusi.

Masinõppe seisukohalt on närvivõrk eriline juhtum mustrite äratundmise meetoditest, diskriminaanalüüsist, klasterdamismeetoditest ja muudest meetoditest.

Seadmed

Alustame riistvarast. Meile on vajalik server, millel on installitud Linuxi operatsioonisüsteem. Masinõppesüsteemide tööks on vajalik piisavalt võimas ja seega kallis riistvara. Kui teil pole head masinat käepärast, soovitan pöörata tähelepanu pilveteenuste pakkujate pakkumistele. Vajalikku serverit on võimalik kiiresti rentida ja maksta ainult kasutusaja eest.

Projektides, kus on vajalik tehisnärvivõrkude loomine, kasutan ma ühte Venemaa pilveteenuse pakkujat. Ettevõte pakub masinõppimiseks mõeldud pilveservereid, millel on võimsad NVIDIA Tesla V100 graafikaprotsessorid (GPU). Ütlemiseks lühidalt: GPU-ga serveri kasutamine võib olla korduvalt tõhusam (kiirem) võrreldes sama hinnaklassi serveriga, kus arvutamiseks kasutatakse CPU-d (kõigile hästi tuntud keskprotsessor). See saavutatakse GPU arhitektuuri omaduste tõttu, mis suudab arvutuste tegemisega kiiremini hakkama saada.

Edasi toimetamiseks soetasin me mitme päevaks sellise serveri:

  • SSD ketas 150 GB
  • RAM 32 GB
  • Tesla V100 16 Gb protsessor 4 tuumaga

Masinale on installitud Ubuntu 18.04.

Paigaldame keskkonna

Nüüd installime serverisse kõik vajaliku, et tööprotsess sujuks. Kuna meie artikkel on eelkõige algajatele, räägin ma selles mõningatest aspektidest, mis neile kasulikud on.

Suures osas teeb keskkonna seadistamisel tööd käsurea kaudu. Enamik kasutajatest kasutab tööks Windowsi operatsioonisüsteemi. Selle OS-i standardne konsool jätab soovida. Seetõttu kasutame mugavat tööriista Cmder/. Laadige alla mini versioon ja käitage Cmder.exe. Järgmisena tuleb ühenduda serveriga SSH-protokolli kaudu:

ssh root@server-ip-or-hostname

Kohandage server-ip-or-hostname IP-aadressile või teie serveri DNS-nimega. Sisestage seejärel parool ja kui ühendamine on õnnestunud, peaksime saama ligikaudu sellise teadete.

Tere tulemast Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-74-generic x86_64)

ML mudelite arendamise peamine keel on Python. Ja kõige populaarsem platvorm selle kasutamiseks Linuxis on Anaconda.

Paigaldame selle oma serverisse.

Alustame kohaliku pakihalduri värskendamisega:

sudo apt-get update

Installime curl (käsklustööriist):

sudo apt-get install curl

Laadige alla viimane Anaconda Distributioni versioon:

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

Alustame installimist:

bash Anaconda3-2019.10-Linux-x86_64.sh

Tarkvara installimise käigus tuleb kinnitada litsentsileping. Kui installimine õnnestub, peaksite nägema järgmist:

Aitäh, et installisite Anaconda3!

Masinõppe mudelite arendamiseks on loodud palju raamistikku, me töötame kõige populaarsematega: PyTorch ja Tensorflow.

Raamistiku kasutamine võimaldab kiirendada arendust ja kasutada juba valmis tööriistu standardsete ülesannete jaoks.

Selles näites töötame PyTorchiga. Installime selle:

conda install pytorch torchvision cudatoolkit=10.1 -c pytorch

Nüüd peame käivitama Jupyter Notebooki — populaarse masinõppe spetsialistide arendusvahendi. See võimaldab kirjutada koodi ja kohe näha tulemusi. Jupyter Notebook kuulub Anaconda komplekti ja on juba meie serveris installitud. Peame selle ära ühendama meie tööstussüsteemist.

Selleks käivitame esmalt Jupyter serveris, määratledes port 8080:

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

Seejärel avame meie konsolis Cmder veel ühe vahekaart (ülemine menüü — Uus konsoli dialoog) ja ühendame SSH kaudu serveriga port 8080:

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

Esimese käsu sisestamisel pakutakse meile linke Jupyter avamiseks meie brauseris:

Märkmiku avamiseks avage see fail brauseris:
        file:///root/.local/share/jupyter/runtime/nbserver-18788-open.html
    Või kopeerige ja kleepige mõni neist URL-idest:
        http://localhost:8080/?token=cca0bd0b30857821194b9018a5394a4ed2322236f116d311
     või http://127.0.0.1:8080/?token=cca0bd0b30857821194b9018a5394a4ed2322236f116d311

Kasutame localhost:8080 linki. Kopeerige täielik tee ja kleepige see kohalikku brauseri aadressiribale. Avaneb Jupyter Notebook.

Loome uue märkmiku: New — Notebook — Python 3.

Kontrollime, et kõik installitud komponendid töötavad õigesti. Sisestame Jupyterisse PyTorchi näidiskoode ja käivitame selle (nupp Run):

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

Tulemus peaks olema umbes selline:

Teie esimene närvivõrk graafika protsessoril (GPU). Algajate juhend

Kui teil on sarnane tulemus — siis oleme kõik õigesti seadistanud ja saame alustada tehisnärvivõrgu arendamist!

Loome tehisnärvivõrgu

Loome tehisnärvivõrgu piltide tuvastamiseks. Võtame aluseks selle juhend.

Meie võrgu treenimiseks kasutame avalikke CIFAR10 andmekogusid. Sellel on järgmised klassid: "lennuk", "auto", "lind", "kass", "hirv", "koer", "siga", "hobune", "laev", "veok". CIFAR10 pildid on suurusega 3x32x32, mis tähendab 3-kanalilisi värvipilte suurusega 32×32 pikslit.

Teie esimene närvivõrk graafika protsessoril (GPU). Algajate juhend
Tööks kasutame loodud PyTorch paketti piltidega töötamiseks — torchvision.

Teeme järgmised sammud järjestikku:

  • Treening- ja testandmete komplektide laadimine ja normaliseerimine
  • Neuraalvõrgu määratlemine
  • Võrgu treenimine treeningandmetel
  • Võrgu testimine testandmetel
  • Korrake treeningut ja testimist GPU abil

Kogu allpool toodud koodi täidame Jupyter Notebookis.

CIFAR10 laadimine ja normaliseerimine

Kopeerige ja täitke Jupyteris järgmine kood:


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 = ('lennuk', 'auto', 'lind', 'kass',
           'hirv', 'koer', 'konn', 'hobune', 'laev', 'veok')

Vastus peab olema järgmine:

Laadimine https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz faili ./data/cifar-10-python.tar.gz
Eraldamine ./data/cifar-10-python.tar.gz faili ./data
Failid on juba allalaaditud ja kinnitatud

Kuvame mõned treeningpildid kontrollimiseks:


import matplotlib.pyplot as plt
import numpy as np

# funktsioon pildi kuvamiseks

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

# hankime mõned juhuslikud treeningpildid
dataiter = iter(trainloader)
images, labels = dataiter.next()

# näitame pilte
imshow(torchvision.utils.make_grid(images))
# prindime sildid
print(' '.join('%5s' % classes[labels[j]] for j in range(4)))

Teie esimene närvivõrk graafika protsessoril (GPU). Algajate juhend

Neuraalvõrgu määratlemine

Alustame sellest, kuidas töötab piltide tuvastamise närvivõrk. See on lihtne otseühendusega võrk. See võtab sisendi, edastab selle läbi mitme kihi ükshaaval ja lõpuks annab väljundi.

Teie esimene närvivõrk graafika protsessoril (GPU). Algajate juhend

Loodame sarnase võrgu meie keskkonnas:


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

Määratleme samuti kadufunktsiooni ja optimeerija


import torch.optim as optim

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

Võrgu treenimine treeningandmetel

Alustame meie närvivõrgu koolitust. Tahan rõhutada, et pärast selle koodi käivitamist tuleb oodata mõni aeg, kuni töö lõpeb. Minul kestis see 5 minutit. Võrgu koolitamiseks on vajalik aeg.

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

Saame sellise tulemuse:

Teie esimene närvivõrk graafika protsessoril (GPU). Algajate juhend

Salvestame meie koolitatud mudeli:

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

Võrgu testimine testandmetel

Me oleme koolitanud võrku kasutades koolitusandmete komplekti. Kuid peame kontrollima, kas võrk on üldse millegi õppinud.

Kontrollime seda, ennustades klassi märki, mille neuronivõrk toodab, ja kontrollides seda tõe suhtes. Kui ennustus on õige, lisame näidise õigete ennustuste loendisse.
Näidake testkomplekti pilti:

dataiter = iter(testloader)
pildid, sildid = dataiter.next()

# prindi pildid
imshow(torchvision.utils.make_grid(pildid))
print('Tõeline: ', ' '.join('%5s' % classes[sildid[j]] for j in range(4)))

Teie esimene närvivõrk graafika protsessoril (GPU). Algajate juhend

Nüüd palume neuronivõrgul öelda, mis on nende piltide peal:


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

outputs = net(images)

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

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

Teie esimene närvivõrk graafika protsessoril (GPU). Algajate juhend

Tulemused näivad olevat üsna head: võrk tuvastas õigesti kolm neljast pildist.

Vaadakem, kuidas võrk töötab kogu andmestikus.


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('Võrgu täpsus 10000 testpildi peal: %d %%' % (
    100 * correct / total))

Teie esimene närvivõrk graafika protsessoril (GPU). Algajate juhend

Paistab, et võrk teab midagi ja töötab. Kui ta klassifitseeriks juhuslikult, oleks täpsus 10%.

Nüüd vaatame, milliseid klasse võrk paremini määratleb:

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

Teie esimene närvivõrk graafika protsessoril (GPU). Algajate juhend

Tundub, et võrk määratleb kõige paremini autod ja laevad: 71% täpsust.

Nii et võrgustik töötab. Proovime nüüd selle töö üle viia graafikaprotsessorile (GPU) ja vaatame, mis muutub.

Neuraalvõrgu treenimine GPU-l

Esiteks selgitan lühidalt, mis on CUDA. CUDA (Compute Unified Device Architecture) on NVIDIA välja töötatud paralleelsete arvutuste platvorm, mis on mõeldud üldiseks arvutamiseks graafikaprotsessoritel (GPU). CUDA kaudu saavad arendajad oluliselt kiirendada arvutuslikke rakendusi, kasutades graafikaprotsessorite võimalusi. Meie ostetud serveris on see platvorm juba installitud.

Määratlegem esmalt meie GPU kui esmane nähtav cuda seade.

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
# Eeldades, et oleme CUDA masinas, peaks see printima CUDA seadme:
print(device)

Teie esimene närvivõrk graafika protsessoril (GPU). Algajate juhend

Saadame võrgu GPU-le:

net.to(device)

Samuti peame igal sammul saatma sisendid ja sihid GPU-le:

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

Käivitame võrgu edasise treenimise juba GPU-l:

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

Sel korral kestis võrgu koolitus umbes 3 minutit. Tuletame meelde, et sama etapp tavalise protsessoriga kestis 5 minutit. Erinevus ei ole märkimisväärne, kuna meie võrk ei ole nii suur. Suuremate koolitusandmete kasutamisel suureneb erinevus GPU ja traditsioonilise protsessori kiirusel.

Tundub, et selleks kõik. Mida me suudame saavutada:

  • Me uurisime, mis on GPU ja valisime serveri, kuhu see on paigaldatud;
  • Me seadistasime tarkvarakeskkonna tehisnärvivõrgu loomiseks;
  • Me lõime tehisnärvivõrgu piltide tuvastamiseks ja koolitasime selle;
  • Korrigeerisime võrgu koolitust GPU-de kasutamisega ja saavutasime kiirusetõusu.

Olen rõõmuga valmis vastama küsimustele kommentaarides.

Allikas: habr.com

Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster