Via unua neŭrala reto sur grafika prilaboranta unuo (GPU). Gvidilo por komencantoj

Via unua neŭrala reto sur grafika prilaboranta unuo (GPU). Gvidilo por komencantoj
En ĉi tiu artikolo, mi rakontos al vi kiel agordi maŝinlernantan medion en 30 minutoj, krei neŭralan reton por bilda rekono, kaj poste funkcii la saman reton per grafika procesoro (GPU).

Unue, ni difinu kio estas neŭrala reto.

En nia kazo, ĉi tio estas matematika modelo, same kiel ĝia programaro aŭ aparataro enkorpiĝo, konstruita sur la principo de organizo kaj funkciado de biologiaj neŭralaj retoj - retoj de nervaj ĉeloj de vivanta organismo. Ĉi tiu koncepto ekestis studante la procezojn okazantajn en la cerbo kaj provante modeligi ĉi tiujn procezojn.

Neŭralaj retoj ne estas programitaj en la kutima senco de la vorto, ili estas trejnitaj. La kapablo lerni estas unu el la ĉefaj avantaĝoj de neŭralaj retoj super tradiciaj algoritmoj. Teknike, lernado konsistas el trovado de la koeficientoj de ligoj inter neŭronoj. Dum la trejnadprocezo, la neŭrala reto povas identigi kompleksajn dependecojn inter enirdatenoj kaj produktaĵdatenoj, same kiel plenumi ĝeneraligo.

El la vidpunkto de maŝinlernado, neŭrala reto estas speciala kazo de padronrekono-metodoj, diskriminacia analizo, amasigaj metodoj kaj aliaj metodoj.

Ekipaĵo

Unue, ni rigardu la ekipaĵon. Ni bezonas servilon kun la Linukso operaciumo instalita sur ĝi. La ekipaĵo necesa por funkciigi maŝinlernajn sistemojn estas sufiĉe potencaj kaj, kiel rezulto, multekostaj. Por tiuj, kiuj ne havas bonan maŝinon ĉemane, mi rekomendas atenti la ofertojn de nubaj provizantoj. Vi povas rapide lui la postulatan servilon kaj pagi nur por la tempo de uzo.

En projektoj, kie necesas krei neŭralaj retoj, mi uzas la servilojn de unu el la rusaj nubaj provizantoj. La kompanio ofertas nubajn servilojn lueblaj specife por maŝinlernado kun potencaj grafikaj procesoroj Tesla V100 (GPU) de NVIDIA. Resume: uzi servilon kun GPU povas esti dekoble pli efika (rapida) kompare kun servilo de simila kosto, kiu uzas CPU (la konata centra prilaborado) por kalkuloj. Ĉi tio estas atingita pro la trajtoj de la GPU-arkitekturo, kiu eltenas kalkulojn pli rapide.

Por efektivigi la ekzemplojn priskribitajn sube, ni aĉetis la sekvan servilon dum pluraj tagoj:

  • SSD-disko 150 GB
  • RAM 32 GB
  • Tesla V100 16 Gb-procesoro kun 4 kernoj

Ni instalis Ubuntu 18.04 sur nia maŝino.

Agordo de la medio

Nun ni instalu ĉion necesan por labori en la servilo. Ĉar nia artikolo estas ĉefe por komencantoj, mi parolos pri iuj punktoj, kiuj estos utilaj al ili.

Multe da laboro dum agordado de medio estas farita per la komandlinio. Plej multaj uzantoj uzas Vindozon kiel sian funkciantan OS. La norma konzolo en ĉi tiu OS lasas multon por deziri. Tial ni uzos oportunan ilon Cmder/. Elŝutu la mini-version kaj rulu Cmder.exe. Poste vi devas konektiĝi al la servilo per SSH:

ssh root@server-ip-or-hostname

Anstataŭ servilo-ip-aŭ-gastigantonomo, specifu la IP-adreson aŭ DNS-nomon de via servilo. Poste, enigu la pasvorton kaj se la konekto estas sukcesa, ni devus ricevi mesaĝon similan al ĉi tio.

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

La ĉefa lingvo por disvolvi ML-modelojn estas Python. Kaj la plej populara platformo por ĝia uzo en Linukso estas Anakondo.

Ni instalu ĝin sur nia servilo.

Ni komencas ĝisdatigante la lokan pakaĵadministrilon:

