Grafik ishlov berish blokidagi (GPU) birinchi neyron tarmog'ingiz. Yangi boshlanuvchilar uchun qo'llanma

Grafik ishlov berish blokidagi (GPU) birinchi neyron tarmog'ingiz. Yangi boshlanuvchilar uchun qo'llanma
Ushbu maqolada men sizga 30 daqiqada mashinani o'rganish muhitini qanday sozlashni, tasvirni aniqlash uchun neyron tarmoqni yaratishni va keyin xuddi shu tarmoqni grafik protsessorda (GPU) ishga tushirishni aytib beraman.

Birinchidan, neyron tarmoq nima ekanligini aniqlaymiz.

Bizning holatda, bu matematik model, shuningdek, biologik neyron tarmoqlarni - tirik organizmning asab hujayralari tarmoqlarini tashkil etish va ishlash tamoyiliga asoslangan dasturiy ta'minot yoki apparat timsoli. Bu kontseptsiya miyada sodir bo'ladigan jarayonlarni o'rganish va bu jarayonlarni modellashtirishga harakat qilish paytida paydo bo'lgan.

Neyron tarmoqlar so'zning odatiy ma'nosida dasturlashtirilmagan, ular o'qitilgan. O'rganish qobiliyati neyron tarmoqlarning an'anaviy algoritmlarga nisbatan asosiy afzalliklaridan biridir. Texnik jihatdan o'rganish neyronlar orasidagi bog'lanish koeffitsientlarini topishdan iborat. O'quv jarayonida neyron tarmoq kirish ma'lumotlari va chiqish ma'lumotlari o'rtasidagi murakkab bog'liqlikni aniqlashga, shuningdek umumlashtirishni amalga oshirishga qodir.

Mashinani o'rganish nuqtai nazaridan neyron tarmoq naqshni aniqlash usullari, diskriminant tahlili, klasterlash usullari va boshqa usullarning alohida holatidir.

uskunalar

Birinchidan, uskunani ko'rib chiqaylik. Bizga Linux operatsion tizimi o'rnatilgan server kerak. Mashinani o'rganish tizimlarini ishlatish uchun zarur bo'lgan uskunalar juda kuchli va natijada qimmat. Qo'lida yaxshi mashinaga ega bo'lmaganlar uchun bulutli provayderlarning takliflariga e'tibor berishni maslahat beraman. Siz kerakli serverni tezda ijaraga olishingiz va faqat foydalanish vaqti uchun to'lashingiz mumkin.

Neyron tarmoqlarni yaratish zarur bo'lgan loyihalarda men rus bulut provayderlaridan birining serverlaridan foydalanaman. Kompaniya NVIDIA’dan kuchli Tesla V100 grafik protsessorlari (GPU) bilan mashinani o‘rganish uchun bulutli serverlarni ijaraga taklif qiladi. Qisqasi: GPU bilan serverdan foydalanish hisob-kitoblar uchun protsessordan (taniqli markaziy protsessor) foydalanadigan shunga o'xshash narxdagi serverga nisbatan o'nlab marta samaraliroq (tezkor) bo'lishi mumkin. Bunga hisob-kitoblarni tezroq bajaradigan GPU arxitekturasining xususiyatlari tufayli erishiladi.

Quyida tasvirlangan misollarni amalga oshirish uchun biz bir necha kun davomida quyidagi serverni sotib oldik:

  • SSD disk 150 GB
  • RAM 32 GB
  • 100 yadroli Tesla V16 4 Gb protsessor

Biz Ubuntu 18.04 ni kompyuterimizga o'rnatdik.

Atrof muhitni sozlash

Endi serverda ishlash uchun zarur bo'lgan hamma narsani o'rnatamiz. Bizning maqolamiz birinchi navbatda yangi boshlanuvchilar uchun bo'lganligi sababli, men ular uchun foydali bo'lgan ba'zi fikrlar haqida gapiraman.

