Ihr erstes neuronales Netzwerk auf einer Grafikkarte (GPU). Ein Leitfaden fĂŒr AnfĂ€nger

Ihr erstes neuronales Netzwerk auf einer Grafikkarte (GPU). Ein Leitfaden fĂŒr AnfĂ€nger
In diesem Artikel erklĂ€re ich, wie Sie in 30 Minuten eine Umgebung fĂŒr maschinelles Lernen einrichten, ein neuronales Netzwerk zur Bilderkennung erstellen und dieses Netzwerk anschließend auf einer Grafikkarte (GPU) ausfĂŒhren können.

Lassen Sie uns zunÀchst klÀren, was ein neuronales Netzwerk ist.

In unserem Fall handelt es sich um ein mathematisches Modell sowie um dessen Software- oder Hardware-Implementierung, die auf dem Prinzip der Organisation und Funktionsweise biologischer neuronaler Netzwerke – Netzwerke von Nervenzellen lebender Organismen – basiert. Dieser Begriff entstand aus dem VerstĂ€ndnis der Prozesse, die im Gehirn ablaufen, und dem Versuch, diese Prozesse zu modellieren.

Neuronale Netzwerke werden nicht auf die herkömmliche Weise programmiert, sondern sie werden trainiert. Die FĂ€higkeit zum Lernen ist eines der Hauptmerkmale, die neuronale Netzwerke von traditionellen Algorithmen unterscheiden. Technisch gesehen besteht das Lernen darin, die Gewichtungsfaktoren der Verbindungen zwischen den Neuronen zu bestimmen. WĂ€hrend des Lernprozesses kann das neuronale Netzwerk komplexe ZusammenhĂ€nge zwischen Eingabedaten und Ausgaben erkennen sowie Verallgemeinerungen durchfĂŒhren.

Im Hinblick auf maschinelles Lernen ist ein neuronales Netzwerk ein spezifischer Fall von Methoden der Mustererkennung, diskriminanter Analyse, Clustering-Methoden und anderen Verfahren.

AusrĂŒstung

Lassen Sie uns zunĂ€chst die Hardware klĂ€ren. Wir benötigen einen Server mit einem installierten Linux-Betriebssystem. FĂŒr den Betrieb von maschinellen Lernsystemen ist leistungsstarke und somit kostspielige Hardware erforderlich. Wer keine geeignete Maschine zur VerfĂŒgung hat, sollte ein Angebot von Cloud-Anbietern in Betracht ziehen. Den benötigten Server kann man schnell mieten und nur fĂŒr die Nutzungsdauer bezahlen.

In Projekten, die die Erstellung von neuronalen Netzwerken erfordern, nutze ich Server eines russischen Cloud-Anbieters. Das Unternehmen bietet Cloud-Server speziell fĂŒr maschinelles Lernen zur Miete an, ausgestattet mit leistungsstarken Tesla V100-Grafikprozessoren (GPU) von NVIDIA. Kurz gesagt: Die Nutzung eines Servers mit GPU kann in vielen FĂ€llen deutlich effizienter (schneller) sein im Vergleich zu einem Server, der Ă€hnliche Kosten hat und auf einem CPU (dem allgemein bekannten zentralen Prozessor) basiert. Dies wird durch die Architektur der GPU ermöglicht, die schneller mit Berechnungen umgehen kann.

FĂŒr die AusfĂŒhrung der nachfolgenden Beispiele haben wir fĂŒr ein paar Tage einen solchen Server erworben:

  • SSD-Festplatte 150 GB
  • RAM 32 GB
  • Tesla V100-Prozessor 16 Gb mit 4 Kernen

Auf der Maschine haben wir Ubuntu 18.04 installiert.

Umgebung einrichten

Jetzt installieren wir alles Notwendige fĂŒr die Arbeit auf dem Server. Da unser Artikel in erster Linie fĂŒr AnfĂ€nger gedacht ist, werde ich einige Punkte erlĂ€utern, die gerade fĂŒr sie nĂŒtzlich sind.

