Ваша прва неуронска мрежа на јединици за графичку обраду (ГПУ). Водич за почетнике

Ваша прва неуронска мрежа на јединици за графичку обраду (ГПУ). Водич за почетнике
У овом чланку ћу вам рећи како да подесите окружење за машинско учење за 30 минута, креирате неуронску мрежу за препознавање слика, а затим покренете исту мрежу на графичком процесору (ГПУ).

Прво, хајде да дефинишемо шта је неуронска мрежа.

У нашем случају, ово је математички модел, као и његово софтверско или хардверско оличење, изграђено на принципу организације и функционисања биолошких неуронских мрежа - мрежа нервних ћелија живог организма. Овај концепт је настао током проучавања процеса који се дешавају у мозгу и покушаја да се ти процеси моделирају.

Неуронске мреже нису програмиране у уобичајеном смислу те речи, оне су обучене. Способност учења је једна од главних предности неуронских мрежа у односу на традиционалне алгоритме. Технички, учење се састоји од проналажења коефицијената веза између неурона. Током процеса обуке, неуронска мрежа је у стању да идентификује сложене зависности између улазних и излазних података, као и да изврши генерализацију.

Са становишта машинског учења, неуронска мрежа је посебан случај метода препознавања образаца, дискриминантне анализе, метода груписања и других метода.

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

Прво, погледајмо опрему. Потребан нам је сервер са инсталираним Линук оперативним системом. Опрема потребна за рад система машинског учења је прилично моћна и, као резултат, скупа. За оне који немају добру машину при руци, препоручујем да обрате пажњу на понуде клауд провајдера. Можете брзо изнајмити тражени сервер и платити само време коришћења.

У пројектима где је потребно креирати неуронске мреже користим сервере једног од руских провајдера облака. Компанија нуди сервере у облаку за изнајмљивање посебно за машинско учење са моћним Тесла В100 графичким процесорима (ГПУ) компаније НВИДИА. Укратко: коришћење сервера са ГПУ-ом може бити десетине пута ефикасније (брже) у поређењу са сервером сличне цене који користи ЦПУ (познату централну процесорску јединицу) за прорачуне. Ово се постиже захваљујући карактеристикама ГПУ архитектуре, која се брже носи са прорачунима.

Да бисмо имплементирали доле описане примере, купили смо следећи сервер на неколико дана:

  • ССД диск 150 ГБ
  • РАМ 32 ГБ
  • Тесла В100 16 Гб процесор са 4 језгра

Инсталирали смо Убунту 18.04 на нашу машину.

Постављање окружења

Сада инсталирајмо све што је потребно за рад на серверу. Пошто је наш чланак првенствено за почетнике, говорићу о неким тачкама које ће им бити корисне.

Велики део посла приликом подешавања окружења обавља се преко командне линије. Већина корисника користи Виндовс као оперативни ОС. Стандардна конзола у овом ОС-у оставља много да се пожели. Због тога ћемо користити згодан алат Цмдер/. Преузмите мини верзију и покрените Цмдер.еке. Затим се морате повезати са сервером преко ССХ:

ssh root@server-ip-or-hostname

Уместо сервер-ип-ор-хостнаме, наведите ИП адресу или ДНС име вашег сервера. Затим унесите лозинку и ако је веза успешна, требало би да добијемо поруку сличну овој.

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

Главни језик за развој МЛ модела је Питхон. А најпопуларнија платформа за његову употребу на Линуку је Анаконда.

Хајде да га инсталирамо на наш сервер.

Почињемо ажурирањем локалног менаџера пакета:

sudo apt-get update

Инсталирајте цурл (услужни програм командне линије):

sudo apt-get install curl

Преузмите најновију верзију Анацонда Дистрибутион:

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!

Многи оквири су сада креирани за развој МЛ модела; радимо са најпопуларнијим: ПиТорцх и Тенсорфлов.

Коришћење оквира вам омогућава да повећате брзину развоја и користите готове алате за стандардне задатке.

У овом примеру ћемо радити са ПиТорцх-ом. Хајде да га инсталирамо:

conda install pytorch torchvision cudatoolkit=10.1 -c pytorch

Сада морамо да покренемо Јупитер Нотебоок, популаран развојни алат за стручњаке за МЛ. Омогућава вам да напишете код и одмах видите резултате његовог извршења. Јупитер Нотебоок је укључен уз Анацонда и већ је инсталиран на нашем серверу. Морате да се повежете на њега са нашег десктоп система.

Да бисмо то урадили, прво ћемо покренути Јупитер на серверу који наводи порт 8080:

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

Затим, отварајући још једну картицу у нашој Цмдер конзоли (горњи мени - дијалог Нова конзола) ми ћемо се повезати преко порта 8080 на сервер преко ССХ:

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

Када унесемо прву команду, биће нам понуђене везе за отварање Јупитер-а у нашем претраживачу:

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

Хајде да користимо везу за лоцалхост:8080. Копирајте пуну путању и налепите је у адресну траку локалног претраживача вашег рачунара. Јупитер Нотебоок ће се отворити.

