Vaša prva nevronska mreža na grafični procesorski enoti (GPE). Priročnik za začetnike

Vaša prva nevronska mreža na grafični procesorski enoti (GPE). Priročnik za začetnike
V tem članku vam bom povedal, kako v 30 minutah vzpostaviti okolje strojnega učenja, ustvariti nevronsko mrežo za prepoznavanje slik in nato isto mrežo zagnati na grafičnem procesorju (GPE).

Najprej opredelimo, kaj je nevronska mreža.

V našem primeru je to matematični model, pa tudi njegova programska ali strojna izvedba, zgrajena na principu organizacije in delovanja bioloških nevronskih mrež - mrež živčnih celic živega organizma. Ta koncept je nastal med preučevanjem procesov, ki se dogajajo v možganih, in poskusom modeliranja teh procesov.

Nevronske mreže niso programirane v običajnem pomenu besede, ampak so usposobljene. Sposobnost učenja je ena glavnih prednosti nevronskih mrež pred tradicionalnimi algoritmi. Tehnično je učenje sestavljeno iz iskanja koeficientov povezav med nevroni. V procesu usposabljanja je nevronska mreža sposobna prepoznati kompleksne odvisnosti med vhodnimi in izhodnimi podatki ter izvesti posplošitev.

Z vidika strojnega učenja je nevronska mreža poseben primer metod za prepoznavanje vzorcev, diskriminantne analize, metod združevanja v gruče in drugih metod.

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

Najprej si oglejmo opremo. Potrebujemo strežnik z nameščenim operacijskim sistemom Linux. Oprema, ki je potrebna za delovanje sistemov strojnega učenja, je precej zmogljiva in posledično draga. Tistim, ki pri roki nimate dobrega stroja, priporočam, da ste pozorni na ponudbe ponudnikov v oblaku. Zahtevani strežnik lahko hitro najamete in plačate le čas uporabe.

Pri projektih, kjer je potrebno ustvariti nevronske mreže, uporabljam strežnike enega od ruskih ponudnikov oblakov. Podjetje ponuja najem strežnikov v oblaku posebej za strojno učenje z zmogljivimi grafičnimi procesorji Tesla V100 (GPU) podjetja NVIDIA. Na kratko: uporaba strežnika z GPE je lahko desetkrat učinkovitejša (hitrejša) v primerjavi s strežnikom podobne cene, ki za izračune uporablja CPE (dobro znana centralna procesna enota). To je doseženo zaradi značilnosti arhitekture GPU, ki se hitreje spopada z izračuni.

Za izvedbo spodaj opisanih primerov smo za več dni kupili naslednji strežnik:

  • SSD disk 150 GB
  • RAM 32 GB
  • Tesla V100 16 Gb procesor s 4 jedri

Na naš računalnik smo namestili Ubuntu 18.04.

Postavitev okolja

Zdaj pa namestimo vse, kar je potrebno za delo na strežniku. Ker je naš članek namenjen predvsem začetnikom, bom govoril o nekaterih točkah, ki jim bodo koristne.

Veliko dela pri nastavljanju okolja se opravi prek ukazne vrstice. Večina uporabnikov uporablja Windows kot delovni OS. Standardna konzola v tem operacijskem sistemu pušča veliko želenega. Zato bomo uporabili priročno orodje Cmder/. Prenesite mini različico in zaženite Cmder.exe. Nato se morate povezati s strežnikom prek SSH:

ssh root@server-ip-or-hostname

Namesto server-ip-ali-hostname določite naslov IP ali ime DNS vašega strežnika. Nato vnesite geslo in če je povezava uspešna, bi morali prejeti podobno sporočilo.

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

Glavni jezik za razvoj modelov ML je Python. In najbolj priljubljena platforma za njegovo uporabo v Linuxu je anaconda.

Namestimo ga na naš strežnik.

Začnemo s posodobitvijo lokalnega upravitelja paketov:

sudo apt-get update

Namestite curl (pripomoček ukazne vrstice):

sudo apt-get install curl