sudo apt-get update

Instalu buklon (komandlinia utileco):

sudo apt-get install curl

Elŝutu la lastan version de Anaconda Distribution:

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

Ni komencu la instaladon:

bash Anaconda3-2019.10-Linux-x86_64.sh

Dum la instala procezo, oni petos vin konfirmi la permesilan interkonsenton. Post sukcesa instalado, vi devus vidi ĉi tion:

Thank you for installing Anaconda3!

Multaj kadroj nun estis kreitaj por la evoluo de ML-modeloj; ni laboras kun la plej popularaj: PyTorch и Tensorfluo.

Uzado de la kadro permesas vin pliigi la rapidecon de disvolviĝo kaj uzi pretajn ilojn por normaj taskoj.

En ĉi tiu ekzemplo ni laboros kun PyTorch. Ni instalu ĝin:

conda install pytorch torchvision cudatoolkit=10.1 -c pytorch

Nun ni devas lanĉi Jupyter Notebook, popularan evoluilon por ML-specialistoj. Ĝi permesas vin skribi kodon kaj tuj vidi la rezultojn de ĝia ekzekuto. Jupyter Notebook estas inkluzivita kun Anaconda kaj jam estas instalita sur nia servilo. Vi devas konekti al ĝi de nia labortabla sistemo.

Por fari tion, ni unue lanĉos Jupyter sur la servilo specifante la havenon 8080:

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

Poste, malfermante alian langeton en nia Cmder-konzolo (supra menuo - Nova konzola dialogo) ni konektos per haveno 8080 al la servilo per SSH:

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

Kiam ni enigas la unuan komandon, ni proponos ligilojn por malfermi Jupyter en nia retumilo:

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

Ni uzu la ligilon por localhost:8080. Kopiu la plenan vojon kaj algluu ĝin en la adresbreton de la loka retumilo de via komputilo. Jupyter Notebook malfermos.

Ni kreu novan kajeron: Nova - Kajero - Python 3.

Ni kontrolu la ĝustan funkciadon de ĉiuj komponantoj, kiujn ni instalis. Ni enigu la ekzemplon PyTorch-kodon en Jupyter kaj rulu la ekzekuton (Run-butono):

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

La rezulto devus esti io kiel ĉi tio:

Via unua neŭrala reto sur grafika prilaboranta unuo (GPU). Gvidilo por komencantoj

Se vi havas similan rezulton, tiam ni agordis ĉion ĝuste kaj ni povas komenci disvolvi neŭralan reton!

Kreante neŭralan reton

Ni kreos neŭralan reton por bilda rekono. Ni prenu ĉi tion kiel bazon gvidado.

Ni uzos la publike haveblan CIFAR10-datumaron por trejni la reton. Ĝi havas klasojn: "aviadilo", "aŭto", "birdo", "kato", "cervo", "hundo", "rano", "ĉevalo", "ŝipo", "kamiono". Bildoj en CIFAR10 estas 3x32x32, tio estas 3-kanalaj kolorbildoj de 32x32 pikseloj.

Via unua neŭrala reto sur grafika prilaboranta unuo (GPU). Gvidilo por komencantoj
Por laboro, ni uzos la pakaĵon kreitan de PyTorch por labori kun bildoj - torchvision.

Ni faros la sekvajn paŝojn en ordo:

  • Ŝargado kaj normaligo de trejnado kaj testaj datumoj
  • Neŭrala Reto Difino
  • Reta trejnado pri trejnaj datumoj
  • Reto-testado pri testaj datumoj
  • Ni ripetu trejnadon kaj testadon per GPU

Ni ekzekutos la tutan kodon sube en Jupyter Notebook.

Ŝargado kaj normaligo de CIFAR10

Kopiu kaj rulu la sekvan kodon en 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')

La respondo devus esti:

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

Ni montru plurajn trejnajn bildojn por testado:


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

Via unua neŭrala reto sur grafika prilaboranta unuo (GPU). Gvidilo por komencantoj

Neŭrala Reto Difino

Ni unue konsideru kiel funkcias neŭrala reto por bildrekono. Ĉi tio estas simpla punkto-al-punkta reto. Ĝi prenas enigajn datumojn, pasas ĝin tra pluraj tavoloj unu post la alia, kaj poste fine produktas eligajn datumojn.

Via unua neŭrala reto sur grafika prilaboranta unuo (GPU). Gvidilo por komencantoj

