Eich rhwydwaith niwral cyntaf ar uned brosesu graffeg (GPU). Canllaw i Ddechreuwyr

Eich rhwydwaith niwral cyntaf ar uned brosesu graffeg (GPU). Canllaw i Ddechreuwyr
Yn yr erthygl hon, byddaf yn dweud wrthych sut i sefydlu amgylchedd dysgu peiriant mewn 30 munud, creu rhwydwaith niwral ar gyfer adnabod delweddau, ac yna rhedeg yr un rhwydwaith ar brosesydd graffeg (GPU).

Yn gyntaf, gadewch i ni ddiffinio beth yw rhwydwaith niwral.

Yn ein hachos ni, mae hwn yn fodel mathemategol, yn ogystal â'i ymgorfforiad meddalwedd neu galedwedd, wedi'i adeiladu ar yr egwyddor o drefniadaeth a gweithrediad rhwydweithiau niwral biolegol - rhwydweithiau o gelloedd nerfol organeb fyw. Cododd y cysyniad hwn wrth astudio'r prosesau sy'n digwydd yn yr ymennydd a cheisio modelu'r prosesau hyn.

Nid yw rhwydweithiau nerfol yn cael eu rhaglennu yn ystyr arferol y gair, maent wedi'u hyfforddi. Y gallu i ddysgu yw un o brif fanteision rhwydweithiau niwral dros algorithmau traddodiadol. Yn dechnegol, mae dysgu yn cynnwys dod o hyd i'r cyfernodau cysylltiadau rhwng niwronau. Yn ystod y broses hyfforddi, mae'r rhwydwaith niwral yn gallu nodi dibyniaethau cymhleth rhwng data mewnbwn a data allbwn, yn ogystal â pherfformio cyffredinoli.

O safbwynt dysgu peiriant, mae rhwydwaith niwral yn achos arbennig o ddulliau adnabod patrwm, dadansoddiad gwahaniaethol, dulliau clystyru a dulliau eraill.

Offer

Yn gyntaf, gadewch i ni edrych ar yr offer. Mae angen gweinydd gyda'r system weithredu Linux wedi'i gosod arno. Mae'r offer sydd ei angen i weithredu systemau dysgu peiriant yn eithaf pwerus ac, o ganlyniad, yn ddrud. I'r rhai nad oes ganddynt beiriant da wrth law, rwy'n argymell rhoi sylw i gynigion darparwyr cwmwl. Gallwch rentu'r gweinydd gofynnol yn gyflym a thalu am yr amser defnydd yn unig.

Mewn prosiectau lle mae angen creu rhwydweithiau niwral, rwy'n defnyddio gweinyddwyr un o'r darparwyr cwmwl Rwsia. Mae'r cwmni'n cynnig gweinyddwyr cwmwl i'w rhentu yn benodol ar gyfer dysgu peiriannau gyda phroseswyr graffeg pwerus Tesla V100 (GPU) o NVIDIA. Yn fyr: gall defnyddio gweinydd gyda GPU fod ddegau o weithiau'n fwy effeithlon (cyflym) o'i gymharu â gweinydd o gost debyg sy'n defnyddio CPU (yr uned brosesu ganolog adnabyddus) ar gyfer cyfrifiadau. Cyflawnir hyn oherwydd nodweddion y bensaernïaeth GPU, sy'n ymdopi â chyfrifiadau yn gyflymach.

Er mwyn gweithredu'r enghreifftiau a ddisgrifir isod, fe wnaethom brynu'r gweinydd canlynol am sawl diwrnod:

  • Disg SSD 150 GB
  • RAM 32 GB
  • Prosesydd Tesla V100 16 Gb gyda 4 craidd

Fe wnaethon ni osod Ubuntu 18.04 ar ein peiriant.

Sefydlu'r amgylchedd

Nawr, gadewch i ni osod popeth sy'n angenrheidiol ar gyfer gwaith ar y gweinydd. Gan fod ein herthygl yn bennaf ar gyfer dechreuwyr, byddaf yn siarad am rai pwyntiau a fydd yn ddefnyddiol iddynt.

