Jūsų pirmasis neuroninis tinklas grafikos apdorojimo bloke (GPU). Pradedančiųjų vadovas

Jūsų pirmasis neuroninis tinklas grafikos apdorojimo bloke (GPU). Pradedančiųjų vadovas
Šiame straipsnyje papasakosiu, kaip per 30 minučių nustatyti mašininio mokymosi aplinką, sukurti vaizdų atpažinimo neuroninį tinklą ir paleisti tą patį tinklą grafikos procesoriuje (GPU).

Pirma, apibrėžkime, kas yra neuroninis tinklas.

Mūsų atveju tai yra matematinis modelis, taip pat jo programinė ar techninė įranga, sukurta remiantis biologinių neuroninių tinklų - gyvo organizmo nervinių ląstelių tinklų - organizavimo ir veikimo principu. Ši koncepcija atsirado tiriant smegenyse vykstančius procesus ir bandant juos modeliuoti.

Neuroniniai tinklai nėra programuojami įprasta to žodžio prasme, jie yra treniruojami. Gebėjimas mokytis yra vienas iš pagrindinių neuroninių tinklų pranašumų, palyginti su tradiciniais algoritmais. Techniškai mokymasis susideda iš jungčių tarp neuronų koeficientų nustatymo. Mokymo proceso metu neuroninis tinklas gali nustatyti sudėtingas įvesties ir išvesties duomenų priklausomybes bei atlikti apibendrinimą.

Mašininio mokymosi požiūriu neuroninis tinklas yra ypatingas modelių atpažinimo metodų, diskriminacinės analizės, klasterizacijos metodų ir kitų metodų atvejis.

įranga

Pirmiausia pažvelkime į įrangą. Mums reikia serverio su įdiegta Linux operacine sistema. Mašininio mokymosi sistemoms valdyti reikalinga įranga yra gana galinga ir dėl to brangi. Neturintiems po ranka geros mašinos rekomenduoju atkreipti dėmesį į debesų tiekėjų pasiūlymus. Reikiamą serverį išsinuomoti galite greitai ir mokėti tik už naudojimosi laiką.

Projektuose, kur reikia kurti neuroninius tinklus, naudoju vieno iš Rusijos debesų tiekėjų serverius. Bendrovė siūlo išsinuomoti debesies serverius specialiai mašininiam mokymuisi su galingais Tesla V100 grafikos procesoriais (GPU) iš NVIDIA. Trumpai tariant: serverio su GPU naudojimas gali būti dešimtis kartų efektyvesnis (greitesnis), palyginti su panašios kainos serveriu, kuris skaičiavimams naudoja procesorių (gerai žinomą centrinį procesorių). Tai pasiekiama dėl GPU architektūros ypatybių, kurios greičiau susidoroja su skaičiavimais.

Norėdami įgyvendinti toliau aprašytus pavyzdžius, kelioms dienoms įsigijome šį serverį:

  • SSD diskas 150 GB
  • RAM 32 GB
  • Tesla V100 16 Gb procesorius su 4 branduoliais

Įrenginyje įdiegėme Ubuntu 18.04.

Aplinkos sutvarkymas

Dabar įdiekime serveryje viską, ko reikia darbui. Kadangi mūsų straipsnis visų pirma skirtas pradedantiesiems, pakalbėsiu apie kai kuriuos dalykus, kurie jiems bus naudingi.

Daug darbo nustatant aplinką atliekama per komandinę eilutę. Dauguma vartotojų naudoja „Windows“ kaip savo veikiančią OS. Standartinė šios OS konsolė palieka daug norimų rezultatų. Todėl naudosime patogų įrankį Cmder/. Atsisiųskite mini versiją ir paleiskite Cmder.exe. Tada turite prisijungti prie serverio per SSH:

ssh root@server-ip-or-hostname

Vietoj serverio IP arba pagrindinio kompiuterio pavadinimo nurodykite savo serverio IP adresą arba DNS pavadinimą. Tada įveskite slaptažodį ir, jei ryšys bus sėkmingas, turėtume gauti panašų pranešimą.

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

Pagrindinė kalba kuriant ML modelius yra Python. Ir populiariausia platforma, skirta naudoti Linux sistemoje Anakonda.

Įdiegkime jį savo serveryje.

Pradedame nuo vietinės paketų tvarkyklės atnaujinimo:

sudo apt-get update

Įdiekite curl (komandinės eilutės įrankis):

sudo apt-get install curl

Atsisiųskite naujausią Anaconda Distribution versiją:

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

Pradėkime diegimą:

