Ditt første nevrale nettverk på en grafikkbehandlingsenhet (GPU). Nybegynnerguide

Ditt første nevrale nettverk på en grafikkbehandlingsenhet (GPU). Nybegynnerguide
I denne artikkelen vil jeg fortelle deg hvordan du setter opp et maskinlæringsmiljø på 30 minutter, lager et nevralt nettverk for bildegjenkjenning og deretter kjører det samme nettverket på en grafikkprosessor (GPU).

Først, la oss definere hva et nevralt nettverk er.

I vårt tilfelle er dette en matematisk modell, så vel som dens programvare- eller maskinvareutførelse, bygget på prinsippet om organisering og funksjon av biologiske nevrale nettverk - nettverk av nerveceller til en levende organisme. Dette konseptet oppsto mens vi studerte prosessene som skjer i hjernen og forsøkte å modellere disse prosessene.

Nevrale nettverk er ikke programmert i ordets vanlige betydning, de er trent. Evnen til å lære er en av hovedfordelene med nevrale nettverk fremfor tradisjonelle algoritmer. Teknisk sett består læring av å finne koeffisientene for sammenhenger mellom nevroner. Under treningsprosessen er det nevrale nettverket i stand til å identifisere komplekse avhengigheter mellom inngangsdata og utdata, samt utføre generalisering.

Fra et maskinlæringssynspunkt er et nevralt nettverk et spesielt tilfelle av mønstergjenkjenningsmetoder, diskriminantanalyse, klyngingsmetoder og andre metoder.

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

La oss først se på utstyret. Vi trenger en server med Linux-operativsystemet installert på den. Utstyret som kreves for å betjene maskinlæringssystemer er ganske kraftig og som et resultat dyrt. For de som ikke har en god maskin for hånden, anbefaler jeg å ta hensyn til tilbudene til skyleverandører. Du kan leie den nødvendige serveren raskt og betale kun for brukstiden.

I prosjekter hvor det er nødvendig å lage nevrale nettverk, bruker jeg serverne til en av de russiske skyleverandørene. Selskapet tilbyr skyservere til leie spesielt for maskinlæring med kraftige Tesla V100-grafikkprosessorer (GPU) fra NVIDIA. Kort sagt: å bruke en server med en GPU kan være titalls ganger mer effektiv (raskt) sammenlignet med en server med tilsvarende pris som bruker en CPU (den velkjente sentralbehandlingsenheten) til beregninger. Dette oppnås på grunn av funksjonene til GPU-arkitekturen, som takler beregninger raskere.

For å implementere eksemplene beskrevet nedenfor, kjøpte vi følgende server i flere dager:

  • SSD-disk 150 GB
  • RAM 32 GB
  • Tesla V100 16 Gb prosessor med 4 kjerner

Vi installerte Ubuntu 18.04 på maskinen vår.

Sette opp miljøet

La oss nå installere alt som er nødvendig for arbeid på serveren. Siden artikkelen vår først og fremst er for nybegynnere, vil jeg snakke om noen punkter som vil være nyttige for dem.

Mye av arbeidet når du setter opp et miljø gjøres gjennom kommandolinjen. De fleste brukerne bruker Windows som sitt fungerende OS. Standardkonsollen i dette operativsystemet etterlater mye å være ønsket. Derfor vil vi bruke et praktisk verktøy Cmder/. Last ned miniversjonen og kjør Cmder.exe. Deretter må du koble til serveren via SSH:

ssh root@server-ip-or-hostname

I stedet for server-ip-eller-vertsnavn, spesifiser IP-adressen eller DNS-navnet til serveren din. Deretter skriver du inn passordet, og hvis tilkoblingen er vellykket, bør vi motta en melding som ligner på denne.

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

Hovedspråket for å utvikle ML-modeller er Python. Og den mest populære plattformen for bruk på Linux er Anaconda.

La oss installere det på serveren vår.

Vi starter med å oppdatere den lokale pakkebehandleren:

