Графикалық өңдеу блогындағы (GPU) бірінші нейрондық желіңіз. Жаңадан бастаушыларға арналған нұсқаулық

Графикалық өңдеу блогындағы (GPU) бірінші нейрондық желіңіз. Жаңадан бастаушыларға арналған нұсқаулық
Бұл мақалада мен сізге 30 минут ішінде машиналық оқыту ортасын қалай орнату керектігін, кескінді тану үшін нейрондық желіні құруды және сол желіні графикалық процессорда (GPU) іске қосуды айтамын.

Алдымен нейрондық желі дегеніміз не екенін анықтайық.

Біздің жағдайда бұл математикалық модель, сондай-ақ оның бағдарламалық немесе аппараттық нұсқасы, биологиялық нейрондық желілерді - тірі ағзаның жүйке жасушаларының желілерін ұйымдастыру және жұмыс істеу принципіне негізделген. Бұл тұжырымдама мида болып жатқан процестерді зерттеп, осы процестерді модельдеуге тырысқанда пайда болды.

Нейрондық желілер сөздің әдеттегі мағынасында бағдарламаланбайды, олар оқытылады. Үйрену қабілеті дәстүрлі алгоритмдерге қарағанда нейрондық желілердің басты артықшылықтарының бірі болып табылады. Техникалық тұрғыдан оқыту нейрондар арасындағы байланыс коэффициенттерін табудан тұрады. Оқыту процесінде нейрондық желі кіріс деректері мен шығыс деректері арасындағы күрделі тәуелділіктерді анықтауға, сондай-ақ жалпылауды орындауға қабілетті.

Машиналық оқыту тұрғысынан нейрондық желі үлгіні тану әдістерінің, дискриминантты талдаудың, кластерлеу әдістерінің және басқа әдістердің ерекше жағдайы болып табылады.

Жабдық

Алдымен жабдықты қарастырайық. Бізге Linux операциялық жүйесі орнатылған сервер қажет. Машиналық оқыту жүйелерін басқаруға қажетті жабдық жеткілікті қуатты және нәтижесінде қымбат. Қолында жақсы машинасы жоқ адамдар үшін бұлтты провайдерлердің ұсыныстарына назар аударуды ұсынамын. Қажетті серверді жылдам жалға алуға және тек пайдалану уақыты үшін төлеуге болады.

Нейрондық желілерді құру қажет жобаларда мен ресейлік бұлттық провайдерлердің бірінің серверлерін қолданамын. Компания NVIDIA қуатты Tesla V100 графикалық процессорларымен (GPU) машиналық оқыту үшін арнайы жалға алу үшін бұлттық серверлерді ұсынады. Қысқаша айтқанда: GPU бар серверді пайдалану есептеулер үшін CPU (белгілі орталық өңдеу блогы) пайдаланатын ұқсас құны бар сервермен салыстырғанда ондаған есе тиімдірек (жылдам) болуы мүмкін. Бұған есептеулерді тезірек орындайтын GPU архитектурасының ерекшеліктері арқасында қол жеткізілді.

Төменде сипатталған мысалдарды орындау үшін біз бірнеше күн бойы келесі серверді сатып алдық:

  • SSD дискі 150 ГБ
  • ЖЖҚ 32 ГБ
  • 100 ядросы бар Tesla V16 4 Гб процессоры

Біз құрылғымызға Ubuntu 18.04 орнаттық.

Ортаны орнату

Енді серверде жұмыс істеуге қажеттінің барлығын орнатайық. Біздің мақала ең алдымен жаңадан бастаушыларға арналғандықтан, мен оларға пайдалы болатын кейбір тармақтар туралы айтатын боламын.

Ортаны орнату кезінде көп жұмыс пәрмен жолы арқылы орындалады. Пайдаланушылардың көпшілігі Windows жүйесін жұмыс істейтін операциялық жүйе ретінде пайдаланады. Бұл ОЖ-дағы стандартты консоль көп нәрсені қажет етеді. Сондықтан біз ыңғайлы құралды қолданамыз Cmder/. Шағын нұсқаны жүктеп алып, Cmder.exe файлын іске қосыңыз. Содан кейін серверге SSH арқылы қосылу керек:

ssh root@server-ip-or-hostname

Server-ip-немесе-хост атауының орнына серверіңіздің 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

Енді біз ML мамандары үшін танымал әзірлеу құралы болып табылатын Jupyter Notebook-ті іске қосуымыз керек. Ол кодты жазуға және оның орындалу нәтижелерін бірден көруге мүмкіндік береді. Jupyter Notebook Anaconda бағдарламасына кіреді және серверде орнатылған. Оған біздің жұмыс үстелі жүйемізден қосылу керек.

Ол үшін алдымен 8080 портын көрсететін серверде Jupyter іске қосылады:

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

Әрі қарай, Cmder консолінде басқа қойындыны ашамыз (жоғарғы мәзір - Жаңа консоль диалогы) біз 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 ашылады.

Жаңа жазу кітапшасын жасайық: Жаңа - ноутбук - Python 3.

Біз орнатқан барлық компоненттердің дұрыс жұмысын тексерейік. PyTorch мысалын Jupyter-ге енгізіп, орындауды іске қосыңыз (Орындау түймесі):

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

Нәтиже келесідей болуы керек:

Графикалық өңдеу блогындағы (GPU) бірінші нейрондық желіңіз. Жаңадан бастаушыларға арналған нұсқаулық

Егер сізде ұқсас нәтиже болса, біз барлығын дұрыс конфигурацияладық және нейрондық желіні дамытуды бастай аламыз!

Нейрондық желіні құру

Біз кескінді тану үшін нейрондық желіні жасаймыз. Осыны негізге алайық көшбасшылық.

Біз желіні оқыту үшін жалпыға қолжетімді CIFAR10 деректер жинағын пайдаланамыз. Оның кластары бар: «ұшақ», «автокөлік», «құс», «мысық», «бұғы», «ит», «бақа», «ат», «кеме», «жүк көлігі». CIFAR10-дағы кескіндер 3x32x32, яғни 3x32 пиксельді 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) — графикалық өңдеу блоктарында (GPU) жалпы есептеулер үшін NVIDIA әзірлеген параллельді есептеу платформасы. CUDA көмегімен әзірлеушілер GPU қуатын пайдалану арқылы есептеу қосымшаларын күрт жеделдете алады. Бұл платформа біз сатып алған серверде орнатылған.

Алдымен 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 көмегімен желілік оқытуды қайталап, жылдамдықты арттырдық.

Түсініктемелерде сұрақтарға жауап беруге қуаныштымын.

Ақпарат көзі: www.habr.com

пікір қалдыру