Ären éischten neurale Netzwierk op enger Grafikveraarbechtungseenheet (GPU). Ufänger d'Guide

Ären éischten neurale Netzwierk op enger Grafikveraarbechtungseenheet (GPU). Ufänger d'Guide
An dësem Artikel wäert ech Iech soen wéi Dir e Maschinnléierëmfeld an 30 Minutten opstellt, en neuralt Netzwierk fir Bilderkennung erstellt, an dann datselwecht Netzwierk op engem Grafikprozessor (GPU) lafen.

Als éischt, loosst eis definéieren wat en neuralt Netzwierk ass.

An eisem Fall ass dëst e mathematesche Modell, wéi och seng Software oder Hardware Ausféierung, gebaut op de Prinzip vun der Organisatioun a Fonctionnement vun biologeschen neural Netzwierker - Netzwierker vun Nerve Zellen vun engem liewege Organismus. Dëst Konzept ass entstanen beim Studium vun de Prozesser déi am Gehir optrieden a probéiert dës Prozesser ze modelléieren.

Neural Netzwierker sinn net am gewéinleche Sënn vum Wuert programméiert, si ginn trainéiert. D'Fäegkeet ze léieren ass ee vun den Haaptvirdeeler vun neurale Netzwierker iwwer traditionell Algorithmen. Technesch besteet d'Léieren aus der Sich no de Koeffizienten vu Verbindungen tëscht Neuronen. Wärend dem Trainingsprozess ass den neurale Netzwierk fäeg komplex Ofhängegkeeten tëscht Inputdaten an Ausgangsdaten z'identifizéieren, souwéi Generaliséierung auszeféieren.

Aus der Siicht vum Maschinnléieren ass en neuralt Netzwierk e spezielle Fall vu Mustererkennungsmethoden, diskriminant Analyse, Clustermethoden an aner Methoden.

Ausrüstung

Als éischt, loosst eis d'Ausrüstung kucken. Mir brauchen e Server mat dem Linux Betribssystem installéiert. D'Ausrüstung déi néideg ass fir Maschinnléiersystemer ze bedreiwen ass zimmlech mächteg an als Resultat deier. Fir déi, déi keng gutt Maschinn bei der Hand hunn, empfeelen ech op d'Offer vu Cloud Provider opmierksam ze maachen. Dir kënnt den erfuerderlechen Server séier lounen a bezuelt nëmme fir d'Zäit vum Gebrauch.

A Projeten, wou et néideg ass fir neural Netzwierker ze kreéieren, benotzen ech d'Servere vun engem vun de russesche Cloud-Provider. D'Firma bitt Cloud-Server fir Loyer speziell fir Maschinnléieren mat mächtege Tesla V100 Grafikprozessoren (GPU) vun NVIDIA. Kuerz gesot: e Server mat enger GPU benotzen kann zéng mol méi effizient (séier) sinn am Verglach zu engem Server vun ähnlechen Käschten, deen eng CPU benotzt (déi bekannte Zentralveraarbechtungseenheet) fir Berechnungen. Dëst gëtt erreecht duerch d'Features vun der GPU Architektur, déi méi séier mat Berechnunge këmmert.

Fir déi hei ënnen beschriwwe Beispiller ëmzesetzen, hu mir de folgende Server fir e puer Deeg kaaft:

  • SSD Scheif 150 GB
  • RAM 32 GB
  • Tesla V100 16 Gb Prozessor mat 4 Kär

Mir hunn Ubuntu 18.04 op eiser Maschinn installéiert.

D'Ëmwelt opbauen

Loosst eis elo alles installéieren wat néideg ass fir um Server ze schaffen. Well eisen Artikel haaptsächlech fir Ufänger ass, wäert ech iwwer e puer Punkte schwätzen, déi fir si nëtzlech sinn.

Vill vun der Aarbecht beim Ariichten vun engem Ëmfeld gëtt duerch d'Kommandozeil gemaach. Déi meescht vun de Benotzer benotzen Windows als hiren Aarbechts OS. D'Standardkonsole an dësem OS léisst vill ze wënschen. Dofir wäerte mir e praktescht Tool benotzen Cmder/. Luet d'Mini Versioun erof a lafen Cmder.exe. Als nächst musst Dir mam Server iwwer SSH verbannen:

ssh root@server-ip-or-hostname

Amplaz Server-IP-oder-Hostnumm, spezifizéiert d'IP Adress oder DNS Numm vun Ärem Server. Als nächst gitt d'Passwuert a wann d'Verbindung erfollegräich ass, solle mir e Message ähnlech wéi dëst kréien.

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

D'Haaptsprooch fir ML Modeller z'entwéckelen ass Python. An déi populärste Plattform fir seng Benotzung op Linux ass Anaconda.

Loosst eis et op eisem Server installéieren.

Mir starten mam Update vum lokale Package Manager:

sudo apt-get update

