Ditt första neurala nätverk på en grafikprocessor (GPU). Nybörjarguide

Ditt första neurala nätverk på en grafikprocessor (GPU). Nybörjarguide
I den här artikeln kommer jag att berätta hur du ställer in en maskininlärningsmiljö på 30 minuter, skapar ett neuralt nätverk för bildigenkänning och sedan kör samma nätverk på en grafikprocessor (GPU).

Låt oss först definiera vad ett neuralt nätverk är.

I vårt fall är detta en matematisk modell, såväl som dess mjukvara eller hårdvara, byggd på principen om organisation och funktion av biologiska neurala nätverk - nätverk av nervceller i en levande organism. Detta koncept uppstod när man studerade de processer som förekommer i hjärnan och försökte modellera dessa processer.

Neurala nätverk är inte programmerade i ordets vanliga bemärkelse, de är tränade. Förmågan att lära sig är en av de största fördelarna med neurala nätverk jämfört med traditionella algoritmer. Tekniskt sett består lärande av att hitta koefficienterna för kopplingar mellan neuroner. Under träningsprocessen kan det neurala nätverket identifiera komplexa beroenden mellan indata och utdata, samt utföra generalisering.

Ur maskininlärningssynpunkt är ett neuralt nätverk ett specialfall av mönsterigenkänningsmetoder, diskriminantanalys, klustringsmetoder och andra metoder.

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

Låt oss först titta på utrustningen. Vi behöver en server med operativsystemet Linux installerat på den. Utrustningen som krävs för att driva maskininlärningssystem är ganska kraftfull och som ett resultat dyr. För de som inte har en bra maskin till hands rekommenderar jag att uppmärksamma molnleverantörernas erbjudanden. Du kan hyra den nödvändiga servern snabbt och betala endast för användningstiden.

I projekt där det är nödvändigt att skapa neurala nätverk använder jag servrarna hos en av de ryska molnleverantörerna. Företaget erbjuder molnservrar att hyra specifikt för maskininlärning med kraftfulla Tesla V100-grafikprocessorer (GPU) från NVIDIA. Kort sagt: att använda en server med en GPU kan vara tiotals gånger effektivare (snabbt) jämfört med en server med liknande kostnad som använder en CPU (den välkända centralenheten) för beräkningar. Detta uppnås på grund av funktionerna i GPU-arkitekturen, som klarar beräkningar snabbare.

För att implementera exemplen som beskrivs nedan köpte vi följande server i flera dagar:

  • SSD-disk 150 GB
  • RAM 32 GB
  • Tesla V100 16 Gb processor med 4 kärnor

Vi installerade Ubuntu 18.04 på vår maskin.

Att sätta upp miljön

Låt oss nu installera allt som behövs för arbete på servern. Eftersom vår artikel främst är för nybörjare, kommer jag att prata om några punkter som kommer att vara användbara för dem.

Mycket av arbetet när du ställer in en miljö görs via kommandoraden. De flesta av användarna använder Windows som sitt fungerande operativsystem. Standardkonsolen i detta operativsystem lämnar mycket övrigt att önska. Därför kommer vi att använda ett bekvämt verktyg Cmdder/. Ladda ner miniversionen och kör Cmder.exe. Därefter måste du ansluta till servern via SSH:

ssh root@server-ip-or-hostname

Istället för server-ip-eller-värdnamn, ange IP-adressen eller DNS-namnet för din server. Ange sedan lösenordet och om anslutningen lyckas bör vi få ett meddelande liknande detta.

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

Huvudspråket för att utveckla ML-modeller är Python. Och den mest populära plattformen för dess användning på Linux är Anakonda.

Låt oss installera det på vår server.

Vi börjar med att uppdatera den lokala pakethanteraren:

sudo apt-get update

Installera curl (kommandoradsverktyg):

sudo apt-get install curl

Ladda ner den senaste versionen av Anaconda Distribution:

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

Låt oss börja installationen:

bash Anaconda3-2019.10-Linux-x86_64.sh

Under installationsprocessen kommer du att bli ombedd att bekräfta licensavtalet. Efter lyckad installation bör du se detta:

Thank you for installing Anaconda3!

Många ramverk har nu skapats för utveckling av ML-modeller; vi arbetar med de mest populära: PyTorch и Tensorflöde.

Genom att använda ramverket kan du öka utvecklingshastigheten och använda färdiga verktyg för standarduppgifter.

I det här exemplet kommer vi att arbeta med PyTorch. Låt oss installera det:

conda install pytorch torchvision cudatoolkit=10.1 -c pytorch

Nu måste vi lansera Jupyter Notebook, ett populärt utvecklingsverktyg för ML-specialister. Det låter dig skriva kod och omedelbart se resultatet av dess exekvering. Jupyter Notebook ingår i Anaconda och är redan installerad på vår server. Du måste ansluta till den från vårt skrivbordssystem.

För att göra detta kommer vi först att starta Jupyter på servern som anger port 8080:

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

När vi sedan öppnar en annan flik i vår Cmder-konsol (toppmenyn - Ny konsoldialog) kommer vi att ansluta via port 8080 till servern via SSH:

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

När vi anger det första kommandot kommer vi att erbjudas länkar för att öppna Jupyter i vår webbläsare:

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

Låt oss använda länken för localhost:8080. Kopiera hela sökvägen och klistra in den i adressfältet i din dators lokala webbläsare. Jupyter Notebook öppnas.

Låt oss skapa en ny anteckningsbok: Ny - Notebook - Python 3.

Låt oss kontrollera att alla komponenter som vi installerade fungerar korrekt. Låt oss ange exempel PyTorch-koden i Jupyter och köra exekveringen (Kör-knappen):

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

