Ваша першая нейронавая сетка на графічным працэсары (GPU). Кіраўніцтва для пачаткоўцаў

Ваша першая нейронавая сетка на графічным працэсары (GPU). Кіраўніцтва для пачаткоўцаў
У гэтым артыкуле я распавяду як за 30 хвілін наладзіць асяроддзе для машыннага навучання, стварыць нейронавую сетку для распазнання малюнкаў a потым запусціць тую ж сетку на графічным працэсары (GPU).

Для пачатку вызначым што такое нейронавая сетка.

У нашым выпадку гэта матэматычная мадэль, а таксама яе праграмнае ці апаратнае ўвасабленне, пабудаваная па прынцыпе арганізацыі і функцыянавання біялагічных нейронавых сетак - сетак нервовых клетак жывога арганізма. Гэта паняцце ўзнікла пры вывучэнні працэсаў, якія праходзяць у мозгу, і пры спробе змадэляваць гэтыя працэсы.

Нейронныя сеткі не праграмуюцца ў звыклым сэнсе гэтага слова, яны вучацца. Магчымасць навучання - адна з галоўных пераваг нейронавых сетак перад традыцыйнымі алгарытмамі. Тэхнічна навучанне заключаецца ў знаходжанні каэфіцыентаў сувязей паміж нейронамі. У працэсе навучання нейронавая сетка здольная выяўляць складаныя залежнасці паміж уваходнымі дадзенымі і выходнымі, а таксама выконваць абагульненне.

З пункту гледжання машыннага навучання, нейронавая сетка ўяўляе сабой прыватны выпадак метадаў распазнання выяў, дыскрымінантнага аналізу, метадаў кластарызацыі і іншых метадаў.

Абсталяванне

Спачатку разбяромся з абсталяваннем. Нам неабходны сервер з усталяванай на ім аперацыйнай сістэмай Linux. Абсталяванне для працы сістэм машыннага навучання патрабуецца дастаткова магутнае і як следства дарагое. Тым, у каго няма пад рукой добрай машыны, рэкамендую звярнуць увагу на прапанову хмарных правайдэраў. Неабходны сервер можна атрымаць у арэнду хутка і плаціць толькі за час выкарыстання.

У праектах, дзе неабходна стварэнне нейронавых сетак я выкарыстоўваю сервера аднаго з расійскіх хмарных правайдэраў. Кампанія прапануе ў арэнду хмарныя серверы спецыяльна для машыннага навучання з магутнымі графічнымі працэсарамі (GPU) Tesla V100 ад кампаніі NVIDIA. Калі сцісла: выкарыстанне сервера з GPU можа быць у дзясяткі разоў быць больш эфектыўным (хуткім) у параўнанні з аналагічным па кошце серверам дзе для вылічэнняў выкарыстоўваецца CPU (усім добра знаёмы цэнтральны працэсар). Гэта дасягаецца за рахунак асаблівасцяў архітэктуры GPU, якая хутчэй спраўляецца з разлікамі.

Для выканання прыкладаў апісаных далей, мы набылі на некалькі дзён такі сервер:

  • SSD дыск 150 ГБ
  • АЗП 32 ГБ
  • Працэсар Tesla V100 16 Gb з 4-ма ядрамі

На машыну нам устанавілі Ubuntu 18.04.

Усталёўваны асяроддзе

Цяпер усталюем на сервер усё неабходнае для працы. Паколькі наш артыкул у першую чаргу для пачаткоўцаў, буду расказваць у ім пра некаторыя моманты, якія спатрэбяцца менавіта ім.

Вельмі шмат працы пры наладзе асяроддзя выконваецца праз камандны радок. Большасць з карыстачоў у якасці працоўнай АС выкарыстоўваюць Windows. Стандартная кансоль у гэтай АС пакідае жадаць лепшага. Таму мы будзем выкарыстоўваць зручны інструмент Cmder/. Спампоўваем mini версію і запускаем Cmder.exe. Далей неабходна падключыцца да сервера па пратаколе SSH:

ssh root@server-ip-or-hostname

Замест server-ip-or-hostname паказваеце IP адрас ці DNS імя вашага сервера. Далей уводзім пароль і пры паспяховым падлучэнні мы павінны атрымаць прыкладна такое паведамленне.

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

Асноўнай мовай для распрацоўкі ML мадэляў з'яўляецца Python. А найболей папулярнай платформай для яго выкарыстанне па Linux з'яўляецца Анаконда.

Усталюем яе на наш сервер.

Пачынаем з абнаўлення лакальнага мэнэджара пакетаў:

