Jūsu pirmais neironu tīkls grafikas apstrādes blokā (GPU). Rokasgrāmata iesācējiem

Jūsu pirmais neironu tīkls grafikas apstrādes blokā (GPU). Rokasgrāmata iesācējiem
Å ajā rakstā es jums pastāstÄ«Å”u, kā 30 minÅ«tēs iestatÄ«t maŔīnmācÄ«Å”anās vidi, izveidot neironu tÄ«klu attēlu atpazÄ«Å”anai un pēc tam palaist to paÅ”u tÄ«klu grafikas procesorā (GPU).

Pirmkārt, definēsim, kas ir neironu tīkls.

MÅ«su gadÄ«jumā tas ir matemātisks modelis, kā arÄ« tā programmatÅ«ras vai aparatÅ«ras iemiesojums, kas veidots pēc bioloÄ£isko neironu tÄ«klu - dzÄ«va organisma nervu Ŕūnu tÄ«klu - organizācijas un darbÄ«bas principa. Å Ä« koncepcija radās, pētot smadzenēs notiekoÅ”os procesus un mēģinot modelēt Å”os procesus.

Neironu tÄ«kli nav ieprogrammēti Ŕī vārda parastajā nozÄ«mē, tie ir apmācÄ«ti. Spēja mācÄ«ties ir viena no galvenajām neironu tÄ«klu priekÅ”rocÄ«bām salÄ«dzinājumā ar tradicionālajiem algoritmiem. Tehniski mācÄ«Å”anās sastāv no neironu savienojumu koeficientu atraÅ”anas. ApmācÄ«bas procesā neironu tÄ«kls spēj identificēt sarežģītas atkarÄ«bas starp ievaddatiem un izvaddatiem, kā arÄ« veikt vispārināŔanu.

No maŔīnmācīŔanās viedokļa neironu tīkls ir īpaŔs modeļu atpazīŔanas metožu, diskriminantu analīzes, klasterizācijas metožu un citu metožu gadījums.

ŠžŠ±Š¾Ń€ŃƒŠ“Š¾Š²Š°Š½ŠøŠµ

Vispirms apskatÄ«sim aprÄ«kojumu. Mums ir nepiecieÅ”ams serveris ar instalētu Linux operētājsistēmu. MaŔīnmācÄ«Å”anās sistēmu darbÄ«bai nepiecieÅ”amais aprÄ«kojums ir diezgan jaudÄ«gs un lÄ«dz ar to dārgs. Tiem, kam pie rokas nav labas maŔīnas, iesaku pievērst uzmanÄ«bu mākoņpakalpojumu sniedzēju piedāvājumiem. NepiecieÅ”amo serveri var ātri iznomāt un maksāt tikai par lietoÅ”anas laiku.

Projektos, kur nepiecieÅ”ams izveidot neironu tÄ«klus, izmantoju kāda Krievijas mākoņpakalpojumu sniedzēja serverus. Uzņēmums piedāvā nomāt mākoņserverus Ä«paÅ”i maŔīnmācÄ«bai ar jaudÄ«giem Tesla V100 grafikas procesoriem (GPU) no NVIDIA. ÄŖsāk sakot: servera ar GPU izmantoÅ”ana var bÅ«t desmitiem reižu efektÄ«vāka (ātrāka) salÄ«dzinājumā ar lÄ«dzÄ«gu izmaksu serveri, kas aprēķiniem izmanto CPU (labi zināmo centrālo procesoru). Tas tiek panākts, pateicoties GPU arhitektÅ«ras iezÄ«mēm, kas ātrāk tiek galā ar aprēķiniem.

Lai Ä«stenotu tālāk aprakstÄ«tos piemērus, mēs uz vairākām dienām iegādājāmies Ŕādu serveri:

  • SSD disks 150 GB
  • RAM 32 GB
  • Tesla V100 16 Gb procesors ar 4 kodoliem

Mēs savā datorā instalējām Ubuntu 18.04.

Vides iekārtoŔana

Tagad instalēsim visu darbam nepiecieÅ”amo uz servera. Tā kā mÅ«su raksts galvenokārt ir paredzēts iesācējiem, es runāŔu par dažiem punktiem, kas viņiem bÅ«s noderÄ«gi.

Liela daļa darba vides iestatÄ«Å”anas laikā tiek veikta, izmantojot komandrindu. Lielākā daļa lietotāju izmanto Windows kā savu darba OS. Standarta konsole Å”ajā OS atstāj daudz ko vēlēties. Tāpēc mēs izmantosim ērtu rÄ«ku Cmder/. Lejupielādējiet mini versiju un palaidiet Cmder.exe. Tālāk jums ir jāizveido savienojums ar serveri, izmantojot SSH:

ssh root@server-ip-or-hostname

Servera ip vai resursdatora nosaukums vietā norādiet sava servera IP adresi vai DNS nosaukumu. Pēc tam ievadiet paroli un, ja savienojums ir veiksmÄ«gs, mums vajadzētu saņemt lÄ«dzÄ«gu ziņojumu.

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

Galvenā valoda ML modeļu izstrādei ir Python. Un vispopulārākā platforma tās lietoÅ”anai operētājsistēmā Linux ir Anaconda.