Atrof muhitni o'rnatishda ko'p ish buyruq qatori orqali amalga oshiriladi. Ko'pgina foydalanuvchilar o'zlarining operatsion tizimi sifatida Windows-dan foydalanadilar. Ushbu OSdagi standart konsol ko'p narsani orzu qiladi. Shuning uchun biz qulay vositadan foydalanamiz Cmder/. Mini versiyani yuklab oling va Cmder.exe faylini ishga tushiring. Keyin serverga SSH orqali ulanishingiz kerak:

ssh root@server-ip-or-hostname

Server-ip-yoki-hostname o'rniga serveringizning IP-manzilini yoki DNS nomini belgilang. Keyin parolni kiriting va agar ulanish muvaffaqiyatli bo'lsa, shunga o'xshash xabarni olishimiz kerak.

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

ML modellarini ishlab chiqish uchun asosiy til Python hisoblanadi. Va uni Linuxda ishlatish uchun eng mashhur platforma Anaconda.

Keling, uni serverimizga o'rnatamiz.

Biz mahalliy paket menejerini yangilashdan boshlaymiz:

sudo apt-get update

Curl o'rnating (buyruqlar qatori yordam dasturi):

sudo apt-get install curl

Anaconda Distribution-ning so'nggi versiyasini yuklab oling:

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

O'rnatishni boshlaylik:

bash Anaconda3-2019.10-Linux-x86_64.sh

O'rnatish jarayonida sizdan litsenziya shartnomasini tasdiqlash so'raladi. Muvaffaqiyatli o'rnatishdan keyin siz buni ko'rishingiz kerak:

Thank you for installing Anaconda3!

Endi ML modellarini ishlab chiqish uchun ko'plab ramkalar yaratilgan; biz eng mashhurlari bilan ishlaymiz: PyTorch и Tensor oqimi.

Ramkadan foydalanish rivojlanish tezligini oshirish va standart vazifalar uchun tayyor vositalardan foydalanish imkonini beradi.

Ushbu misolda biz PyTorch bilan ishlaymiz. Keling, uni o'rnatamiz:

conda install pytorch torchvision cudatoolkit=10.1 -c pytorch

Endi biz ML mutaxassislari uchun mashhur ishlab chiqish vositasi bo'lgan Jupyter Notebook-ni ishga tushirishimiz kerak. Bu sizga kod yozish va uning bajarilishi natijalarini darhol ko'rish imkonini beradi. Jupyter Notebook Anaconda-ga kiritilgan va bizning serverimizga allaqachon o'rnatilgan. Unga ish stolimiz tizimidan ulanishingiz kerak.

Buni amalga oshirish uchun avval 8080 portini ko'rsatuvchi serverda Jupyterni ishga tushiramiz:

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

Keyin, Cmder konsolida boshqa yorliqni ochib (yuqori menyu - Yangi konsol dialog oynasi) biz 8080 port orqali serverga SSH orqali ulanamiz:

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

Birinchi buyruqni kiritganimizda, bizga brauzerimizda Jupyterni ochish uchun havolalar taklif etiladi:

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

Keling, localhost:8080 uchun havoladan foydalanamiz. To'liq yo'ldan nusxa oling va uni shaxsiy kompyuteringizning mahalliy brauzerining manzil satriga joylashtiring. Jupyter Notebook ochiladi.

Keling, yangi daftar yaratamiz: New - Notebook - Python 3.

Keling, biz o'rnatgan barcha komponentlarning to'g'ri ishlashini tekshiramiz. Keling, misol PyTorch kodini Jupyter-ga kiritamiz va ijroni ishga tushiramiz (Run tugmasi):

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

Natija shunday bo'lishi kerak:

Grafik ishlov berish blokidagi (GPU) birinchi neyron tarmog'ingiz. Yangi boshlanuvchilar uchun qo'llanma

Agar sizda shunga o'xshash natija bo'lsa, biz hamma narsani to'g'ri sozladik va biz neyron tarmoqni rivojlantirishni boshlashimiz mumkin!