Mae llawer o'r gwaith wrth sefydlu amgylchedd yn cael ei wneud trwy'r llinell orchymyn. Mae'r rhan fwyaf o'r defnyddwyr yn defnyddio Windows fel eu OS gweithredol. Mae'r consol safonol yn yr OS hwn yn gadael llawer i'w ddymuno. Felly, byddwn yn defnyddio offeryn cyfleus Cmder/. Dadlwythwch y fersiwn fach a rhedeg Cmder.exe. Nesaf mae angen i chi gysylltu â'r gweinydd trwy SSH:

ssh root@server-ip-or-hostname

Yn lle gweinydd-ip-neu-enw gwesteiwr, nodwch gyfeiriad IP neu enw DNS eich gweinydd. Nesaf, rhowch y cyfrinair ac os yw'r cysylltiad yn llwyddiannus, dylem dderbyn neges debyg i hyn.

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

Y brif iaith ar gyfer datblygu modelau ML yw Python. A'r platfform mwyaf poblogaidd ar gyfer ei ddefnyddio ar Linux yw Anaconda.

Gadewch i ni ei osod ar ein gweinydd.

Rydym yn dechrau trwy ddiweddaru'r rheolwr pecyn lleol:

sudo apt-get update

Gosod curl (cyfleustodau llinell orchymyn):

sudo apt-get install curl

Dadlwythwch y fersiwn ddiweddaraf o Anaconda Distribution:

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

Gadewch i ni ddechrau'r gosodiad:

bash Anaconda3-2019.10-Linux-x86_64.sh

Yn ystod y broses osod, gofynnir i chi gadarnhau'r cytundeb trwydded. Ar ôl ei osod yn llwyddiannus dylech weld hyn:

Thank you for installing Anaconda3!

Mae llawer o fframweithiau bellach wedi’u creu ar gyfer datblygu modelau ML; PyTorch и Llif tensor.

Mae defnyddio'r fframwaith yn caniatáu ichi gynyddu cyflymder datblygu a defnyddio offer parod ar gyfer tasgau safonol.

Yn yr enghraifft hon byddwn yn gweithio gyda PyTorch. Gadewch i ni ei osod:

conda install pytorch torchvision cudatoolkit=10.1 -c pytorch

Nawr mae angen i ni lansio Jupyter Notebook, offeryn datblygu poblogaidd ar gyfer arbenigwyr ML. Mae'n caniatáu ichi ysgrifennu cod a gweld canlyniadau ei weithredu ar unwaith. Mae Jupyter Notebook wedi'i gynnwys gydag Anaconda ac mae eisoes wedi'i osod ar ein gweinydd. Mae angen i chi gysylltu ag ef o'n system bwrdd gwaith.

I wneud hyn, byddwn yn lansio Jupyter yn gyntaf ar y gweinydd sy'n nodi porthladd 8080:

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

Nesaf, gan agor tab arall yn ein consol Cmder (bwydlen uchaf - deialog consol newydd) byddwn yn cysylltu trwy borthladd 8080 â'r gweinydd trwy SSH:

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

Pan fyddwn yn mynd i mewn i'r gorchymyn cyntaf, byddwn yn cael cynnig dolenni i agor Jupyter yn ein porwr:

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

Gadewch i ni ddefnyddio'r ddolen ar gyfer localhost: 8080. Copïwch y llwybr llawn a'i gludo i mewn i far cyfeiriad porwr lleol eich PC. Bydd Jupyter Notebook yn agor.

Gadewch i ni greu llyfr nodiadau newydd: Newydd - Llyfr Nodiadau - Python 3.

Gadewch i ni wirio gweithrediad cywir yr holl gydrannau a osodwyd gennym. Gadewch i ni nodi'r cod PyTorch enghreifftiol yn Jupyter a rhedeg y gweithrediad (Rhedeg botwm):

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

Dylai'r canlyniad fod yn rhywbeth fel hyn:

Eich rhwydwaith niwral cyntaf ar uned brosesu graffeg (GPU). Canllaw i Ddechreuwyr