Instalēsim to savā serverī.

Mēs sākam ar vietējā pakotņu pārvaldnieka atjaunināŔanu:

sudo apt-get update

Instalējiet curl (komandrindas utilīta):

sudo apt-get install curl

Lejupielādējiet jaunāko Anaconda Distribution versiju:

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

Sāksim instalÄ“Å”anu:

bash Anaconda3-2019.10-Linux-x86_64.sh

InstalÄ“Å”anas procesa laikā jums tiks lÅ«gts apstiprināt licences lÄ«gumu. Pēc veiksmÄ«gas instalÄ“Å”anas jums vajadzētu redzēt Å”o:

Thank you for installing Anaconda3!

ML modeļu izstrādei tagad ir izveidoti daudzi ietvari, mēs strādājam ar populārākajiem: PyTorch Šø tenzora plÅ«sma.

Izmantojot ietvaru, varat palielināt izstrādes ātrumu un izmantot gatavus rīkus standarta uzdevumiem.

Šajā piemērā mēs strādāsim ar PyTorch. Instalēsim to:

conda install pytorch torchvision cudatoolkit=10.1 -c pytorch

Tagad mums ir jāizlaiž Jupyter Notebook, populārs izstrādes rīks ML speciālistiem. Tas ļauj rakstīt kodu un nekavējoties redzēt tā izpildes rezultātus. Jupyter piezīmjdators ir iekļauts Anaconda komplektācijā un jau ir instalēts mūsu serverī. Jums ir jāizveido savienojums ar to no mūsu darbvirsmas sistēmas.

Lai to izdarītu, mēs vispirms palaidīsim Jupyter serverī, norādot portu 8080:

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

Pēc tam, atverot citu cilni mÅ«su Cmder konsolē (augŔējā izvēlne ā€” dialoglodziņŔ Jauna konsole), mēs caur portu 8080 izveidosim savienojumu ar serveri, izmantojot SSH:

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

Ievadot pirmo komandu, mums tiks piedāvātas saites, lai pārlūkprogrammā atvērtu Jupyter:

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

Izmantosim saiti uz localhost:8080. Kopējiet pilnu ceļu un ielīmējiet to datora lokālās pārlūkprogrammas adreses joslā. Tiks atvērts Jupyter piezīmju grāmatiņa.

Izveidosim jaunu piezīmju grāmatiņu: Jauns - Piezīmju grāmatiņa - Python 3.

Pārbaudīsim visu mūsu instalēto komponentu pareizu darbību. Ievadīsim PyTorch koda piemēru Jupyter un palaidīsim izpildi (poga Palaist):

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

Rezultātam vajadzētu bÅ«t apmēram Ŕādam:

Jūsu pirmais neironu tīkls grafikas apstrādes blokā (GPU). Rokasgrāmata iesācējiem

Ja jums ir lÄ«dzÄ«gs rezultāts, tad esam visu pareizi konfigurējuÅ”i un varam sākt neironu tÄ«kla izstrādi!

Neironu tīkla izveide

Izveidosim neironu tÄ«klu attēlu atpazÄ«Å”anai. Ņemsim to par pamatu vadÄ«ba.

TÄ«kla apmācÄ«Å”anai izmantosim publiski pieejamo CIFAR10 datu kopu. Tam ir klases: "lidmaŔīna", "maŔīna", "putns", "kaÄ·is", "brieži", "suns", "varde", "zirgs", "kuÄ£is", "kravas automaŔīna". CIFAR10 attēli ir 3x32x32, tas ir, 3 kanālu krāsu attēli ar 32x32 pikseļiem.

Jūsu pirmais neironu tīkls grafikas apstrādes blokā (GPU). Rokasgrāmata iesācējiem
Darbam izmantosim PyTorch izveidoto pakotni darbam ar attēliem - torchvision.

Mēs veiksim Ŕādas darbÄ«bas secÄ«bā:

  • ApmācÄ«bas un testa datu kopu ielāde un normalizÄ“Å”ana
  • Neironu tÄ«kla definÄ«cija
  • TÄ«kla apmācÄ«ba par apmācÄ«bu datiem
  • TÄ«kla testÄ“Å”ana uz testa datiem
  • Atkārtosim apmācÄ«bu un testÄ“Å”anu, izmantojot GPU

Mēs izpildīsim visu tālāk norādīto kodu Jupyter Notebook.

CIFAR10 ielāde un normalizÄ“Å”ana

Kopējiet un palaidiet Å”o kodu programmā 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')

Atbildei jābūt Ŕādai:

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

Pārbaudei parādīsim vairākus treniņu attēlus:


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ūsu pirmais neironu tīkls grafikas apstrādes blokā (GPU). Rokasgrāmata iesācējiem

Neironu tīkla definīcija

Vispirms apskatÄ«sim, kā darbojas attēlu atpazÄ«Å”anas neironu tÄ«kls. Å is ir vienkārÅ”s tÄ«kls no punkta uz punktu. Tas ņem ievades datus, izlaiž tos pa vairākiem slāņiem pa vienam un pēc tam beidzot ražo izvaddatus.