Resultatet borde bli ungefär så här:

Ditt första neurala nätverk på en grafikprocessor (GPU). Nybörjarguide

Om du har ett liknande resultat, då har vi konfigurerat allt korrekt och vi kan börja utveckla ett neuralt nätverk!

Skapa ett neuralt nätverk

Vi kommer att skapa ett neuralt nätverk för bildigenkänning. Låt oss ta detta som grund ledning.

Vi kommer att använda den allmänt tillgängliga CIFAR10-datauppsättningen för att träna nätverket. Den har klasser: "flygplan", "bil", "fågel", "katt", "hjort", "hund", "groda", "häst", "fartyg", "lastbil". Bilder i CIFAR10 är 3x32x32, det vill säga 3-kanaliga färgbilder på 32x32 pixlar.

Ditt första neurala nätverk på en grafikprocessor (GPU). Nybörjarguide
För arbete kommer vi att använda paketet skapat av PyTorch för att arbeta med bilder - torchvision.

Vi kommer att göra följande steg i ordning:

  • Laddar och normaliserar tränings- och testdatauppsättningar
  • Neural Network Definition
  • Nätverksträning på träningsdata
  • Nätverkstestning på testdata
  • Låt oss upprepa träning och testning med GPU

Vi kommer att köra all kod nedan i Jupyter Notebook.

Laddar och normaliserar CIFAR10

Kopiera och kör följande kod 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 vara:

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

Låt oss visa flera träningsbilder för testning:


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örsta neurala nätverk på en grafikprocessor (GPU). Nybörjarguide

Neural Network Definition

Låt oss först överväga hur ett neuralt nätverk för bildigenkänning fungerar. Detta är ett enkelt punkt-till-punkt-nätverk. Den tar indata, skickar den genom flera lager ett efter ett och producerar sedan utdata.

Ditt första neurala nätverk på en grafikprocessor (GPU). Nybörjarguide

Låt oss skapa ett liknande nätverk i vår miljö:


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 definierar även en förlustfunktion och en optimerare


import torch.optim as optim

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

Nätverksträning på träningsdata

Låt oss börja träna vårt neurala nätverk. Observera att efter att du har kört den här koden måste du vänta ett tag tills arbetet är slutfört. Det tog mig 5 minuter. Det tar tid att träna upp nätverket.

 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öljande resultat:

Ditt första neurala nätverk på en grafikprocessor (GPU). Nybörjarguide

Vi sparar vår utbildade modell:

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

Nätverkstestning på testdata

Vi tränade nätverket med hjälp av en uppsättning träningsdata. Men vi måste kontrollera om nätverket har lärt sig något alls.

Vi kommer att testa detta genom att förutsäga klassetiketten som det neurala nätverket matar ut och testa det för att se om det är sant. Om förutsägelsen är korrekt lägger vi till provet till listan över korrekta förutsägelser.
Låt oss visa en bild från testsetet:

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örsta neurala nätverk på en grafikprocessor (GPU). Nybörjarguide

Låt oss nu be det neurala nätverket berätta vad som finns på dessa bilder:


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örsta neurala nätverk på en grafikprocessor (GPU). Nybörjarguide

Resultaten verkar ganska bra: nätverket identifierade tre av fyra bilder korrekt.

Låt oss se hur nätverket presterar över hela datamängden.


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örsta neurala nätverk på en grafikprocessor (GPU). Nybörjarguide

Det verkar som att nätverket vet något och fungerar. Om han bestämde klasserna slumpmässigt skulle noggrannheten vara 10 %.

Låt oss nu se vilka klasser nätverket identifierar bättre:

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örsta neurala nätverk på en grafikprocessor (GPU). Nybörjarguide

Det verkar som att nätverket är bäst på att identifiera bilar och fartyg: 71 % noggrannhet.

Så nätverket fungerar. Låt oss nu försöka överföra dess arbete till grafikprocessorn (GPU) och se vad som ändras.

Att träna ett neuralt nätverk på GPU

Först ska jag kort förklara vad CUDA är. CUDA (Compute Unified Device Architecture) är en parallell datorplattform utvecklad av NVIDIA för allmän beräkning av grafikprocessorer (GPU). Med CUDA kan utvecklare dramatiskt accelerera datorapplikationer genom att utnyttja kraften hos GPU:er. Denna plattform är redan installerad på vår server som vi köpte.

Låt oss först definiera vår GPU som den första synliga 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örsta neurala nätverk på en grafikprocessor (GPU). Nybörjarguide

Skicka nätverket till GPU:n:

net.to(device)

Vi måste också skicka indata och mål vid varje steg till GPU:n:

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

Låt oss träna om nätverket på GPU:n:

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

Den här gången varade nätverksträningen i cirka 3 minuter. Låt oss komma ihåg att samma steg på en konventionell processor varade i 5 minuter. Skillnaden är inte signifikant, detta händer eftersom vårt nätverk inte är så stort. När du använder stora arrayer för träning kommer skillnaden mellan hastigheten på GPU:n och en traditionell processor att öka.

Det verkar vara allt. Vad vi lyckades göra:

  • Vi tittade på vad en GPU är och valde servern som den är installerad på;
  • Vi har satt upp en mjukvarumiljö för att skapa ett neuralt nätverk;
  • Vi skapade ett neuralt nätverk för bildigenkänning och tränade det;
  • Vi upprepade nätverksträningen med GPU:n och fick en ökad hastighet.

Jag svarar gärna på frågor i kommentarerna.

Källa: will.com

Lägg en kommentar