sudo apt-get update

Усталёўваны curl (службовая праграма каманднага радка):

sudo apt-get install curl

Спампоўваем апошнюю версію Anaconda Distribution:

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

Запускаем ўстаноўку:

bash Anaconda3-2019.10-Linux-x86_64.sh

У працэсе ўстаноўкі неабходна будзе пацвердзіць ліцэнзійную дамову. Пры паспяховай усталёўцы вы павінны будзеце ўбачыць гэта:

Thank you for installing Anaconda3!

Для распрацоўкі ML мадэляў зараз створана мноства фрэймворкаў, мы працуем з найболей папулярнымі: PyTorch и Тэнзорны паток.

Выкарыстанне фрэймворка дазваляе павялічыць хуткасць распрацоўкі і выкарыстоўваць ужо гатовыя прылады для стандартных задач.

У гэтым прыкладзе будзем працаваць з PyTorch. Усталюем яго:

conda install pytorch torchvision cudatoolkit=10.1 -c pytorch

Зараз нам неабходна запусціць Jupyter Notebook - папулярны ў ML спецыялістаў інструмент распрацоўкі. Ён дазваляе пісаць код і адразу бачыць вынікі яго выканання. Jupyter Notebook уваходзіць у склад Anaconda і ўжо ўсталяваны на нашым серверы. Неабходна падключыцца да яго з нашай настольнай сістэмы.

Для гэтага мы спачатку запусцім Jupyter на серверы паказаўшы порт 8080:

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

Далей адкрыўшы ў нашай кансолі Cmder яшчэ адну ўкладку (верхняе меню – New console dialog) падлучымся па порце 8080 да сервера праз SSH:

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

Пры ўводзе першай каманды нам будзе прапанаваны спасылкі для адкрыцця 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

Скарыстаемся спасылкай на localhost:8080. Скапіюйце поўны шлях і ўстаўце ў адрасны радок лакальнага браўзэра вашага ПК. Адкрыецца Jupyter Notebook.

Створым новы наўтбук: New - Notebook - Python 3.

Праверым карэктную працу ўсіх кампанентаў якія мы ўстанавілі. Увядзем у Jupyter прыклад кода PyTorch і запусцім выкананне (кнопка Run):

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

Вынік павінен быць прыкладна такім:

Ваша першая нейронавая сетка на графічным працэсары (GPU). Кіраўніцтва для пачаткоўцаў

Калі ў вас аналагічны вынік - значыць мы ўсё наладзілі правільна і можам прыступаць да распрацоўкі нейронавай сеткі!

Ствараем нейронавую сетку

Будзем ствараць нейронавую сетку для распазнання малюнкаў. За аснову возьмем гэта кіраўніцтва.

Для трэніроўкі сеткі мы будзем выкарыстоўваць агульнадаступны набор даных CIFAR10. У яго ёсць класы: "самалёт", "аўтамабіль", "птушка", "котка", "алень", "сабака", "жаба", "конь", "карабель", "грузавік". Выявы ў CIFAR10 маюць памер 3x32x32, гэта значыць 3-канальныя каляровыя выявы памерам 32×32 пікселяў.

Ваша першая нейронавая сетка на графічным працэсары (GPU). Кіраўніцтва для пачаткоўцаў
Для працы мы будзем выкарыстоўваць створаны PyTorch пакет для працы з выявамі - torchvision.

Мы зробім наступныя крокі па парадку:

  • Загрузка і нармалізацыя набораў навучальных і тэставых даных
  • Вызначэнне нейронавай сеткі
  • Трэніроўка сеткі на трэніровачных дадзеных
  • Тэставанне сеткі на тэставых дадзеных
  • Паўторым трэніроўку і тэсціраванне з выкарыстаннем GPU

Увесь прыведзены ніжэй код мы будзем выконваць у Jupyter Notebook.

Загрузка і нармалізацыя CIFAR10

Скапіюйце і выканайце ў 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')

Адказ павінен быць такі:

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

Вывядзем некалькі трэніровачных вобразаў для праверкі:


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

Ваша першая нейронавая сетка на графічным працэсары (GPU). Кіраўніцтва для пачаткоўцаў

Вызначэнне нейронавай сеткі

Разгледзім спачатку як працуе нейронавая сетка па распазнанні малюнкаў. Гэта простая сетка прамой сувязі. Ён прымае ўваходныя дадзеныя, прапускае іх праз некалькі пластоў адзін за іншым, а затым, нарэшце, выдае выходныя дадзеныя.