Prenesite najnovejšo različico Anaconda Distribution:

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

Začnimo namestitev:

bash Anaconda3-2019.10-Linux-x86_64.sh

Med postopkom namestitve boste morali potrditi licenčno pogodbo. Po uspešni namestitvi bi morali videti tole:

Thank you for installing Anaconda3!

Za razvoj modelov ML je bilo ustvarjenih veliko ogrodij; delamo z najbolj priljubljenimi: PyTorch и Tenzorski tok.

Uporaba ogrodja vam omogoča, da povečate hitrost razvoja in uporabite že pripravljena orodja za standardne naloge.

V tem primeru bomo delali s PyTorch. Namestimo ga:

conda install pytorch torchvision cudatoolkit=10.1 -c pytorch

Zdaj moramo zagnati Jupyter Notebook, priljubljeno razvojno orodje za strokovnjake za ML. Omogoča pisanje kode in takojšen ogled rezultatov njene izvedbe. Jupyter Notebook je vključen v Anacondo in je že nameščen na našem strežniku. Nanj se morate povezati iz našega namiznega sistema.

Da bi to naredili, bomo najprej zagnali Jupyter na strežniku z navedbo vrat 8080:

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

Nato odpremo drug zavihek v naši konzoli Cmder (zgornji meni - pogovorno okno Nova konzola) in se prek vrat 8080 povežemo s strežnikom prek SSH:

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

Ko vnesemo prvi ukaz, se nam v brskalniku ponudijo povezave za odpiranje Jupyterja:

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

Uporabimo povezavo za localhost:8080. Kopirajte celotno pot in jo prilepite v naslovno vrstico lokalnega brskalnika vašega računalnika. Odpre se Jupyter Notebook.

Ustvarimo nov zvezek: Novo – Beležnica – Python 3.

Preverimo pravilno delovanje vseh komponent, ki smo jih namestili. V Jupyter vnesemo primer kode PyTorch in zaženemo izvedbo (gumb Zaženi):

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

Rezultat bi moral biti nekaj takega:

Vaša prva nevronska mreža na grafični procesorski enoti (GPE). Priročnik za začetnike

Če imate podoben rezultat, potem smo vse pravilno konfigurirali in lahko začnemo razvijati nevronsko mrežo!

Ustvarjanje nevronske mreže

Ustvarili bomo nevronsko mrežo za prepoznavanje slik. Vzemimo to za osnovo vodstvo.

Za usposabljanje omrežja bomo uporabili javno dostopen nabor podatkov CIFAR10. Ima razrede: "letalo", "avto", "ptica", "mačka", "jelen", "pes", "žaba", "konj", "ladja", "tovornjak". Slike v CIFAR10 so 3x32x32, torej 3-kanalne barvne slike 32x32 slikovnih pik.

Vaša prva nevronska mreža na grafični procesorski enoti (GPE). Priročnik za začetnike
Za delo bomo uporabljali paket, ki ga je ustvaril PyTorch za delo s slikami - torchvision.

Naslednje korake bomo izvedli po vrstnem redu:

  • Nalaganje in normalizacija nizov podatkov o usposabljanju in testih
  • Definicija nevronske mreže
  • Omrežno usposabljanje na podatkih o usposabljanju
  • Testiranje omrežja na testnih podatkih
  • Ponovimo usposabljanje in testiranje z GPU

Vso spodnjo kodo bomo izvedli v Jupyter Notebook.

Nalaganje in normalizacija CIFAR10

Kopirajte in zaženite naslednjo kodo v Jupyterju:


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 moral 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 več slik za vadbo 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 nevronska mreža na grafični procesorski enoti (GPE). Priročnik za začetnike

Definicija nevronske mreže

Najprej razmislimo, kako deluje nevronska mreža za prepoznavanje slik. To je preprosto omrežje od točke do točke. Vzame vhodne podatke, jih prenese skozi več plasti enega za drugim in nato končno proizvede izhodne podatke.

Vaša prva nevronska mreža na grafični procesorski enoti (GPE). Priročnik za začetnike

