Вашата първа невронна мрежа на графичен процесор (GPU). Наръчник за начинаещи

Вашата първа невронна мрежа на графичен процесор (GPU). Наръчник за начинаещи
В тази статия ще ви кажа как да настроите среда за машинно обучение за 30 минути, да създадете невронна мрежа за разпознаване на изображения и след това да стартирате същата мрежа на графичен процесор (GPU).

Първо, нека дефинираме какво е невронна мрежа.

В нашия случай това е математически модел, както и неговото софтуерно или хардуерно изпълнение, изградено на принципа на организация и функциониране на биологични невронни мрежи - мрежи от нервни клетки на жив организъм. Тази концепция възниква, докато изучаваме процесите, протичащи в мозъка, и се опитваме да моделираме тези процеси.

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

От гледна точка на машинното обучение, невронната мрежа е специален случай на методите за разпознаване на образи, дискриминантния анализ, методите за клъстериране и други методи.

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

Първо, нека да разгледаме оборудването. Имаме нужда от сървър с инсталирана на него операционна система Linux. Оборудването, необходимо за работа със системи за машинно обучение, е доста мощно и в резултат на това скъпо. За тези, които нямат добра машина под ръка, препоръчвам да обърнат внимание на офертите на облачните доставчици. Можете бързо да наемете необходимия сървър и да плащате само за времето на използване.

В проекти, където е необходимо да се създадат невронни мрежи, използвам сървърите на един от руските облачни доставчици. Компанията предлага облачни сървъри под наем специално за машинно обучение с мощни Tesla V100 графични процесори (GPU) от NVIDIA. Накратко: използването на сървър с GPU може да бъде десетки пъти по-ефективно (бързо) в сравнение със сървър с подобна цена, който използва CPU (добре познатия централен процесор) за изчисления. Това се постига благодарение на характеристиките на архитектурата на GPU, която се справя по-бързо с изчисленията.

За да приложим примерите, описани по-долу, закупихме следния сървър за няколко дни:

  • SSD диск 150 GB
  • RAM 32 GB
  • Процесор Tesla V100 16 Gb с 4 ядра

Инсталирахме Ubuntu 18.04 на нашата машина.

Настройка на средата

Сега нека инсталираме всичко необходимо за работа на сървъра. Тъй като нашата статия е предимно за начинаещи, ще говоря за някои точки, които ще бъдат полезни за тях.

Голяма част от работата при настройка на среда се извършва чрез командния ред. Повечето потребители използват Windows като работна операционна система. Стандартната конзола в тази операционна система оставя много да се желае. Затова ще използваме удобен инструмент Cmder/. Изтеглете мини версията и стартирайте 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 конзола (горно меню - нов диалогов прозорец на конзолата), ще се свържем през порт 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 и да стартираме изпълнението (бутон Run):

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

Резултатът трябва да е нещо подобно:

Вашата първа невронна мрежа на графичен процесор (GPU). Наръчник за начинаещи

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

Създаване на невронна мрежа

Ще създадем невронна мрежа за разпознаване на изображения. Нека вземем това за основа ръководство.

Ще използваме публично достъпния набор от данни CIFAR10, за да обучим мрежата. Има класове: „самолет“, „кола“, „птица“, „котка“, „елен“, „куче“, „жаба“, „кон“, „кораб“, „камион“. Изображенията в CIFAR10 са 3x32x32, тоест 3-канални цветни изображения от 32x32 пиксела.

Вашата първа невронна мрежа на графичен процесор (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. Тази платформа вече е инсталирана на нашия сървър, който закупихме.

Нека първо определим нашия 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

Добавяне на нов коментар