Хајде да направимо нову бележницу: Ново - Бележница - Питхон 3.

Хајде да проверимо исправан рад свих компоненти које смо инсталирали. Хајде да унесемо пример ПиТорцх кода у Јупитер и покренемо извршење (дугме Рун):

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

Резултат би требао бити отприлике овако:

Ваша прва неуронска мрежа на јединици за графичку обраду (ГПУ). Водич за почетнике

Ако имате сличан резултат, онда смо све исправно конфигурисали и можемо да почнемо да развијамо неуронску мрежу!

Креирање неуронске мреже

Направићемо неуронску мрежу за препознавање слика. Узмимо ово као основу вођство.

Користићемо јавно доступни скуп података ЦИФАР10 за обуку мреже. Има класе: „авион”, „аутомобил”, „птица”, „мачка”, „јелен”, „пас”, „жаба”, „коњ”, „брод”, „камион”. Слике у ЦИФАР10 су 3к32к32, односно 3-каналне слике у боји од 32к32 пиксела.

Ваша прва неуронска мрежа на јединици за графичку обраду (ГПУ). Водич за почетнике
За рад ћемо користити пакет који је креирао ПиТорцх за рад са сликама - торцхвисион.

Урадићемо следеће кораке по редоследу:

  • Учитавање и нормализација скупова података за обуку и тестирање
  • Дефиниција неуронске мреже
  • Мрежна обука о подацима о обуци
  • Мрежно тестирање на тестним подацима
  • Поновимо обуку и тестирање користећи ГПУ

Извршићемо сав доњи код у Јупитер нотебоок-у.

Учитавање и нормализација ЦИФАР10

Копирајте и покрените следећи код у Јупитер-у:


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

Ваша прва неуронска мрежа на јединици за графичку обраду (ГПУ). Водич за почетнике

Дефиниција неуронске мреже

Хајде да прво размотримо како функционише неуронска мрежа за препознавање слика. Ово је једноставна мрежа од тачке до тачке. Узима улазне податке, прослеђује их кроз неколико слојева један по један, а затим коначно производи излазне податке.

Ваша прва неуронска мрежа на јединици за графичку обраду (ГПУ). Водич за почетнике

Хајде да направимо сличну мрежу у нашем окружењу:


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

Добијамо следећи резултат:

Ваша прва неуронска мрежа на јединици за графичку обраду (ГПУ). Водич за почетнике

Ми чувамо наш обучени модел:

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

Ваша прва неуронска мрежа на јединици за графичку обраду (ГПУ). Водич за почетнике

Сада замолимо неуронску мрежу да нам каже шта је на овим сликама:


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

Ваша прва неуронска мрежа на јединици за графичку обраду (ГПУ). Водич за почетнике

Резултати изгледају прилично добри: мрежа је тачно идентификовала три од четири слике.

Хајде да видимо како мрежа функционише у целом скупу података.


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

Ваша прва неуронска мрежа на јединици за графичку обраду (ГПУ). Водич за почетнике

Изгледа да мрежа нешто зна и ради. Када би насумично одредио класе, тачност би била 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]))

Ваша прва неуронска мрежа на јединици за графичку обраду (ГПУ). Водич за почетнике

Чини се да је мрежа најбоља у идентификацији аутомобила и бродова: тачност од 71%.

Дакле, мрежа ради. Сада покушајмо да пренесемо његов рад на графички процесор (ГПУ) и видимо шта се мења.

Обука неуронске мреже на ГПУ-у

Прво ћу укратко објаснити шта је ЦУДА. ЦУДА (Цомпуте Унифиед Девице Арцхитецтуре) је платформа за паралелно рачунарство коју је развила НВИДИА за опште рачунарство на графичким процесорским јединицама (ГПУ). Са ЦУДА-ом, програмери могу драматично да убрзају рачунарске апликације користећи снагу ГПУ-а. Ова платформа је већ инсталирана на нашем серверу који смо купили.

Хајде да прво дефинишемо наш ГПУ као први видљиви цуда уређај.

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 )

Ваша прва неуронска мрежа на јединици за графичку обраду (ГПУ). Водич за почетнике

Слање мреже на ГПУ:

net.to(device)

Такође ћемо морати да шаљемо улазе и циљеве на сваком кораку ГПУ-у:

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

Хајде да поново обучимо мрежу на ГПУ:

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 минута. Разлика није значајна, то се дешава зато што наша мрежа није тако велика. Када користите велике низове за обуку, разлика између брзине ГПУ-а и традиционалног процесора ће се повећати.

Чини се да је то све. Шта смо успели да урадимо:

  • Погледали смо шта је ГПУ и изабрали сервер на коме је инсталиран;
  • Поставили смо софтверско окружење за креирање неуронске мреже;
  • Направили смо неуронску мрежу за препознавање слика и обучили је;
  • Поновили смо мрежну обуку користећи ГПУ и добили смо повећање брзине.

Радо ћу одговорити на питања у коментарима.

Извор: ввв.хабр.цом

Додај коментар