Jūsu pirmais neironu tīkls grafikas apstrādes blokā (GPU). Rokasgrāmata iesācējiem

Izveidosim līdzīgu tīklu mūsu vidē:


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ēs arī definējam zaudējumu funkciju un optimizētāju


import torch.optim as optim

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

Tīkla apmācība par apmācību datiem

Sāksim apmācÄ«t savu neironu tÄ«klu. LÅ«dzu, ņemiet vērā, ka pēc Ŕī koda palaiÅ”anas jums bÅ«s jāgaida zināms laiks, lÄ«dz darbs tiks pabeigts. Man tas aizņēma 5 minÅ«tes. TÄ«kla apmācÄ«bai nepiecieÅ”ams laiks.

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

Mēs iegÅ«stam Ŕādu rezultātu:

Jūsu pirmais neironu tīkls grafikas apstrādes blokā (GPU). Rokasgrāmata iesācējiem

Mēs saglabājam mūsu apmācīto modeli:

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

Tīkla testēŔana uz testa datiem

Mēs apmācÄ«jām tÄ«klu, izmantojot apmācÄ«bas datu kopu. Bet mums ir jāpārbauda, ā€‹ā€‹vai tÄ«kls vispār ir kaut ko iemācÄ«jies.

Mēs to pārbaudīsim, paredzot neironu tīkla izvadīto klases etiķeti un pārbaudot, vai tā ir patiesa. Ja prognoze ir pareiza, paraugu pievienojam pareizo prognožu sarakstam.
Parādīsim attēlu no testa komplekta:

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ūsu pirmais neironu tīkls grafikas apstrādes blokā (GPU). Rokasgrāmata iesācējiem

Tagad palÅ«gsim neironu tÄ«klam pastāstÄ«t, kas ir Å”ajos attēlos:


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ūsu pirmais neironu tīkls grafikas apstrādes blokā (GPU). Rokasgrāmata iesācējiem

Rezultāti Ŕķiet diezgan labi: tÄ«kls pareizi identificēja trÄ«s no četriem attēliem.

Apskatīsim, kā tīkls darbojas visā datu kopā.


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ūsu pirmais neironu tīkls grafikas apstrādes blokā (GPU). Rokasgrāmata iesācējiem

Å Ä·iet, ka tÄ«kls kaut ko zina un darbojas. Ja viņŔ nejauÅ”i noteiktu klases, precizitāte bÅ«tu 10%.

Tagad apskatīsim, kuras klases tīkls identificē labāk:

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ūsu pirmais neironu tīkls grafikas apstrādes blokā (GPU). Rokasgrāmata iesācējiem

Å Ä·iet, ka tÄ«kls vislabāk identificē automaŔīnas un kuÄ£us: 71% precizitāte.

Tātad tīkls darbojas. Tagad mēģināsim pārsūtīt tā darbu uz grafikas procesoru (GPU) un redzēsim, kas mainās.

Neironu tīkla apmācība uz GPU

Pirmkārt, es Ä«si paskaidroÅ”u, kas ir CUDA. CUDA (Compute Unified Device Architecture) ir paralēla skaitļoÅ”anas platforma, ko NVIDIA izstrādājusi vispārējai skaitļoÅ”anai grafikas apstrādes blokos (GPU). Izmantojot CUDA, izstrādātāji var ievērojami paātrināt skaitļoÅ”anas lietojumprogrammas, izmantojot GPU jaudu. Å Ä« platforma jau ir instalēta mÅ«su iegādātajā serverÄ«.

Vispirms definēsim mūsu GPU kā pirmo redzamo Cuda ierīci.

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ūsu pirmais neironu tīkls grafikas apstrādes blokā (GPU). Rokasgrāmata iesācējiem

Tīkla nosūtīŔana uz GPU:

net.to(device)

Mums būs arī jānosūta ievades dati un mērķi katrā solī uz GPU:

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

Atkārtoti apmācīsim tīklu 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')

Å oreiz tÄ«kla treniņŔ ilga apmēram 3 minÅ«tes. Atcerēsimies, ka tas pats posms parastajā procesorā ilga 5 minÅ«tes. AtŔķirÄ«ba nav bÅ«tiska, tas notiek tāpēc, ka mÅ«su tÄ«kls nav tik liels. Izmantojot lielus masÄ«vus apmācÄ«bai, palielināsies atŔķirÄ«ba starp GPU un tradicionālā procesora ātrumu.

Šķiet, ka tas arī viss. Ko mums izdevās paveikt:

  • Mēs apskatÄ«jām, kas ir GPU, un izvēlējāmies serveri, kurā tas ir instalēts;
  • Mēs esam izveidojuÅ”i programmatÅ«ras vidi neironu tÄ«kla izveidei;
  • Mēs izveidojām neironu tÄ«klu attēlu atpazÄ«Å”anai un apmācām to;
  • Mēs atkārtojām tÄ«kla apmācÄ«bu, izmantojot GPU, un saņēmām ātruma pieaugumu.

Labprāt atbildÄ“Å”u uz jautājumiem komentāros.

Avots: www.habr.com

Pievieno komentāru