Bei der Einrichtung der Umgebung wird viel Arbeit ĂŒber die Kommandozeile erledigt. Die meisten Benutzer nutzen als Arbeitsbetriebssystem Windows. Die Standardkonsole in diesem System lĂ€sst jedoch zu wĂŒnschen ĂŒbrig. Daher werden wir ein hilfreiches Tool verwenden. Cmder/. Laden Sie die Mini-Version herunter und starten Sie Cmder.exe. Als NĂ€chstes mĂŒssen Sie sich mit dem Server ĂŒber das SSH-Protokoll verbinden:

ssh root@server-ip-or-hostname

Anstelle von server-ip-or-hostname geben Sie die IP-Adresse oder den DNS-Namen Ihres Servers ein. Geben Sie dann das Passwort ein, und bei erfolgreicher Verbindung sollten Sie etwa folgende Meldung erhalten.

Willkommen bei Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-74-generic x86_64)

Die Hauptprogrammiersprache zur Entwicklung von ML-Modellen ist Python. Die beliebteste Plattform fĂŒr dessen Nutzung unter Linux ist Anaconda.

Wir werden sie auf unserem Server installieren.

Wir beginnen mit der Aktualisierung des lokalen Paketmanagers:

sudo apt-get update

Wir installieren curl (das Kommandozeilenwerkzeug):

sudo apt-get install curl

Laden Sie die neueste Version von Anaconda Distribution herunter:

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

Starten Sie die Installation:

bash Anaconda3-2019.10-Linux-x86_64.sh

Im Installationsprozess mĂŒssen Sie den Lizenzvertrag bestĂ€tigen. Bei erfolgreicher Installation sollten Sie Folgendes sehen:

Danke, dass Sie Anaconda3 installiert haben!

FĂŒr die Entwicklung von ML-Modellen gibt es heutzutage viele Frameworks. Wir arbeiten mit den gĂ€ngigsten: PyTorch und Tensorflow.

Die Verwendung des Frameworks ermöglicht eine schnellere Entwicklung und die Nutzung bereits vorhandener Werkzeuge fĂŒr Standardaufgaben.

In diesem Beispiel werden wir mit PyTorch arbeiten. Lassen Sie uns es installieren:

conda install pytorch torchvision cudatoolkit=10.1 -c pytorch

Nun mĂŒssen wir Jupyter Notebook starten – ein bei ML-Spezialisten beliebtes Entwicklungswerkzeug. Es ermöglicht das Schreiben von Code und Sichtbarmachen der Ergebnisse der AusfĂŒhrung. Jupyter Notebook ist Teil von Anaconda und bereits auf unserem Server installiert. Wir mĂŒssen uns von unserem Desktop-System aus damit verbinden.

Dazu starten wir zuerst Jupyter auf dem Server und geben den Port 8080 an:

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

Öffnen Sie dann in unserem Konsolenprogramm Cmder einen weiteren Tab (oberes MenĂŒ – Neue Konsolendialog) und verbinden Sie sich ĂŒber SSH am Port 8080 mit dem Server:

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

Beim Eingeben des ersten Befehls erhalten wir Links zur Öffnung von Jupyter in unserem Browser:

Um auf das Notizbuch zuzugreifen, öffnen Sie diese Datei in einem Browser:
        file:///root/.local/share/jupyter/runtime/nbserver-18788-open.html
    Oder kopieren Sie eine dieser URLs:
        http://localhost:8080/?token=cca0bd0b30857821194b9018a5394a4ed2322236f116d311
     oder http://127.0.0.1:8080/?token=cca0bd0b30857821194b9018a5394a4ed2322236f116d311

Nutzen Sie den Link fĂŒr localhost:8080. Kopieren Sie den vollstĂ€ndigen Pfad und fĂŒgen Sie ihn in die Adresszeile Ihres lokalen Browsers ein. Jupyter Notebook wird geöffnet.

Erstellen wir ein neues Notizbuch: Neu — Notizbuch — Python 3.

ÜberprĂŒfen wir, ob alle Komponenten, die wir installiert haben, korrekt funktionieren. Geben Sie ein Beispiel fĂŒr PyTorch in Jupyter ein und fĂŒhren Sie es aus (Taste AusfĂŒhren):

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

Das Ergebnis sollte etwa so aussehen:

Ihr erstes neuronales Netzwerk auf einer Grafikkarte (GPU). Ein Leitfaden fĂŒr AnfĂ€nger