bash Anaconda3-2019.10-Linux-x86_64.sh

Diegimo proceso metu jūsų bus paprašyta patvirtinti licencijos sutartį. Sėkmingai įdiegę turėtumėte pamatyti tai:

Thank you for installing Anaconda3!

ML modelių kūrimui dabar sukurta daug karkasų, dirbame su populiariausiais: „PyTorch“ и tenzorinis srautas.

Naudodami sistemą galite padidinti kūrimo greitį ir naudoti paruoštus įrankius standartinėms užduotims atlikti.

Šiame pavyzdyje dirbsime su PyTorch. Įdiegkime:

conda install pytorch torchvision cudatoolkit=10.1 -c pytorch

Dabar turime paleisti Jupyter Notebook – populiarų ML specialistų kūrimo įrankį. Tai leidžia parašyti kodą ir iš karto pamatyti jo vykdymo rezultatus. „Jupyter Notebook“ yra įtrauktas į „Anaconda“ ir jau įdiegtas mūsų serveryje. Prie jo reikia prisijungti iš mūsų darbalaukio sistemos.

Norėdami tai padaryti, pirmiausia paleisime Jupyter serveryje, nurodydami 8080 prievadą:

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

Tada atidarę kitą skirtuką „Cmder“ pulte (viršutinis meniu - Naujos konsolės dialogas), per 8080 prievadą prisijungsime prie serverio per SSH:

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

Kai įvesime pirmąją komandą, mums bus pasiūlytos nuorodos atidaryti Jupyter naršyklėje:

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

Naudokime saitą localhost:8080. Nukopijuokite visą kelią ir įklijuokite jį į savo kompiuterio vietinės naršyklės adreso juostą. Atsidarys „Jupyter“ užrašų knygelė.

Sukurkime naują bloknotą: Nauja – Užrašų knygelė – Python 3.

Patikrinkime, ar tinkamai veikia visi mūsų įdiegti komponentai. Įveskime pavyzdinį PyTorch kodą į Jupyter ir paleiskite vykdymą (mygtukas Vykdyti):

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

Rezultatas turėtų būti maždaug toks:

Jūsų pirmasis neuroninis tinklas grafikos apdorojimo bloke (GPU). Pradedančiųjų vadovas

Jei turite panašų rezultatą, mes viską sukonfigūravome teisingai ir galime pradėti kurti neuroninį tinklą!

Neuroninio tinklo kūrimas

Sukursime neuroninį tinklą vaizdo atpažinimui. Paimkime tai kaip pagrindą vadovas.

Tinklui apmokyti naudosime viešai prieinamą CIFAR10 duomenų rinkinį. Jame yra klasės: „lėktuvas“, „automobilis“, „paukštis“, „katė“, „elnias“, „šuo“, „varlė“, „arklys“, „laivas“, „sunkvežimis“. CIFAR10 vaizdai yra 3x32x32, tai yra 3 kanalų spalvoti 32x32 pikselių vaizdai.

Jūsų pirmasis neuroninis tinklas grafikos apdorojimo bloke (GPU). Pradedančiųjų vadovas
Darbui naudosime PyTorch sukurtą paketą darbui su vaizdais – torchvision.

Mes atliksime šiuos veiksmus eilės tvarka:

  • Treniruočių ir testų duomenų rinkinių įkėlimas ir normalizavimas
  • Neuroninio tinklo apibrėžimas
  • Tinklo mokymai apie mokymo duomenis
  • Tinklo bandymas naudojant bandymo duomenis
  • Pakartokime mokymą ir testavimą naudojant GPU

Mes vykdysime visą toliau pateiktą kodą „Jupyter Notebook“.

Įkeliamas ir normalizuojamas CIFAR10

Nukopijuokite ir paleiskite šį kodą „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 = ('plane', 'car', 'bird', 'cat',
           'deer', 'dog', 'frog', 'horse', 'ship', 'truck')

Atsakymas turėtų būti toks:

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

Testavimui parodykime kelis mokymo vaizdus:


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

Jūsų pirmasis neuroninis tinklas grafikos apdorojimo bloke (GPU). Pradedančiųjų vadovas

Neuroninio tinklo apibrėžimas

Pirmiausia panagrinėkime, kaip veikia vaizdų atpažinimo neuroninis tinklas. Tai paprastas „point-to-point“ tinklas. Jis paima įvesties duomenis, po vieną perduoda juos per kelis sluoksnius ir galiausiai sukuria išvesties duomenis.