Installéiert Curl (Command Line Utility):

sudo apt-get install curl

Luet déi lescht Versioun vun Anaconda Distribution erof:

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

Loosst eis d'Installatioun ufänken:

bash Anaconda3-2019.10-Linux-x86_64.sh

Wärend der Installatiounsprozess gitt Dir gefrot fir de Lizenzvertrag ze bestätegen. Bei der erfollegräicher Installatioun sollt Dir dëst gesinn:

Thank you for installing Anaconda3!

Vill Kadere goufen elo erstallt fir d'Entwécklung vu ML Modeller; mir schaffen mat de populärsten: PyTorch и tensor Flux.

D'Benotzung vum Kader erlaabt Iech d'Geschwindegkeet vun der Entwécklung ze erhéijen a fäerdege Tools fir Standardaufgaben ze benotzen.

An dësem Beispill wäerte mir mat PyTorch schaffen. Loosst eis et installéieren:

conda install pytorch torchvision cudatoolkit=10.1 -c pytorch

Elo musse mir Jupyter Notebook starten, e populär Entwécklungsinstrument fir ML Spezialisten. Et erlaabt Iech Code ze schreiwen an direkt d'Resultater vu senger Ausféierung ze gesinn. Jupyter Notebook ass mat Anaconda abegraff an ass schonn op eisem Server installéiert. Dir musst et vun eisem Desktop System verbannen.

Fir dëst ze maachen, starten mir als éischt de Jupyter um Server deen den Hafen 8080 spezifizéiert:

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

Als nächst, öffnen eng aner Tab an eiser Cmder Konsole (Topmenü - Neie Konsol Dialog) mir verbannen iwwer Port 8080 mam Server iwwer SSH:

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

Wa mir den éischte Kommando aginn, gi mir Linken ugebuede fir Jupyter an eisem Browser opzemaachen:

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

Loosst eis de Link fir localhost benotzen:8080. Kopéiert de komplette Wee a paste se an d'Adressbar vum lokalen Browser vun Ärem PC. Jupyter Notebook wäert opmaachen.

Loosst eis en neit Notizbuch erstellen: Nei - Notizbuch - Python 3.

Loosst eis d'korrekt Operatioun vun all de Komponenten kontrolléieren déi mir installéiert hunn. Loosst eis de Beispill PyTorch Code an Jupyter aginn an d'Ausféierung lafen (Run Knäppchen):

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

D'Resultat sollt eppes wéi dat sinn:

Ären éischten neurale Netzwierk op enger Grafikveraarbechtungseenheet (GPU). Ufänger d'Guide

Wann Dir en ähnlecht Resultat hutt, da hu mir alles richteg konfiguréiert a mir kënnen ufänken en neuralt Netzwierk z'entwéckelen!

En neuralt Netzwierk erstellen

Mir erstellen en neuralt Netzwierk fir Bilderkennung. Loosst eis dat als Basis huelen Leadership.

Mir wäerten déi ëffentlech verfügbar CIFAR10 Dataset benotze fir de Reseau ze trainéieren. Et huet Klassen: "Fliger", "Auto", "Vugel", "Kat", "Rei", "Hond", "Fräsch", "Päerd", "Schëff", "Camion". Biller an CIFAR10 sinn 3x32x32, dat ass, 3-Kanal Faarf Biller vun 32x32 Pixel.

Ären éischten neurale Netzwierk op enger Grafikveraarbechtungseenheet (GPU). Ufänger d'Guide
Fir Aarbecht benotze mir de Package erstallt vu PyTorch fir mat Biller ze schaffen - torchvision.

Mir maachen déi folgend Schrëtt an Uerdnung:

  • Lueden an normaliséieren Training an Test Datesets
  • Neural Network Definitioun
  • Reseau Training op Training Daten
  • Netzwierk Testen op Testdaten
  • Loosst eis Training an Tester mat GPU widderhuelen

Mir wäerten all de Code hei ënnen am Jupyter Notebook ausféieren.

Lueden an normaliséieren CIFAR10

Kopéiert a lafen de folgende Code am 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')

D'Äntwert soll sinn:

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

Loosst eis e puer Trainingsbilder weisen fir ze testen:


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

Ären éischten neurale Netzwierk op enger Grafikveraarbechtungseenheet (GPU). Ufänger d'Guide

Neural Network Definitioun

Loosst eis als éischt kucken wéi en neuralt Netzwierk fir Bilderkennung funktionnéiert. Dëst ass en einfache Punkt-zu-Punkt Netzwierk. Et hëlt Inputdaten, passéiert se duerch verschidde Schichten een nom aneren, a produzéiert dann endlech Ausgangsdaten.

Ären éischten neurale Netzwierk op enger Grafikveraarbechtungseenheet (GPU). Ufänger d'Guide

Loosst eis en ähnlecht Netzwierk an eisem Ëmfeld erstellen:


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