Wenn Sie ein Àhnliches Ergebnis erhalten, haben wir alles richtig eingerichtet und können mit der Entwicklung des neuronalen Netzwerks beginnen!

Erstellen eines neuronalen Netzwerks

Wir werden ein neuronales Netzwerk zur Bilderkennung erstellen. Wir nehmen dies als Grundlage. die Richtlinien.

FĂŒr das Training des Netzwerks werden wir den öffentlichen Datensatz CIFAR10 verwenden. Er enthĂ€lt die Klassen: „Flugzeug“, „Auto“, „Vogel“, „Katze“, „Reh“, „Hund“, „Frosch“, „Pferd“, „Schiff“, „Lkw“. Die Bilder im CIFAR10 haben die GrĂ¶ĂŸe 3x32x32, also 3-kanalige Farbabbildungen mit einer GrĂ¶ĂŸe von 32×32 Pixeln.

Ihr erstes neuronales Netzwerk auf einer Grafikkarte (GPU). Ein Leitfaden fĂŒr AnfĂ€nger
FĂŒr unsere Arbeit verwenden wir das erstellte PyTorch-Paket fĂŒr die Bildbearbeitung – torchvision.

Wir werden die folgenden Schritte in der Reihenfolge durchfĂŒhren:

  • Laden und Normalisieren der Trainings- und TestdatensĂ€tze
  • Definieren des neuronalen Netzwerks
  • Training des Netzwerks mit den Trainingsdaten
  • Testen des Netzwerks mit den Testdaten
  • Wir wiederholen das Training und die Tests unter Verwendung von GPU

Den gesamten nachstehenden Code fĂŒhren wir in Jupyter Notebook aus.

Laden und Normalisieren von CIFAR10

Kopieren und fĂŒhren Sie den folgenden Code in Jupyter aus:


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 = ('Flugzeug', 'Auto', 'Vogel', 'Katze',
           'Reh', 'Hund', 'Frosch', 'Pferd', 'Schiff', 'Lkw')

Die Antwort sollte so aussehen:

Herunterladen von https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz nach ./data/cifar-10-python.tar.gz
Entpacken von ./data/cifar-10-python.tar.gz nach ./data
Dateien bereits heruntergeladen und ĂŒberprĂŒft

Lassen Sie uns einige Trainingsbilder zur ÜberprĂŒfung anzeigen:


import matplotlib.pyplot as plt
import numpy as np

# Funktionen zum Anzeigen eines Bildes

def imshow(img):
    img = img / 2 + 0.5     # Normalisieren
    npimg = img.numpy()
    plt.imshow(np.transpose(npimg, (1, 2, 0)))
    plt.show()

# Einige zufÀllige Trainingsbilder holen
dataiter = iter(trainloader)
images, labels = dataiter.next()

# Bilder anzeigen
imshow(torchvision.utils.make_grid(images))
# Labels ausgeben
print(' '.join('%5s' % classes[labels[j]] for j in range(4)))

Ihr erstes neuronales Netzwerk auf einer Grafikkarte (GPU). Ein Leitfaden fĂŒr AnfĂ€nger

Definieren des neuronalen Netzwerks

Schauen wir uns zunĂ€chst an, wie ein neuronales Netzwerk zur Bilderkennung funktioniert. Es handelt sich um ein einfaches Feedforward-Netzwerk. Es nimmt Eingabedaten entgegen, durchlĂ€uft diese schichtweise, und gibt schließlich die Ausgabedaten aus.

Ihr erstes neuronales Netzwerk auf einer Grafikkarte (GPU). Ein Leitfaden fĂŒr AnfĂ€nger

Lassen Sie uns ein Àhnliches Netzwerk in unserer Umgebung 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()

Lassen Sie uns auch die Verlustfunktion und den Optimierer definieren.


import torch.optim as optim

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

Training des Netzwerks mit den Trainingsdaten