Os oes gennych ganlyniad tebyg, yna rydym wedi ffurfweddu popeth yn gywir a gallwn ddechrau datblygu rhwydwaith niwral!

Creu rhwydwaith niwral

Byddwn yn creu rhwydwaith niwral ar gyfer adnabod delweddau. Gadewch i ni gymryd hyn fel sail arweinyddiaeth.

Byddwn yn defnyddio'r set ddata CIFAR10 sydd ar gael yn gyhoeddus i hyfforddi'r rhwydwaith. Mae ganddo ddosbarthiadau: “awyren”, “car”, “aderyn”, “cath”, “carw”, “ci”, “llyffant”, “ceffyl”, “llong”, “truc”. Mae'r delweddau yn CIFAR10 yn 3x32x32, hynny yw, delweddau lliw 3 sianel o 32x32 picsel.

Eich rhwydwaith niwral cyntaf ar uned brosesu graffeg (GPU). Canllaw i Ddechreuwyr
Ar gyfer gwaith, byddwn yn defnyddio'r pecyn a grëwyd gan PyTorch ar gyfer gweithio gyda delweddau - torchvision.

Byddwn yn gwneud y camau canlynol mewn trefn:

  • Llwytho a normaleiddio setiau data hyfforddi a phrofi
  • Diffiniad Rhwydwaith Niwral
  • Hyfforddiant rhwydwaith ar ddata hyfforddiant
  • Profi rhwydwaith ar ddata profion
  • Gadewch i ni ailadrodd hyfforddiant a phrofi gan ddefnyddio GPU

Byddwn yn gweithredu'r holl god isod yn Jupyter Notebook.

Llwytho a normaleiddio CIFAR10

Copïwch a rhedwch y cod canlynol yn 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')

Dylai'r ateb fod:

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

Gadewch i ni arddangos sawl delwedd hyfforddi i'w profi:


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

Eich rhwydwaith niwral cyntaf ar uned brosesu graffeg (GPU). Canllaw i Ddechreuwyr

Diffiniad Rhwydwaith Niwral

Yn gyntaf, gadewch i ni ystyried sut mae rhwydwaith niwral ar gyfer adnabod delweddau yn gweithio. Rhwydwaith pwynt-i-bwynt syml yw hwn. Mae'n cymryd data mewnbwn, yn ei basio trwy sawl haen fesul un, ac yna'n cynhyrchu data allbwn yn olaf.

Eich rhwydwaith niwral cyntaf ar uned brosesu graffeg (GPU). Canllaw i Ddechreuwyr

Gadewch i ni greu rhwydwaith tebyg yn ein hamgylchedd:


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

Rydym hefyd yn diffinio swyddogaeth golled ac optimizer


import torch.optim as optim

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

Hyfforddiant rhwydwaith ar ddata hyfforddiant

Gadewch i ni ddechrau hyfforddi ein rhwydwaith niwral. Sylwch, ar ôl i chi redeg y cod hwn, bydd angen i chi aros peth amser nes bod y gwaith wedi'i gwblhau. Cymerodd 5 munud i mi. Mae'n cymryd amser i hyfforddi'r rhwydwaith.

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

Rydym yn cael y canlyniad canlynol:

Eich rhwydwaith niwral cyntaf ar uned brosesu graffeg (GPU). Canllaw i Ddechreuwyr

Rydym yn arbed ein model hyfforddedig:

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

Profi rhwydwaith ar ddata profion

Fe wnaethom hyfforddi'r rhwydwaith gan ddefnyddio set o ddata hyfforddi. Ond mae angen inni wirio a yw'r rhwydwaith wedi dysgu unrhyw beth o gwbl.

Byddwn yn profi hyn trwy ragfynegi'r label dosbarth y mae'r rhwydwaith niwral yn ei allbynnu a'i brofi i weld a yw'n wir. Os yw'r rhagfynegiad yn gywir, rydym yn ychwanegu'r sampl at y rhestr o ragfynegiadau cywir.
Gadewch i ni ddangos delwedd o'r set prawf:

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