Neyron tarmog'ini yaratish

Tasvirni aniqlash uchun neyron tarmoq yaratamiz. Keling, buni asos qilib olaylik etakchilik.

Tarmoqni o'qitish uchun biz hammaga ochiq CIFAR10 ma'lumotlar to'plamidan foydalanamiz. Uning sinflari mavjud: "samolyot", "avtomobil", "qush", "mushuk", "kiyik", "it", "qurbaqa", "ot", "kema", "yuk mashinasi". CIFAR10-dagi tasvirlar 3x32x32, ya'ni 3x32 pikselli 32 kanalli rangli tasvirlar.

Grafik ishlov berish blokidagi (GPU) birinchi neyron tarmog'ingiz. Yangi boshlanuvchilar uchun qo'llanma
Ish uchun biz PyTorch tomonidan tasvirlar bilan ishlash uchun yaratilgan paketdan foydalanamiz - torchvision.

Biz quyidagi bosqichlarni tartibda bajaramiz:

  • O'quv va test ma'lumotlar to'plamlarini yuklash va normallashtirish
  • Neyron tarmoq ta'rifi
  • Trening ma'lumotlari bo'yicha tarmoq treningi
  • Sinov ma'lumotlari bo'yicha tarmoq sinovi
  • Keling, GPU yordamida trening va testlarni takrorlaymiz

Quyidagi barcha kodlarni Jupyter Notebook da bajaramiz.

CIFAR10ni yuklash va normallashtirish

Jupyter-da quyidagi kodni nusxalash va ishga tushirish:


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

Javob quyidagicha bo'lishi kerak:

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

Sinov uchun bir nechta o'quv rasmlarini ko'rsatamiz:


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

Grafik ishlov berish blokidagi (GPU) birinchi neyron tarmog'ingiz. Yangi boshlanuvchilar uchun qo'llanma

Neyron tarmoq ta'rifi

Keling, avval tasvirni aniqlash uchun neyron tarmoq qanday ishlashini ko'rib chiqaylik. Bu oddiy nuqtadan nuqtaga tarmoq. U kirish ma'lumotlarini oladi, uni bir necha qatlamlardan birma-bir o'tkazadi va nihoyat chiqish ma'lumotlarini ishlab chiqaradi.

Grafik ishlov berish blokidagi (GPU) birinchi neyron tarmog'ingiz. Yangi boshlanuvchilar uchun qo'llanma

Keling, bizning muhitimizda shunga o'xshash tarmoq yarataylik:


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

Shuningdek, biz yo'qotish funktsiyasi va optimallashtiruvchini aniqlaymiz


import torch.optim as optim

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

Trening ma'lumotlari bo'yicha tarmoq treningi

Neyron tarmog'imizni mashq qilishni boshlaylik. E'tibor bering, ushbu kodni ishga tushirgandan so'ng, ish tugaguncha biroz kutishingiz kerak bo'ladi. Menga 5 daqiqa vaqt ketdi. Tarmoqni o'rgatish uchun vaqt kerak bo'ladi.

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

Biz quyidagi natijani olamiz:

Grafik ishlov berish blokidagi (GPU) birinchi neyron tarmog'ingiz. Yangi boshlanuvchilar uchun qo'llanma

Biz o'qitilgan modelimizni saqlaymiz:

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

Sinov ma'lumotlari bo'yicha tarmoq sinovi

Biz tarmoqni o'quv ma'lumotlari to'plamidan foydalangan holda o'rgatganmiz. Ammo biz tarmoq umuman biror narsani o'rganganligini tekshirishimiz kerak.

Biz buni neyron tarmoq chiqaradigan sinf yorlig'ini bashorat qilish va uning to'g'ri yoki yo'qligini tekshirish orqali sinab ko'ramiz. Agar bashorat to'g'ri bo'lsa, biz namunani to'g'ri bashoratlar ro'yxatiga qo'shamiz.
Keling, test to'plamidan rasmni ko'rsatamiz:

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