Ваша першая нейронавая сетка на графічным працэсары (GPU). Кіраўніцтва для пачаткоўцаў

Створым падобную сетку ў нашым асяроддзі:


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

Азначальны гэтак жа функцыю страт і аптымізатар


import torch.optim as optim

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

Трэніроўка сеткі на трэніровачных дадзеных

Пачынаем трэніроўку нашай нейронавай сеткі. Звяртаю ўвагу, што пасля таго як вы запусціце на выкананне гэты код, трэба будзе пачакаць некаторы час да завяршэння працы. У мяне гэта заняло 5 хвіл. Для навучанне сеткі патрэбны час.

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

Атрымаем такі вынік:

Ваша першая нейронавая сетка на графічным працэсары (GPU). Кіраўніцтва для пачаткоўцаў

Захоўваем нашу навучаную мадэль:

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

Тэставанне сеткі на тэставых дадзеных

Мы навучылі сетку выкарыстоўваю набор навучальных дадзеных. Але нам трэба праверыць, ці навучылася сетка наогул нечаму.

Мы праверым гэта, прадказаўшы пазнаку класа, якую выводзіць нейронавая сетка, і праверыўшы яе на прадмет праўдзівасці. Калі прагноз правільны, мы дадаем ўзор у спіс правільных прагнозаў.
Давайце пакажам малюнак з тэставага набору:

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

Ваша першая нейронавая сетка на графічным працэсары (GPU). Кіраўніцтва для пачаткоўцаў

Зараз папросім нейронавую сетку паведаміць нам што на гэтых карцінках:


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

Ваша першая нейронавая сетка на графічным працэсары (GPU). Кіраўніцтва для пачаткоўцаў

Вынікі здаюцца даволі добрымі: сетка вызначыла правільна тры карцінкі з чатырох.

Давайце паглядзім, як сетка працуе ва ўсім наборы дадзеных.


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

Ваша першая нейронавая сетка на графічным працэсары (GPU). Кіраўніцтва для пачаткоўцаў

Падобна на тое сетка нешта ведае і працуе. Калі б ён вызначала класы наўздагад, то дакладнасць была б 10%.

Цяпер паглядзім якія класы сетка вызначае лепш:

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

Ваша першая нейронавая сетка на графічным працэсары (GPU). Кіраўніцтва для пачаткоўцаў

Выглядае што лепш за ўсё сетка вызначае аўтамабілі і караблі: 71% дакладнасці.

Такім чынам сетка працуе. Цяпер паспрабуем перанесці яе працу на графічны працэсар (GPU) і паглядзі што зменіцца.

Трэніроўка нейронавай сеткі на GPU

Спачатку растлумачу сцісла што такое CUDA. CUDA (Compute Unified Device Architecture) – платформа паралельных вылічэнняў, распрацаваная NVIDIA, для агульных вылічэнняў на графічных працэсарах (GPU). З дапамогай CUDA распрацоўшчыкі могуць значна паскорыць вылічальныя прыкладанні, выкарыстоўваючы магчымасці графічных працэсараў. На нашым сэрвэры, які мы набылі, дадзеная платформа ўжо ўсталявана.

Давайце спачатку вызначым наша GPU як першая бачная прылада 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 )

Ваша першая нейронавая сетка на графічным працэсары (GPU). Кіраўніцтва для пачаткоўцаў

Адпраўляем сетку на GPU:

net.to(device)

Гэтак жа нам давядзецца адпраўляць уваходы і мэты на кожным кроку і ў GPU:

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

Запусцім паўторнае навучанне сеткі ўжо на 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')

На гэты раз навучанне сеткі працягвалася па часе каля 3 хвілін. Нагадаем, што той жа этап на звычайным працэсары доўжыўся 5 хвілін. Розніца не істотная, гэта адбываецца таму, што наша сетка не такая вялікая. Пры выкарыстанні вялікіх масіваў для навучання розніца паміж хуткасцю працы GPU і традыцыйнага працэсара будзе ўзрастаць.

На гэтым здаецца ўсё. Што нам удалося зрабіць:

  • Мы разгледзелі, што такое GPU і выбралі сервер на якім ён усталяваны;
  • Мы наладзілі праграмнае асяроддзе для стварэння нейронавай сеткі;
  • Мы стварылі нейронавую сетку для распазнання малюнкаў і навучылі яе;
  • Мы паўтарылі навучанне сеткі з выкарыстаннем GPU і атрымалі прырост у хуткасці.

Буду рады адказаць на пытанні ў каментарах.

Крыніца: habr.com

Дадаць каментар