График боловсруулах нэгж (GPU) дээрх таны анхны мэдрэлийн сүлжээ. Эхлэгчдэд зориулсан гарын авлага

График боловсруулах нэгж (GPU) дээрх таны анхны мэдрэлийн сүлжээ. Эхлэгчдэд зориулсан гарын авлага
Энэ нийтлэлд би 30 минутын дотор машин сургалтын орчинг хэрхэн тохируулах, дүрсийг таних мэдрэлийн сүлжээ үүсгэх, дараа нь график процессор (GPU) дээр ижил сүлжээг ажиллуулах талаар танд хэлэх болно.

Эхлээд мэдрэлийн сүлжээ гэж юу болохыг тодорхойлъё.

Манай тохиолдолд энэ нь биологийн мэдрэлийн сүлжээ - амьд организмын мэдрэлийн эсийн сүлжээг зохион байгуулах, ажиллуулах зарчим дээр суурилсан математик загвар, түүнчлэн түүний програм хангамж эсвэл техник хангамжийн хувилбар юм. Энэхүү ойлголт нь тархинд тохиолддог үйл явцыг судалж, эдгээр үйл явцыг загварчлахыг оролдох явцад үүссэн.

Мэдрэлийн сүлжээнүүд нь ердийн утгаараа програмчлагдаагүй, сургагдсан байдаг. Сурах чадвар нь уламжлалт алгоритмаас мэдрэлийн сүлжээний гол давуу талуудын нэг юм. Техникийн хувьд суралцах нь мэдрэлийн эсүүдийн хоорондын холболтын коэффициентийг олохоос бүрдэнэ. Сургалтын явцад мэдрэлийн сүлжээ нь оролтын өгөгдөл болон гаралтын өгөгдлийн хоорондох нарийн төвөгтэй хамаарлыг тодорхойлох, түүнчлэн ерөнхий дүгнэлт хийх боломжтой.

Машины сургалтын үүднээс мэдрэлийн сүлжээ нь хэв маягийг таних арга, ялгах шинжилгээ, кластерын арга болон бусад аргуудын онцгой тохиолдол юм.

Тоног төхөөрөмж

Эхлээд тоног төхөөрөмжийг авч үзье. Бидэнд Линукс үйлдлийн систем суулгасан сервер хэрэгтэй байна. Машин сургалтын системийг ажиллуулахад шаардагдах тоног төхөөрөмж нь нэлээд хүчирхэг бөгөөд үр дүнд нь үнэтэй байдаг. Гартаа сайн машингүй хүмүүст би үүлэн үйлчилгээ үзүүлэгчдийн саналд анхаарлаа хандуулахыг зөвлөж байна. Та шаардлагатай серверээ хурдан түрээслэх боломжтой бөгөөд зөвхөн ашиглалтын хугацааны төлбөрийг төлөх боломжтой.

Мэдрэлийн сүлжээ үүсгэх шаардлагатай төслүүдэд би Оросын үүлэн үйлчилгээ үзүүлэгчдийн нэг серверийг ашигладаг. Тус компани нь NVIDIA-ийн хүчирхэг Tesla V100 график процессор (GPU) бүхий машин сургалтын зориулалттай үүлэн серверүүдийг түрээслэхийг санал болгож байна. Товчхондоо: GPU бүхий серверийг ашиглах нь тооцоололд CPU ашигладаг ижил өртөгтэй сервертэй харьцуулахад хэдэн арван дахин илүү үр ашигтай (хурдан) байж болно. Энэ нь тооцооллыг илүү хурдан гүйцэтгэдэг GPU архитектурын онцлогоос шалтгаална.

Доор тайлбарласан жишээнүүдийг хэрэгжүүлэхийн тулд бид дараах серверийг хэд хоногийн турш худалдаж авсан:

  • SSD диск 150 ГБ
  • RAM 32 GB
  • Tesla V100 16 цөмтэй 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 юм. Линукс дээр ашиглах хамгийн алдартай платформ бол Анасбара.

Үүнийг сервер дээрээ суулгацгаая.

Бид орон нутгийн багц менежерийг шинэчилж эхэлдэг:

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-тэй ажиллах болно. Үүнийг суулгацгаая:

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 нээгдэнэ.

Шинэ дэвтэр бүтээцгээе: New - Notebook - Python 3.

Бидний суулгасан бүх бүрэлдэхүүн хэсгүүдийн зөв ажиллагааг шалгацгаая. Жишээ PyTorch кодыг Jupyter-д оруулаад гүйцэтгэлийг ажиллуулцгаая (Run товч):

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

сэтгэгдэл нэмэх