Jūsų pirmasis neuroninis tinklas grafikos apdorojimo bloke (GPU). Pradedančiųjų vadovas

Sukurkime panašų tinklą savo aplinkoje:


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

Taip pat apibrėžiame nuostolių funkciją ir optimizatorių


import torch.optim as optim

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

Tinklo mokymai apie mokymo duomenis

Pradėkime treniruoti savo neuroninį tinklą. Atminkite, kad paleidę šį kodą turėsite šiek tiek palaukti, kol darbas bus baigtas. Man užtruko 5 minutes. Tinklui išmokyti reikia laiko.

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

Gauname tokį rezultatą:

Jūsų pirmasis neuroninis tinklas grafikos apdorojimo bloke (GPU). Pradedančiųjų vadovas

Išsaugome savo apmokytą modelį:

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

Tinklo bandymas naudojant bandymo duomenis

Mes apmokėme tinklą naudodami mokymo duomenų rinkinį. Tačiau turime patikrinti, ar tinklas iš viso ko nors išmoko.

Išbandysime tai numatydami klasės etiketę, kurią išveda neuroninis tinklas, ir patikrinsime, ar ji teisinga. Jei prognozė teisinga, pavyzdį įtraukiame į teisingų prognozių sąrašą.
Parodykime vaizdą iš bandymo rinkinio:

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

Jūsų pirmasis neuroninis tinklas grafikos apdorojimo bloke (GPU). Pradedančiųjų vadovas

Dabar paprašykime neuroninio tinklo pasakyti, kas yra šiose nuotraukose:


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

Jūsų pirmasis neuroninis tinklas grafikos apdorojimo bloke (GPU). Pradedančiųjų vadovas

Rezultatai atrodo gana geri: tinklas teisingai nustatė tris iš keturių nuotraukų.

Pažiūrėkime, kaip tinklas veikia visame duomenų rinkinyje.


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

Jūsų pirmasis neuroninis tinklas grafikos apdorojimo bloke (GPU). Pradedančiųjų vadovas

Panašu, kad tinklas kažką žino ir veikia. Jei jis klases nustatytų atsitiktinai, tikslumas būtų 10%.

Dabar pažiūrėkime, kurias klases tinklas identifikuoja geriau:

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

Jūsų pirmasis neuroninis tinklas grafikos apdorojimo bloke (GPU). Pradedančiųjų vadovas

Atrodo, kad tinklas geriausiai identifikuoja automobilius ir laivus: 71% tikslumas.

Taigi tinklas veikia. Dabar pabandykime perkelti jo darbą į grafikos procesorių (GPU) ir pažiūrėkime, kas pasikeis.

Neuroninio tinklo mokymas ant GPU

Pirmiausia trumpai paaiškinsiu, kas yra CUDA. CUDA (Compute Unified Device Architecture) yra lygiagrečios skaičiavimo platforma, sukurta NVIDIA, skirta bendrajam skaičiavimui grafikos apdorojimo blokuose (GPU). Naudodami CUDA, kūrėjai gali žymiai pagreitinti skaičiavimo programas, išnaudodami GPU galią. Ši platforma jau įdiegta mūsų įsigytame serveryje.

Pirmiausia apibrėžkime savo GPU kaip pirmąjį matomą Cuda įrenginį.

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 )

Jūsų pirmasis neuroninis tinklas grafikos apdorojimo bloke (GPU). Pradedančiųjų vadovas

Tinklo siuntimas į GPU:

net.to(device)

Taip pat kiekviename žingsnyje turėsime siųsti įvestis ir taikinius į GPU:

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

Iš naujo apmokykime tinklą 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')

Šį kartą tinklinės treniruotės truko apie 3 minutes. Prisiminkime, kad tas pats etapas įprastame procesoriuje truko 5 minutes. Skirtumas nėra reikšmingas, taip nutinka todėl, kad mūsų tinklas nėra toks didelis. Treniruotėms naudojant didelius masyvus, GPU ir tradicinio procesoriaus greičio skirtumas padidės.

Atrodo, kad viskas. Ką mums pavyko padaryti:

  • Pažiūrėjome, kas yra GPU, ir pasirinkome serverį, kuriame jis įdiegtas;
  • Sukūrėme programinę aplinką neuroniniam tinklui sukurti;
  • Sukūrėme vaizdų atpažinimo neuroninį tinklą ir jį apmokėme;
  • Mes pakartojome tinklo mokymą naudodami GPU ir padidinome greitį.

Mielai atsakysiu į klausimus komentaruose.

Šaltinis: www.habr.com

Добавить комментарий