Mir definéieren och eng Verloscht Funktioun an Optimizer


import torch.optim as optim

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

Reseau Training op Training Daten

Loosst eis ufänken eisen neurale Netzwierk ze trainéieren. Notéiert w.e.g. datt nodeems Dir dëse Code leeft, musst Dir e bëssen Zäit waarden bis d'Aarbecht fäerdeg ass. Et huet mech 5 Minutten gedauert. Et brauch Zäit fir de Reseau ze trainéieren.

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

Mir kréien folgend Resultat:

Ären éischten neurale Netzwierk op enger Grafikveraarbechtungseenheet (GPU). Ufänger d'Guide

Mir späicheren eisen trainéierte Modell:

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

Netzwierk Testen op Testdaten

Mir hunn d'Netzwierk trainéiert mat enger Rei vun Trainingsdaten. Mä mir musse kucken ob d'Netz iwwerhaapt eppes geléiert huet.

Mir wäerten dëst testen andeems de Klasseetikett virausgesot gëtt, deen den neurale Netzwierk ausgëtt an et testen fir ze kucken ob et richteg ass. Wann d'Prognose richteg ass, fügen mir d'Probe op d'Lëscht vun de richtege Prognosen.
Loosst eis e Bild aus dem Testset weisen:

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

Ären éischten neurale Netzwierk op enger Grafikveraarbechtungseenheet (GPU). Ufänger d'Guide

Loosst eis elo den neurale Netzwierk froen fir eis ze soen wat op dëse Biller ass:


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

Ären éischten neurale Netzwierk op enger Grafikveraarbechtungseenheet (GPU). Ufänger d'Guide

D'Resultater schéngen zimlech gutt: d'Netzwierk huet dräi vu véier Biller korrekt identifizéiert.

Loosst eis kucken wéi d'Netzwierk iwwer de ganzen Dataset funktionnéiert.


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

Ären éischten neurale Netzwierk op enger Grafikveraarbechtungseenheet (GPU). Ufänger d'Guide

Et gesäit aus wéi wann de Reseau eppes weess a funktionnéiert. Wann hien d'Klassen zoufälleg bestëmmt, wier d'Genauegkeet 10%.

Loosst eis elo kucken wéi eng Klassen d'Netzwierk besser identifizéiert:

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

Ären éischten neurale Netzwierk op enger Grafikveraarbechtungseenheet (GPU). Ufänger d'Guide

Et schéngt datt d'Netzwierk am Beschten ass fir Autoen a Schëffer z'identifizéieren: 71% Genauegkeet.

Also de Réseau funktionnéiert. Loosst eis elo probéieren seng Aarbecht op de Grafikprozessor (GPU) ze transferéieren a kucken wat ännert.

Training en neuralt Netzwierk op GPU

Als éischt wäert ech kuerz erklären wat CUDA ass. CUDA (Compute Unified Device Architecture) ass eng parallel Rechenplattform entwéckelt vun NVIDIA fir allgemeng Rechen op Grafikveraarbechtungseenheeten (GPUs). Mat CUDA kënnen d'Entwéckler Informatikapplikatiounen dramatesch beschleunegen andeems se d'Kraaft vu GPUs profitéieren. Dës Plattform ass schonn op eisem Server installéiert dee mir kaaft hunn.

Loosst eis als éischt eis GPU als den éischte siichtbare Cuda Apparat definéieren.

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 )

Ären éischten neurale Netzwierk op enger Grafikveraarbechtungseenheet (GPU). Ufänger d'Guide

Schécken vum Netz un d'GPU:

net.to(device)

Mir mussen och Inputen an Ziler bei all Schrëtt un d'GPU schécken:

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

Loosst eis d'Netzwierk op der GPU nei trainéieren:

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

Dës Kéier huet de Reseau Training ongeféier 3 Minutten gedauert. Loosst eis drun erënneren datt déi selwecht Etapp op engem konventionelle Prozessor 5 Minutten gedauert huet. Den Ënnerscheed ass net bedeitend, dëst geschitt well eist Netzwierk net sou grouss ass. Wann Dir grouss Arrays fir Training benotzt, wäert den Ënnerscheed tëscht der Geschwindegkeet vun der GPU an engem traditionelle Prozessor eropgoen.

Dat schéngt alles ze sinn. Wat mir et fäerdeg bruecht hunn:

  • Mir hunn gekuckt wat eng GPU ass an de Server ausgewielt op deem se installéiert ass;
  • Mir hunn e Software-Ëmfeld opgeriicht fir en neuralt Netzwierk ze kreéieren;
  • Mir hunn en neuralt Netzwierk fir Bilderkennung erstallt an et trainéiert;
  • Mir hunn d'Netzwierktraining mat der GPU widderholl a krut eng Erhéijung vun der Geschwindegkeet.

Ech wäert frou Froen an de Kommentaren ze äntweren.

Source: will.com

Setzt e Commentaire