Wir beginnen mit dem Training unseres neuronalen Netzwerks. Beachten Sie, dass Sie nach dem AusfĂŒhren dieses Codes eine Weile warten mĂŒssen, bis der Vorgang abgeschlossen ist. Bei mir hat es 5 Minuten gedauert. Das Training des Netzwerks benötigt Zeit.

 fĂŒr epoch in range(2): # Schleife ĂŒber das Dataset mehrere Male

 laufender_verlust = 0.0
 fĂŒr i, daten in enumerate(trainloader, 0):
 # Eingaben erhalten; daten sind eine Liste von [Eingaben, Labels]
 eingaben, labels = daten

 # Gradienten der Parameter zurĂŒcksetzen
 optimizer.zero_grad()

 # vorwĂ€rts + rĂŒckwĂ€rts + optimieren
 ausgaben = net(eingaben)
 verlust = criterion(ausgaben, labels)
 verlust.backward()
 optimizer.step()

 # Statistiken drucken
 laufender_verlust += verlust.item()
 wenn i % 2000 == 1999: # alle 2000 Mini-Batches drucken
 print('[%d, ] Verlust: %.3f' %
 (epoch + 1, i + 1, laufender_verlust / 2000))
 laufender_verlust = 0.0

print('Training abgeschlossen')

Wir erhalten folgendes Ergebnis:

Ihr erstes neuronales Netzwerk auf einer Grafikkarte (GPU). Ein Leitfaden fĂŒr AnfĂ€nger

Wir speichern unser trainiertes Modell:

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

Testen des Netzwerks mit den Testdaten

Wir haben das Netzwerk mit einem Trainingsdatensatz trainiert. Aber wir mĂŒssen ĂŒberprĂŒfen, ob das Netzwerk ĂŒberhaupt etwas gelernt hat.

Wir werden dies ĂŒberprĂŒfen, indem wir das Klassenlabel vorhersagen, das das neuronale Netzwerk ausgibt, und es auf Richtigkeit prĂŒfen. Wenn die Vorhersage korrekt ist, fĂŒgen wir das Beispiel der Liste der korrekten Vorhersagen hinzu.
Lassen Sie uns ein Bild aus dem Testdatensatz zeigen:

dataiter = iter(testloader)
images, labels = dataiter.next()

# Bilder ausgeben
imshow(torchvision.utils.make_grid(images))
print('GroundTruth: ', ' '.join('%5s' % classes[labels[j]] for j in range(4)))

Ihr erstes neuronales Netzwerk auf einer Grafikkarte (GPU). Ein Leitfaden fĂŒr AnfĂ€nger

Jetzt bitten wir das neuronale Netzwerk, uns zu sagen, was auf diesen Bildern zu sehen ist:


net = Net()
net.load_state_dict(torch.load(PATH))

outputs = net(images)

_, predicted = torch.max(outputs, 1)

print('Vorhersage: ', ' '.join('%5s' % classes[predicted[j]]
                              for j in range(4)))

Ihr erstes neuronales Netzwerk auf einer Grafikkarte (GPU). Ein Leitfaden fĂŒr AnfĂ€nger

Die Ergebnisse scheinen ziemlich gut zu sein: Das Netzwerk hat drei von vier Bildern korrekt identifiziert.

Schauen wir uns an, wie das Netzwerk im gesamten Datensatz funktioniert.


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('Genauigkeit des Netzwerks bei den 10000 Testbildern: %d %%' % (
    100 * correct / total))

Ihr erstes neuronales Netzwerk auf einer Grafikkarte (GPU). Ein Leitfaden fĂŒr AnfĂ€nger

Es scheint, als wĂŒsste das Netzwerk etwas und funktioniert. Wenn es die Klassen zufĂ€llig identifizieren wĂŒrde, wĂ€re die Genauigkeit bei 10 %.

Sehen wir uns jetzt an, welche Klassen das Netzwerk besser erkennt:

klasse_richtig = list(0. fĂŒr i in range(10))
klasse_total = list(0. fĂŒr i in range(10))
mit torch.no_grad():
 fĂŒr daten in testloader:
 bilder, labels = daten
 ausgaben = net(bilder)
 _, vorhergesagt = torch.max(ausgaben, 1)
 c = (vorhergesagt == labels).squeeze()
 fĂŒr i in range(4):
 label = labels[i]
 klasse_richtig[label] += c[i].item()
 klasse_total[label] += 1


fĂŒr i in range(10):
 print('Genauigkeit von %5s : %%' % (
 klassen[i], 100 * klasse_richtig[i] / klasse_total[i]))