Eich rhwydwaith niwral cyntaf ar uned brosesu graffeg (GPU). Canllaw i Ddechreuwyr

Nawr, gadewch i ni ofyn i'r rhwydwaith niwral ddweud wrthym beth sydd yn y lluniau hyn:


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

Eich rhwydwaith niwral cyntaf ar uned brosesu graffeg (GPU). Canllaw i Ddechreuwyr

Mae'r canlyniadau'n ymddangos yn eithaf da: nododd y rhwydwaith dri o bob pedwar llun yn gywir.

Gadewch i ni weld sut mae'r rhwydwaith yn perfformio ar draws y set ddata gyfan.


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

Eich rhwydwaith niwral cyntaf ar uned brosesu graffeg (GPU). Canllaw i Ddechreuwyr

Mae'n edrych fel bod y rhwydwaith yn gwybod rhywbeth ac yn gweithio. Pe bai'n pennu'r dosbarthiadau ar hap, byddai'r cywirdeb yn 10%.

Nawr, gadewch i ni weld pa ddosbarthiadau y mae'r rhwydwaith yn eu nodi'n well:

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

Eich rhwydwaith niwral cyntaf ar uned brosesu graffeg (GPU). Canllaw i Ddechreuwyr

Mae'n ymddangos mai'r rhwydwaith sydd orau am adnabod ceir a llongau: cywirdeb o 71%.

Felly mae'r rhwydwaith yn gweithio. Nawr, gadewch i ni geisio trosglwyddo ei waith i'r prosesydd graffeg (GPU) a gweld beth sy'n newid.

Hyfforddi rhwydwaith niwral ar GPU

Yn gyntaf, egluraf yn fyr beth yw CUDA. Mae CUDA (Pensaernïaeth Dyfais Unedig Cyfrifiadurol) yn blatfform cyfrifiadurol cyfochrog a ddatblygwyd gan NVIDIA ar gyfer cyfrifiadura cyffredinol ar unedau prosesu graffeg (GPUs). Gyda CUDA, gall datblygwyr gyflymu cymwysiadau cyfrifiadurol yn ddramatig trwy drosoli pŵer GPUs. Mae'r platfform hwn eisoes wedi'i osod ar ein gweinydd a brynwyd gennym.

Yn gyntaf, gadewch i ni ddiffinio ein GPU fel y ddyfais cuda gweladwy gyntaf.

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 )

Eich rhwydwaith niwral cyntaf ar uned brosesu graffeg (GPU). Canllaw i Ddechreuwyr

Anfon y rhwydwaith i'r GPU:

net.to(device)

Bydd yn rhaid i ni hefyd anfon mewnbynnau a thargedau ar bob cam i'r GPU:

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

Gadewch i ni ail-hyfforddi'r rhwydwaith ar y 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')

Y tro hwn, roedd yr hyfforddiant rhwydwaith yn para tua 3 munud. Gadewch inni gofio bod yr un cam ar brosesydd confensiynol yn para 5 munud. Nid yw'r gwahaniaeth yn arwyddocaol, mae hyn yn digwydd oherwydd nad yw ein rhwydwaith mor fawr. Wrth ddefnyddio araeau mawr ar gyfer hyfforddiant, bydd y gwahaniaeth rhwng cyflymder y GPU a phrosesydd traddodiadol yn cynyddu.

Mae'n ymddangos mai dyna'r cyfan. Beth rydym wedi llwyddo i'w wneud:

  • Fe wnaethom edrych ar beth yw GPU a dewis y gweinydd y mae wedi'i osod arno;
  • Rydym wedi sefydlu amgylchedd meddalwedd i greu rhwydwaith niwral;
  • Fe wnaethon ni greu rhwydwaith niwral ar gyfer adnabod delweddau a'i hyfforddi;
  • Fe wnaethom ailadrodd yr hyfforddiant rhwydwaith gan ddefnyddio'r GPU a derbyn cynnydd mewn cyflymder.

Byddaf yn hapus i ateb cwestiynau yn y sylwadau.

Ffynhonnell: hab.com

Ychwanegu sylw