Ustvarimo podobno mrežo v našem okolju:


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

Definiramo tudi funkcijo izgube in optimizator


import torch.optim as optim

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

Omrežno usposabljanje na podatkih o usposabljanju

Začnimo trenirati našo nevronsko mrežo. Upoštevajte, da boste morali po zagonu te kode počakati nekaj časa, da bo delo končano. Vzelo mi je 5 minut. Za usposabljanje omrežja je potreben čas.

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

Dobimo naslednji rezultat:

Vaša prva nevronska mreža na grafični procesorski enoti (GPE). Priročnik za začetnike

Shranimo naš usposobljeni model:

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

Testiranje omrežja na testnih podatkih

Omrežje smo usposobili z naborom učnih podatkov. Moramo pa preveriti, ali se je omrežje sploh česa naučilo.

To bomo preizkusili tako, da bomo predvideli oznako razreda, ki jo izpiše nevronska mreža, in jo testirali, da vidimo, ali je resnična. Če je napoved pravilna, dodamo vzorec na seznam pravilnih napovedi.
Pokažimo sliko iz testnega niza:

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 nevronska mreža na grafični procesorski enoti (GPE). Priročnik za začetnike

Zdaj pa prosimo nevronsko mrežo, da nam pove, kaj je na teh slikah:


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 nevronska mreža na grafični procesorski enoti (GPE). Priročnik za začetnike

Rezultati se zdijo precej dobri: omrežje je pravilno identificiralo tri od štirih slik.

Poglejmo, kako deluje omrežje v celotnem naboru podatkov.


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 nevronska mreža na grafični procesorski enoti (GPE). Priročnik za začetnike

Videti je, da omrežje nekaj ve in deluje. Če bi razrede določil naključno, bi bila natančnost 10 %.

Zdaj pa poglejmo, katere razrede omrežje 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 nevronska mreža na grafični procesorski enoti (GPE). Priročnik za začetnike

Zdi se, da je omrežje najboljše pri prepoznavanju avtomobilov in ladij: 71-odstotna natančnost.

Omrežje torej deluje. Zdaj pa poskusimo prenesti njegovo delo na grafični procesor (GPU) in poglejmo, kaj se bo spremenilo.

Usposabljanje nevronske mreže na GPU

Najprej bom na kratko razložil, kaj je CUDA. CUDA (Compute Unified Device Architecture) je vzporedna računalniška platforma, ki jo je razvila NVIDIA za splošno računalništvo na grafičnih procesnih enotah (GPU). S CUDA lahko razvijalci dramatično pospešijo računalniške aplikacije z izkoriščanjem moči grafičnih procesorjev. Ta platforma je že nameščena na našem strežniku, ki smo ga kupili.

Najprej definirajmo naš GPE kot prvo vidno napravo cuda.

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 nevronska mreža na grafični procesorski enoti (GPE). Priročnik za začetnike

Pošiljanje omrežja v GPE:

net.to(device)

GPE-ju bomo morali na vsakem koraku poslati tudi vnose in cilje:

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

Ponovno usposobimo omrežje 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')

Tokratni mrežni trening je trajal približno 3 minute. Spomnimo se, da je ista stopnja na običajnem procesorju trajala 5 minut. Razlika ni bistvena, to se zgodi, ker naše omrežje ni tako veliko. Pri uporabi velikih nizov za usposabljanje se bo razlika med hitrostjo GPE in tradicionalnim procesorjem povečala.

Zdi se, da je to vse. Kaj nam je uspelo:

  • Pogledali smo, kaj je GPE in izbrali strežnik, na katerem je nameščen;
  • Vzpostavili smo programsko okolje za ustvarjanje nevronske mreže;
  • Ustvarili smo nevronsko mrežo za prepoznavanje slik in jo usposobili;
  • Ponovili smo omrežno usposabljanje z GPE in prejeli povečanje hitrosti.

Z veseljem bom odgovoril na vprašanja v komentarjih.

Vir: www.habr.com

Dodaj komentar