Ihr erstes neuronales Netzwerk auf einer Grafikkarte (GPU). Ein Leitfaden fĂŒr AnfĂ€nger

Es scheint, dass das Netzwerk Autos und Schiffe am besten erkennt: 71 % Genauigkeit.

Jetzt funktioniert das Netzwerk. Lassen Sie uns versuchen, es auf die Grafikkarte (GPU) zu ĂŒbertragen und sehen, was sich Ă€ndert.

Training des neuronalen Netzwerks auf der GPU

Zuerst erklĂ€re ich kurz, was CUDA ist. CUDA (Compute Unified Device Architecture) ist eine von NVIDIA entwickelte Plattform fĂŒr paralleles Rechnen, die allgemeine Berechnungen auf Grafikkarten (GPU) ermöglicht. Mit CUDA können Entwickler ihre Rechenanwendungen erheblich beschleunigen, indem sie die LeistungsfĂ€higkeit von Grafikkarten nutzen. Auf unserem Server, den wir erworben haben, ist diese Plattform bereits installiert.

Lassen Sie uns zunÀchst unsere GPU als das erste sichtbare CUDA-GerÀt festlegen.

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
# Angenommen, wir befinden uns auf einer CUDA-Maschine, sollte dies ein CUDA-GerÀt ausgeben:
print(device)

Ihr erstes neuronales Netzwerk auf einer Grafikkarte (GPU). Ein Leitfaden fĂŒr AnfĂ€nger

Wir senden das Netzwerk an die GPU:

net.to(device)

Außerdem mĂŒssen wir die Eingaben und Ziele bei jedem Schritt ebenfalls an die GPU senden:

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

Lassen Sie uns das erneute Training des Netzwerks bereits auf der GPU starten:

importiere torch.optim als optim

kriterium = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
fĂŒr epoch in range(2): # Schleife ĂŒber das Dataset mehrere Male

 laufender_verlust = 0.0
 fĂŒr i, daten in enumerate(trainloader, 0):
 # Eingaben erhalten; daten sind eine Liste von [Eingaben, Labels]
 eingaben, labels = daten[0].to(device), daten[1].to(device)

 # Gradienten der Parameter zurĂŒcksetzen
 optimizer.zero_grad()

 # vorwĂ€rts + rĂŒckwĂ€rts + optimieren
 ausgaben = net(eingaben)
 verlust = kriterium(ausgaben, labels)
 verlust.backward()
 optimizer.step()

 # Statistiken drucken
 laufender_verlust += verlust.item()
 wenn i % 2000 == 1999: # alle 2000 Mini-Batches drucken
 print('[%d, ] Verlust: %.3f' %
 (epoch + 1, i + 1, laufender_verlust / 2000))
 laufender_verlust = 0.0

print('Training abgeschlossen')

Dieses Mal dauerte das Training des Netzwerks etwa 3 Minuten. Zum Vergleich: Der gleiche Schritt dauerte auf einer herkömmlichen CPU 5 Minuten. Der Unterschied ist nicht signifikant, da unser Netzwerk nicht besonders groß ist. Bei der Verwendung grĂ¶ĂŸerer Datenmengen wird der Geschwindigkeitsunterschied zwischen GPU und traditioneller CPU zunehmen.

Das scheint alles zu sein. Was wir erreicht haben:

  • Wir haben untersucht, was eine GPU ist, und einen Server ausgewĂ€hlt, auf dem sie installiert ist;
  • Wir haben die Programmierumgebung fĂŒr die Erstellung des neuronalen Netzwerks eingerichtet;
  • Wir haben ein neuronales Netzwerk zur Bilderkennung erstellt und es trainiert;
  • Wir haben das Netzwerktraining mit GPU-UnterstĂŒtzung wiederholt und eine Geschwindigkeitssteigerung erzielt.

Ich beantworte gerne Fragen in den Kommentaren.

Quelle: habr.com

ZuverlĂ€ssiges Webhosting mit DDoS-Schutz, VPS- und VDS-Server kaufen đŸ”„ ZuverlĂ€ssiges Webhosting mit DDoS-Schutz, VPS- und VDS-Server kaufen | ProHoster