sudo apt-get update

Installer curl (kommandolinjeverktøy):

sudo apt-get install curl

Last ned siste versjon av Anaconda Distribution:

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

La oss starte installasjonen:

bash Anaconda3-2019.10-Linux-x86_64.sh

Under installasjonsprosessen vil du bli bedt om å bekrefte lisensavtalen. Etter vellykket installasjon bør du se dette:

Thank you for installing Anaconda3!

Mange rammeverk er nå laget for utvikling av ML-modeller; vi jobber med de mest populære: PyTorch и tensorflow.

Ved å bruke rammeverket kan du øke hastigheten på utviklingen og bruke ferdige verktøy for standardoppgaver.

I dette eksemplet skal vi jobbe med PyTorch. La oss installere det:

conda install pytorch torchvision cudatoolkit=10.1 -c pytorch

Nå må vi lansere Jupyter Notebook, et populært utviklingsverktøy for ML-spesialister. Den lar deg skrive kode og umiddelbart se resultatene av dens utførelse. Jupyter Notebook følger med Anaconda og er allerede installert på serveren vår. Du må koble til den fra vårt skrivebordssystem.

For å gjøre dette vil vi først starte Jupyter på serveren som spesifiserer port 8080:

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

Deretter åpner vi en annen fane i Cmder-konsollen vår (toppmeny - Ny konsolldialog), og vi kobler til serveren via port 8080 via SSH:

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

Når vi skriver inn den første kommandoen, vil vi bli tilbudt lenker for å åpne Jupyter i nettleseren vår:

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

La oss bruke lenken for localhost:8080. Kopier hele banen og lim den inn i adressefeltet til PC-ens lokale nettleser. Jupyter Notebook åpnes.

La oss lage en ny notatbok: Ny - Notatbok - Python 3.

La oss sjekke at alle komponentene vi installerte fungerer korrekt. La oss legge inn eksempelet PyTorch-koden i Jupyter og kjøre utførelsen (Kjør-knappen):

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

Resultatet bør være noe slikt:

Ditt første nevrale nettverk på en grafikkbehandlingsenhet (GPU). Nybegynnerguide

Hvis du har et lignende resultat, har vi konfigurert alt riktig, og vi kan begynne å utvikle et nevralt nettverk!

Opprette et nevralt nettverk

Vi skal lage et nevralt nettverk for bildegjenkjenning. La oss ta dette som grunnlag lederskap.

Vi vil bruke det offentlig tilgjengelige CIFAR10-datasettet for å trene nettverket. Den har klasser: "fly", "bil", "fugl", "katt", "hjort", "hund", "frosk", "hest", "skip", "lastebil". Bilder i CIFAR10 er 3x32x32, det vil si 3-kanals fargebilder på 32x32 piksler.

Ditt første nevrale nettverk på en grafikkbehandlingsenhet (GPU). Nybegynnerguide
For arbeid vil vi bruke pakken opprettet av PyTorch for å jobbe med bilder - torchvision.

Vi vil gjøre følgende trinn i rekkefølge:

  • Laster og normaliserer trenings- og testdatasett
  • Nevrale nettverksdefinisjon
  • Nettverkstrening på treningsdata
  • Nettverkstesting på testdata
  • La oss gjenta trening og testing med GPU

Vi vil kjøre all koden nedenfor i Jupyter Notebook.

Laster og normaliserer CIFAR10

Kopier og kjør følgende kode i 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')

Svaret bør være:

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

La oss vise flere treningsbilder for testing:


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

Ditt første nevrale nettverk på en grafikkbehandlingsenhet (GPU). Nybegynnerguide

Nevrale nettverksdefinisjon

La oss først vurdere hvordan et nevralt nettverk for bildegjenkjenning fungerer. Dette er et enkelt punkt-til-punkt-nettverk. Den tar inndata, sender den gjennom flere lag ett etter ett, og produserer til slutt utdata.

Ditt første nevrale nettverk på en grafikkbehandlingsenhet (GPU). Nybegynnerguide

