
I denna artikel kommer jag att förklara hur du pÄ 30 minuter kan stÀlla in en miljö för maskininlÀrning, skapa ett neuralt nÀtverk för bildigenkÀnning och sedan köra samma nÀtverk pÄ en grafisk processor (GPU).
LÄt oss först definiera vad ett neuralt nÀtverk Àr.
I vĂ„rt fall Ă€r det en matematisk modell samt dess program- eller hĂ„rdvaruimplementation, uppbyggd enligt principerna för organisation och funktion av biologiska neurala nĂ€tverk â nĂ€tverk av nervceller i en levande organism. Detta begrepp uppstod vid studiet av processer i hjĂ€rnan och i ett försök att modellera dessa processer.
Neurala nÀtverk programmeras inte pÄ det traditionella sÀttet, de trÀnas. Möjligheten att trÀna Àr en av de största fördelarna med neurala nÀtverk jÀmfört med traditionella algoritmer. Tekniskt sett innebÀr trÀning att hitta vikterna pÄ kopplingarna mellan neuroner. Under trÀningsprocessen kan det neurala nÀtverket identifiera komplexa beroenden mellan ingÄngs- och utgÄngsdata, samt utföra generalisering.
Ur ett maskininlÀrningsperspektiv Àr ett neuralt nÀtverk ett specifikt fall av mönsterigenkÀnning, diskriminantanalyser, klusteranalysmetoder och andra metoder.
Utrustning
Först lÄt oss gÄ igenom hÄrdvaran. Vi behöver en server med ett installerat operativsystem Linux. HÄrdvaran för maskininlÀrningssystem behöver vara tillrÀckligt kraftfull och dÀrmed dyr. För dem som inte har en bra dator tillgÀnglig rekommenderar jag att titta pÄ erbjudanden frÄn molnleverantörer. Den behövda servern kan snabbt hyras och man betalar bara för den tid som anvÀnds.
I projekt dÀr det krÀvs skapande av neurala nÀtverk anvÀnder jag servrar frÄn en av de ryska molnleverantörerna. Företaget erbjuder molnservrar speciellt för maskininlÀrning med kraftfulla grafiska processorer (GPU) Tesla V100 frÄn NVIDIA. Kort sagt: anvÀndning av en server med GPU kan vara tiotals gÄnger mer effektiv (snabb) jÀmfört med en motsvarande server dÀr berÀkningar görs av en CPU (den vÀlkÀnda centrala processorn). Detta uppnÄs tack vare sÀrskild arkitektur för GPU, som snabbare hanterar berÀkningar.
För att genomföra exemplen som beskrivs nedan har vi hyrt en sÄdan server i nÄgra dagar:
- SSD-disk 150 GB
- RAM 32 GB
- Processor Tesla V100 16 Gb med 4 kÀrnor
PĂ„ maskinen installerades Ubuntu 18.04.
Installerar miljön
Nu ska vi installera allt som behövs för att arbeta pÄ servern. Eftersom vÄr artikel framför allt À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 man konfigurerar miljön görs via kommandoraden. De flesta anvÀndare anvÀnder Windows som arbets-OS. Standardkonsolen i detta operativsystem lÀmnar mycket att önska. DÀrför kommer vi att anvÀnda ett bekvÀmt verktyg . Ladda ner mini-versionen och starta Cmder.exe. DÀrefter mÄste vi koppla upp oss mot servern via SSH-protokollet:
ssh root@server-ip-or-hostnameI stÀllet för server-ip-or-hostname anger du IP-adressen eller DNS-namnet pÄ din server. Skriv sedan in ditt lösenord, och vid en lyckad anslutning bör vi fÄ nÄgot liknande detta meddelande.
Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-74-generic x86_64)Det frÀmsta sprÄket för att utveckla ML-modeller Àr Python. Den mest populÀra plattformen för dess anvÀndning pÄ Linux Àr .
LÄt oss installera det pÄ vÄr server.
Vi börjar med att uppdatera den lokala paketchefen:
sudo apt-get updateInstallerar curl (kommandoradsverktyg):
sudo apt-get install curlLaddar ner den senaste versionen av Anaconda Distribution:
cd /tmp
curl âO https://repo.anaconda.com/archive/Anaconda3-2019.10-Linux-x86_64.shStartar installationen:
bash Anaconda3-2019.10-Linux-x86_64.shUnder installationen behöver du bekrÀfta licensavtalet. Vid en lyckad installation bör du se detta:
Thank you for installing Anaconda3!För utveckling av ML-modeller finns det nu ett antal ramverk tillgÀngliga, vi arbetar med de mest populÀra: och .
AnvÀndningen av ramverket gör det möjligt att öka hastigheten pÄ utvecklingen och anvÀnda redan fÀrdiga verktyg för standarduppgifter.
I det hÀr exemplet kommer vi att arbeta med PyTorch. Vi installerar det:
conda install pytorch torchvision cudatoolkit=10.1 -c pytorchNu behöver vi starta Jupyter Notebook â ett populĂ€rt utvecklingsverktyg för ML-specialister. Det gör att du kan skriva kod och omedelbart se resultaten av dess körning. Jupyter Notebook ingĂ„r i Anaconda och Ă€r redan installerad pĂ„ vĂ„r server. Vi behöver ansluta till den frĂ„n vĂ„rt skrivbordssystem.
För att göra detta först startar vi Jupyter pÄ servern och anger port 8080:
jupyter notebook --no-browser --port=8080 --allow-rootDĂ€refter öppnar vi en ny flik i vĂ„r konsol Cmder (övre menyn â New console dialog) och ansluter till servern via SSH pĂ„ port 8080:
ssh -L 8080:localhost:8080 root@server-ip-or-hostnameNÀr vi anger den 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
Vi anvÀnder lÀnken för localhost:8080. Kopiera den fullstÀndiga sökvÀgen och klistra in den i adressfÀltet i din lokala webblÀsare. Jupyter Notebook öppnas.
Vi skapar en ny notebook: New â Notebook â Python 3.
Vi kontrollerar att alla komponenter vi har installerat fungerar korrekt. Vi skriver in ett exempel pÄ PyTorch-kod i Jupyter och kör det (knapp: Run):
from __future__ import print_function
import torch
x = torch.rand(5, 3)
print(x)
Resultatet bör se ungefÀr ut sÄ hÀr:

Om du fÄr ett liknande resultat har vi konfigurerat allt korrekt och kan börja utveckla ett neuralt nÀtverk!
Vi skapar ett neuralt nÀtverk
Vi kommer att skapa ett neuralt nÀtverk för bildigenkÀnning. Vi tar detta som utgÄngspunkt .
För trĂ€ning av nĂ€tverket kommer vi att anvĂ€nda den offentliga datamĂ€ngden CIFAR10. Den har klasser: "flygplan", "bil", "fĂ„gel", "katt", "hjort", "hund", "groda", "hĂ€st", "skepp", "lastbil". Bilderna i CIFAR10 har storleken 3x32x32, det vill sĂ€ga 3-kanaliga fĂ€rgbilder med storleken 32Ă32 pixlar.

För vĂ„rt arbete kommer vi att anvĂ€nda den skapade PyTorch-paketet för bildbehandling â torchvision.
Vi kommer att genomföra följande steg i ordning:
- Nedladdning och normalisering av trÀningsoch testdatamÀngder
- Definiera det neuronala nÀtverket
- TrÀna nÀtverket pÄ trÀningsdata
- Testa nÀtverket med testdata
- Vi upprepar trÀningen och testningen med hjÀlp av GPU
All kod nedan kommer vi att köra i Jupyter Notebook.
Nedladdning och normalisering av 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 ska se ut sÄ hÀr:
Nedladdning av https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz till ./data/cifar-10-python.tar.gz
Extrahering av ./data/cifar-10-python.tar.gz till ./data
Filer har redan laddats ner och verifieratsVi kommer att visa nÄgra trÀningsbilder för verifiering:
import matplotlib.pyplot as plt
import numpy as np
# funktioner för att visa en bild
def imshow(img):
img = img / 2 + 0.5 # avnormalisera
npimg = img.numpy()
plt.imshow(np.transpose(npimg, (1, 2, 0)))
plt.show()
# hÀmta nÄgra slumpmÀssiga trÀningsbilder
dataiter = iter(trainloader)
images, labels = dataiter.next()
# visa bilder
imshow(torchvision.utils.make_grid(images))
# skriv ut etiketter
print(' '.join('%5s' % classes[labels[j]] for j in range(4)))