Grafik ishlov berish blokidagi (GPU) birinchi neyron tarmog'ingiz. Yangi boshlanuvchilar uchun qo'llanma

Endi neyron tarmoqdan ushbu rasmlarda nima borligini aytib berishini so'raymiz:


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

Grafik ishlov berish blokidagi (GPU) birinchi neyron tarmog'ingiz. Yangi boshlanuvchilar uchun qo'llanma

Natijalar juda yaxshi ko'rinadi: tarmoq to'rtta rasmdan uchtasini to'g'ri aniqladi.

Keling, tarmoq butun ma'lumotlar to'plamida qanday ishlashini ko'rib chiqaylik.


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

Grafik ishlov berish blokidagi (GPU) birinchi neyron tarmog'ingiz. Yangi boshlanuvchilar uchun qo'llanma

Tarmoq nimanidir biladi va ishlayotganga o'xshaydi. Agar u tasodifiy sinflarni aniqlasa, aniqlik 10% ni tashkil qiladi.

Keling, tarmoq qaysi sinflarni yaxshiroq aniqlashini ko'rib chiqaylik:

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

Grafik ishlov berish blokidagi (GPU) birinchi neyron tarmog'ingiz. Yangi boshlanuvchilar uchun qo'llanma

Aftidan, tarmoq avtomobillar va kemalarni aniqlashda eng yaxshisi: 71% aniqlik.

Shunday qilib, tarmoq ishlaydi. Endi uning ishini grafik protsessorga (GPU) o'tkazishga harakat qilaylik va qanday o'zgarishlarni ko'ramiz.

GPU-da neyron tarmoqni o'rgatish

Birinchidan, men CUDA nima ekanligini qisqacha tushuntiraman. CUDA (Compute Unified Device Architecture) - NVIDIA tomonidan grafik ishlov berish birliklarida (GPU) umumiy hisoblash uchun ishlab chiqilgan parallel hisoblash platformasi. CUDA yordamida ishlab chiquvchilar GPU quvvatidan foydalangan holda hisoblash ilovalarini keskin tezlashtirishi mumkin. Ushbu platforma allaqachon biz sotib olgan serverimizga o'rnatilgan.

Keling, birinchi navbatda GPU-ni birinchi ko'rinadigan cuda qurilmasi sifatida aniqlaylik.

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 )

Grafik ishlov berish blokidagi (GPU) birinchi neyron tarmog'ingiz. Yangi boshlanuvchilar uchun qo'llanma

Tarmoqni GPUga yuborish:

net.to(device)

Shuningdek, biz GPUga har bir qadamda kirish va maqsadlarni yuborishimiz kerak bo'ladi:

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

Keling, tarmoqni GPU-da qayta o'rgatamiz:

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

Bu safar tarmoq treningi taxminan 3 daqiqa davom etdi. Eslatib o'tamiz, an'anaviy protsessorda xuddi shu bosqich 5 daqiqa davom etgan. Farqi muhim emas, bu bizning tarmog'imiz unchalik katta emasligi sababli sodir bo'ladi. Trening uchun katta massivlardan foydalanganda GPU tezligi va an'anaviy protsessor o'rtasidagi farq ortadi.

Hammasi shu kabi ko'rinadi. Biz nimaga erishdik:

  • Biz GPU nima ekanligini ko'rib chiqdik va u o'rnatilgan serverni tanladik;
  • Biz neyron tarmoqni yaratish uchun dasturiy muhitni o'rnatdik;
  • Biz tasvirni aniqlash uchun neyron tarmog'ini yaratdik va uni o'rgatdi;
  • Biz GPU yordamida tarmoq treningini takrorladik va tezlikni oshirdik.

Izohlarda savollarga javob berishdan xursand bo'laman.

Manba: www.habr.com

a Izoh qo'shish