La oss lage et lignende nettverk i miljøet vårt:


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

Vi definerer også en tapsfunksjon og en optimizer


import torch.optim as optim

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

Nettverkstrening på treningsdata

La oss begynne å trene vårt nevrale nettverk. Vær oppmerksom på at etter at du har kjørt denne koden, må du vente litt til arbeidet er fullført. Det tok meg 5 minutter. Det tar tid å trene nettverket.

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

Vi får følgende resultat:

Ditt første nevrale nettverk på en grafikkbehandlingsenhet (GPU). Nybegynnerguide

Vi lagrer vår trente modell:

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

Nettverkstesting på testdata

Vi trente nettverket ved å bruke et sett med treningsdata. Men vi må sjekke om nettverket i det hele tatt har lært noe.

Vi vil teste dette ved å forutsi klasseetiketten som det nevrale nettverket sender ut og teste det for å se om det er sant. Hvis prediksjonen er riktig, legger vi prøven til listen over riktige prediksjoner.
La oss vise et bilde fra testsettet:

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

Ditt første nevrale nettverk på en grafikkbehandlingsenhet (GPU). Nybegynnerguide

La oss nå be det nevrale nettverket fortelle oss hva som er på disse bildene:


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

Ditt første nevrale nettverk på en grafikkbehandlingsenhet (GPU). Nybegynnerguide

Resultatene virker ganske gode: nettverket identifiserte tre av fire bilder riktig.

La oss se hvordan nettverket fungerer på tvers av hele datasettet.


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

Ditt første nevrale nettverk på en grafikkbehandlingsenhet (GPU). Nybegynnerguide

Det ser ut som nettverket vet noe og fungerer. Hvis han bestemte klassene tilfeldig, ville nøyaktigheten være 10 %.

La oss nå se hvilke klasser nettverket identifiserer best:

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

Ditt første nevrale nettverk på en grafikkbehandlingsenhet (GPU). Nybegynnerguide

Det ser ut til at nettverket er best på å identifisere biler og skip: 71 % nøyaktighet.

Så nettverket fungerer. La oss nå prøve å overføre arbeidet til grafikkprosessoren (GPU) og se hva som endres.

Trening av et nevralt nettverk på GPU

Først vil jeg kort forklare hva CUDA er. CUDA (Compute Unified Device Architecture) er en parallell databehandlingsplattform utviklet av NVIDIA for generell databehandling på grafikkbehandlingsenheter (GPUer). Med CUDA kan utviklere dramatisk akselerere databehandlingsapplikasjoner ved å utnytte kraften til GPUer. Denne plattformen er allerede installert på serveren vår som vi kjøpte.

La oss først definere vår GPU som den første synlige cuda-enheten.

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 )

Ditt første nevrale nettverk på en grafikkbehandlingsenhet (GPU). Nybegynnerguide

Sende nettverket til GPUen:

net.to(device)

Vi må også sende input og mål ved hvert trinn til GPU:

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

La oss trene nettverket på nytt på GPUen:

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

Denne gangen varte nettverkstreningen i ca 3 minutter. La oss huske at det samme trinnet på en konvensjonell prosessor varte i 5 minutter. Forskjellen er ikke signifikant, dette skjer fordi nettverket vårt ikke er så stort. Når du bruker store arrays for trening, vil forskjellen mellom hastigheten til GPUen og en tradisjonell prosessor øke.

Det ser ut til å være alt. Hva vi klarte å gjøre:

  • Vi så på hva en GPU er og valgte serveren den er installert på;
  • Vi har satt opp et programvaremiljø for å lage et nevralt nettverk;
  • Vi laget et nevralt nettverk for bildegjenkjenning og trente det;
  • Vi gjentok nettverkstreningen ved å bruke GPU og fikk en økning i hastighet.

Jeg svarer gjerne på spørsmål i kommentarfeltet.

Kilde: www.habr.com

Legg til en kommentar