Definiera det neuronala nÀtverket
Vi börjar med att se hur ett neuralt nÀtverk för bildigenkÀnning fungerar. Det Àr ett enkelt feedforward-nÀtverk. Det tar indata, skickar dem genom flera lager ett efter ett och ger slutligen utdata.

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 ocksÄ en förlustfunktion och en optimizer
import torch.optim as optim
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)TrÀna nÀtverket pÄ trÀningsdata
Vi börjar trÀningen av vÄrt neurala nÀtverk. Jag vill pÄpeka att efter att du kör den hÀr koden, mÄste du vÀnta en stund tills den Àr klar. Det tog mig 5 minuter. Att trÀna nÀtverket tar tid.
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:

Sparar vÄr trÀnade modell:
PATH = './cifar_net.pth'
torch.save(net.state_dict(), PATH)Testa nÀtverket med testdata
Vi har trÀnat nÀtverket med hjÀlp av trÀningsdata. Men vi mÄste kontrollera om nÀtverket faktiskt har lÀrt sig nÄgot.
Vi kommer att kontrollera detta genom att förutsÀga klassens etikett som det neurala nÀtverket ger och kontrollera den mot den verkliga etiketten. Om förutsÀgelsen Àr korrekt lÀgger vi till exemplet i listan över korrekta förutsÀgelser.
LÄt oss visa en bild frÄn testdatasetet:
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))) 
Nu ber vi det neurala nÀtverket att berÀtta för oss 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)))

Resultaten verkar ganska bra: nÀtverket identifierade tre bilder korrekt av fyra.
LÄt oss se hur nÀtverket presterar pÄ hela datasetet.
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)) 
Det verkar som om nÀtverket vet nÄgot och fungerar. Om det hade klassificerat pÄ ett slumpmÀssigt sÀtt skulle noggrannheten vara 10%.
LÄt oss nu se vilka klasser nÀtverket identifierar bÀst:
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])) 
Det verkar som att nÀtverket mest korrekt identifierar bilar och fartyg: 71% noggrannhet.
SÄ nÀtverket fungerar. Nu ska vi försöka köra det pÄ en grafisk processor (GPU) och se vad som förÀndras.
TrÀning av neuronnÀt pÄ GPU
Först ska jag kort förklara vad CUDA Ă€r. CUDA (Compute Unified Device Architecture) â en plattform för parallella berĂ€kningar, utvecklad av NVIDIA, för allmĂ€nna berĂ€kningar pĂ„ grafiska processorer (GPU). Med CUDA kan utvecklare avsevĂ€rt snabba upp berĂ€kningsapplikationer genom att utnyttja grafiska processorer. PĂ„ vĂ„r server, som vi har köpt, Ă€r denna plattform redan installerad.
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")
# Anta att vi Àr pÄ en CUDA-maskin, detta bör skriva ut en CUDA-enhet:
print(device) 
Skickar nÀtverket till GPU:
net.to(device)Vi mÄste ocksÄ skicka indata och mÄl vid varje steg till GPU:
inputs, labels = data[0].to(device), data[1].to(device)LÄt oss trÀna nÀtverket igen, denna gÄng pÄ 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')Denna gÄng var nÀtverkets trÀningade tid ungefÀr 3 minuter. Kom ihÄg att samma steg pÄ en vanlig processor tog 5 minuter. Skillnaden Àr inte betydande, och det beror pÄ att vÄrt nÀtverk inte Àr sÄ stort. NÀr vi anvÀnder större datamÀngder för trÀning kommer skillnaden i hastighet mellan GPU och traditionell processor att öka.
Det verkar som att vi har kommit till slutet. Vad vi lyckades Ästadkomma:
- Vi gick igenom vad en GPU Àr och valde en server dÀr den Àr installerad;
- Vi stÀllde in den programmiljö som krÀvs för att skapa ett neuronnÀt;
- Vi skapade ett neuronnÀt för bildigenkÀnning och trÀnade det;
- Vi upprepade trÀningen av nÀtverket med hjÀlp av GPU och fick en hastighetsförbÀttring.
Jag ser fram emot att svara pÄ frÄgor i kommentarerna.
KĂ€lla: habr.com