Ni kreu similan reton en nia medio:


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

Ni ankaŭ difinas perdan funkcion kaj optimumiganton


import torch.optim as optim

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

Reta trejnado pri trejnaj datumoj

Ni komencu trejni nian neŭralan reton. Bonvolu noti, ke post kiam vi rulos ĉi tiun kodon, vi devos atendi iom da tempo ĝis la laboro finiĝos. Ĝi prenis min 5 minutojn. Necesas tempo por trejni la reton.

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

Ni ricevas la sekvan rezulton:

Via unua neŭrala reto sur grafika prilaboranta unuo (GPU). Gvidilo por komencantoj

Ni konservas nian trejnitan modelon:

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

Reto-testado pri testaj datumoj

Ni trejnis la reton uzante aron da trejnaj datumoj. Sed ni devas kontroli ĉu la reto lernis ion ajn.

Ni testos ĉi tion antaŭdirante la klasetikedon, kiun la neŭrala reto eligas kaj provante ĝin por vidi ĉu ĝi estas vera. Se la antaŭdiro estas ĝusta, ni aldonas la specimenon al la listo de ĝustaj antaŭdiroj.
Ni montru bildon de la testaro:

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

Via unua neŭrala reto sur grafika prilaboranta unuo (GPU). Gvidilo por komencantoj

Nun ni petu la neŭralan reton diri al ni kio estas en ĉi tiuj bildoj:


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

Via unua neŭrala reto sur grafika prilaboranta unuo (GPU). Gvidilo por komencantoj

La rezultoj ŝajnas sufiĉe bonaj: la reto ĝuste identigis tri el kvar bildoj.

Ni vidu kiel la reto funkcias tra la tuta datumaro.


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

Via unua neŭrala reto sur grafika prilaboranta unuo (GPU). Gvidilo por komencantoj

Ŝajnas, ke la reto scias ion kaj funkcias. Se li determinus la klasojn hazarde, la precizeco estus 10%.

Nun ni vidu kiujn klasojn la reto identigas pli bone:

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

Via unua neŭrala reto sur grafika prilaboranta unuo (GPU). Gvidilo por komencantoj

Ŝajnas, ke la reto estas plej bona por identigi aŭtojn kaj ŝipojn: 71% precizeco.

Do la reto funkcias. Nun ni provu translokigi ĝian laboron al la grafika procesoro (GPU) kaj vidu, kio ŝanĝiĝas.

Trejnado de neŭrala reto sur GPU

Unue, mi mallonge klarigos kio estas CUDA. CUDA (Compute Unified Device Architecture) estas paralela komputika platformo evoluigita fare de NVIDIA por ĝenerala komputado sur grafikaj pretigaj unuoj (GPUoj). Kun CUDA, programistoj povas draste akceli komputikaplikojn utiligante la potencon de GPUoj. Ĉi tiu platformo jam estas instalita sur nia servilo, kiun ni aĉetis.

Ni unue difinu nian GPU kiel la unuan videblan kudan aparaton.

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 )

Via unua neŭrala reto sur grafika prilaboranta unuo (GPU). Gvidilo por komencantoj

Sendante la reton al la GPU:

net.to(device)

Ni ankaŭ devos sendi enigojn kaj celojn ĉe ĉiu paŝo al la GPU:

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

Ni retrejnu la reton sur la 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')

Ĉi-foje, la rettrejnado daŭris ĉirkaŭ 3 minutojn. Ni memoru, ke la sama etapo sur konvencia procesoro daŭris 5 minutojn. La diferenco ne estas grava, tio okazas ĉar nia reto ne estas tiom granda. Kiam vi uzas grandajn tabelojn por trejnado, la diferenco inter la rapideco de la GPU kaj tradicia procesoro pliiĝos.

Tio ŝajnas esti ĉio. Kion ni sukcesis fari:

  • Ni rigardis kio estas GPU kaj elektis la servilon sur kiu ĝi estas instalita;
  • Ni starigis programaran medion por krei neŭralan reton;
  • Ni kreis neŭralan reton por bilda rekono kaj trejnis ĝin;
  • Ni ripetis la retan trejnadon uzante la GPU kaj ricevis pliiĝon de rapideco.

Mi volonte respondos demandojn en la komentoj.

fonto: www.habr.com

Aldoni komenton