U ovom ću vam članku reći kako postaviti okruženje za strojno učenje u 30 minuta, stvoriti neuronsku mrežu za prepoznavanje slike, a zatim pokrenuti istu mrežu na grafičkom procesoru (GPU).
Prvo, definirajmo što je neuronska mreža.
U našem slučaju, to je matematički model, kao i njegova softverska ili hardverska izvedba, izgrađena na principu organizacije i funkcioniranja bioloških neuronskih mreža - mreža živčanih stanica živog organizma. Ovaj koncept nastao je tijekom proučavanja procesa koji se odvijaju u mozgu i pokušaja modeliranja tih procesa.
Neuronske mreže nisu programirane u uobičajenom smislu te riječi, one se treniraju. Sposobnost učenja jedna je od glavnih prednosti neuronskih mreža u odnosu na tradicionalne algoritme. Tehnički, učenje se sastoji od pronalaženja koeficijenata veza između neurona. Tijekom procesa obuke, neuronska mreža je u stanju identificirati složene ovisnosti između ulaznih i izlaznih podataka, kao i izvesti generalizaciju.
Sa stajališta strojnog učenja, neuronska mreža je poseban slučaj metoda prepoznavanja uzoraka, diskriminativne analize, metoda klasteriranja i drugih metoda.
Оборудование
Prvo, pogledajmo opremu. Trebamo poslužitelj s instaliranim operativnim sustavom Linux. Oprema potrebna za upravljanje sustavima strojnog učenja prilično je moćna i, kao rezultat toga, skupa. Za one koji nemaju dobar stroj pri ruci, preporučujem da obratite pozornost na ponude pružatelja usluga oblaka. Traženi server možete brzo unajmiti i platiti samo vrijeme korištenja.
U projektima u kojima je potrebno izraditi neuronske mreže koristim poslužitelje jednog od ruskih pružatelja usluga oblaka. Tvrtka nudi poslužitelje u oblaku za najam posebno za strojno učenje sa snažnim Tesla V100 grafičkim procesorima (GPU) tvrtke NVIDIA. Ukratko: korištenje poslužitelja s GPU-om može biti desetke puta učinkovitije (brže) u usporedbi s poslužiteljem slične cijene koji za izračune koristi CPU (dobro poznata središnja procesorska jedinica). To se postiže zahvaljujući značajkama GPU arhitekture, koja se brže nosi s izračunima.
Za implementaciju dolje opisanih primjera kupili smo sljedeći poslužitelj na nekoliko dana:
- SSD disk 150 GB
- RAM 32 GB
- Tesla V100 16 Gb procesor sa 4 jezgre
Instalirali smo Ubuntu 18.04 na našem računalu.
Postavljanje okoline
Sada idemo instalirati sve što je potrebno za rad na poslužitelju. Budući da je naš članak prvenstveno za početnike, govorit ću o nekim točkama koje će im biti korisne.
Velik dio posla pri postavljanju okruženja obavlja se putem naredbenog retka. Većina korisnika koristi Windows kao radni OS. Standardna konzola u ovom OS-u ostavlja mnogo želja. Stoga ćemo koristiti prikladan alat
ssh root@server-ip-or-hostname
Umjesto server-ip-or-hostname, navedite IP adresu ili DNS naziv vašeg poslužitelja. Zatim unesite lozinku i ako je veza uspješna, trebali bismo primiti poruku sličnu ovoj.
Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-74-generic x86_64)
Glavni jezik za razvoj ML modela je Python. A najpopularnija platforma za njegovu upotrebu na Linuxu je
Instalirajmo ga na naš poslužitelj.
Počinjemo s ažuriranjem lokalnog upravitelja paketa:
sudo apt-get update
Instalirajte curl (uslužni program naredbenog retka):
sudo apt-get install curl
Preuzmite najnoviju verziju Anaconda Distribution:
cd /tmp
curl –O https://repo.anaconda.com/archive/Anaconda3-2019.10-Linux-x86_64.sh
Započnimo instalaciju:
bash Anaconda3-2019.10-Linux-x86_64.sh
Tijekom postupka instalacije od vas će se tražiti da potvrdite licencni ugovor. Nakon uspješne instalacije trebali biste vidjeti ovo:
Thank you for installing Anaconda3!
Sada su stvoreni mnogi okviri za razvoj ML modela; radimo s najpopularnijima:
Korištenje okvira omogućuje vam povećanje brzine razvoja i korištenje gotovih alata za standardne zadatke.
U ovom primjeru radit ćemo s PyTorchom. Instalirajmo ga:
conda install pytorch torchvision cudatoolkit=10.1 -c pytorch
Sada moramo pokrenuti Jupyter Notebook, popularan razvojni alat za stručnjake za ML. Omogućuje vam da napišete kod i odmah vidite rezultate njegovog izvršenja. Jupyter Notebook uključen je u Anacondu i već je instaliran na našem poslužitelju. Morate se spojiti na njega s našeg desktop sustava.
Da bismo to učinili, prvo ćemo pokrenuti Jupyter na poslužitelju navodeći port 8080:
jupyter notebook --no-browser --port=8080 --allow-root
Zatim, otvaranjem druge kartice u našoj Cmder konzoli (gornji izbornik - dijaloški okvir Nova konzola) spojit ćemo se preko porta 8080 na poslužitelj putem SSH-a:
ssh -L 8080:localhost:8080 root@server-ip-or-hostname
Kada unesemo prvu naredbu, ponudit će nam se linkovi za otvaranje Jupytera u našem pregledniku:
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
Iskoristimo vezu za localhost:8080. Kopirajte cijeli put i zalijepite ga u adresnu traku lokalnog preglednika vašeg računala. Otvorit će se Jupyter Notebook.
Kreirajmo novu bilježnicu: Novo - Bilježnica - Python 3.
Provjerimo ispravan rad svih komponenti koje smo instalirali. Unesite primjer PyTorch koda u Jupyter i pokrenite izvršenje (gumb Pokreni):
from __future__ import print_function
import torch
x = torch.rand(5, 3)
print(x)
Rezultat bi trebao biti nešto poput ovoga:
Ako imate sličan rezultat, onda smo sve ispravno konfigurirali i možemo početi razvijati neuronsku mrežu!
Stvaranje neuronske mreže
Napravit ćemo neuronsku mrežu za prepoznavanje slike. Uzmimo ovo kao osnovu
Koristit ćemo javno dostupan skup podataka CIFAR10 za obuku mreže. Ima klase: "avion", "auto", "ptica", "mačka", "jelen", "pas", "žaba", "konj", "brod", "kamion". Slike u CIFAR10 su 3x32x32, odnosno 3-kanalne slike u boji od 32x32 piksela.
Za rad ćemo koristiti paket koji je kreirao PyTorch za rad sa slikama - torchvision.
Napravit ćemo sljedeće korake redom:
- Učitavanje i normaliziranje skupova podataka za obuku i testiranje
- Definicija neuronske mreže
- Mrežna obuka na podacima o obuci
- Mrežno testiranje na testnim podacima
- Ponovimo obuku i testiranje koristeći GPU
Izvršit ćemo sav donji kod u Jupyter Notebooku.
Učitavanje i normaliziranje CIFAR10
Kopirajte i pokrenite sljedeći kod u Jupyteru:
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')
Odgovor bi trebao biti:
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
Prikažimo nekoliko slika treninga za testiranje:
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)))
Definicija neuronske mreže
Razmotrimo prvo kako funkcionira neuronska mreža za prepoznavanje slika. Ovo je jednostavna mreža od točke do točke. Uzima ulazne podatke, prolazi ih kroz nekoliko slojeva jedan po jedan, a zatim konačno proizvodi izlazne podatke.
Kreirajmo sličnu mrežu u našem okruženju:
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()
Također definiramo funkciju gubitka i optimizator
import torch.optim as optim
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
Mrežna obuka na podacima o obuci
Počnimo trenirati našu neuronsku mrežu. Imajte na umu da ćete nakon pokretanja ovog koda morati pričekati neko vrijeme dok se posao ne završi. Trebalo mi je 5 minuta. Potrebno je vrijeme za treniranje mreže.
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')
Dobivamo sljedeći rezultat:
Spremamo naš trenirani model:
PATH = './cifar_net.pth'
torch.save(net.state_dict(), PATH)
Mrežno testiranje na testnim podacima
Istrenirali smo mrežu pomoću skupa podataka za obuku. Ali moramo provjeriti je li mreža uopće nešto naučila.
To ćemo testirati predviđanjem oznake klase koju neuronska mreža isporučuje i testiranjem da vidimo je li točna. Ako je predviđanje točno, dodajemo uzorak na popis točnih predviđanja.
Pokažimo sliku iz testnog skupa:
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)))
Sada zamolimo neuronsku mrežu da nam kaže što je na ovim slikama:
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)))
Rezultati se čine prilično dobrima: mreža je točno identificirala tri od četiri slike.
Pogledajmo kako se mreža ponaša u cijelom skupu podataka.
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))
Čini se da mreža nešto zna i radi. Kad bi nasumce odredio klase, točnost bi bila 10%.
Sada da vidimo koje klase mreža bolje identificira:
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]))
Čini se da je mreža najbolja u identificiranju automobila i brodova: 71% točnosti.
Dakle, mreža radi. Pokušajmo sada prenijeti njegov rad na grafički procesor (GPU) i vidjeti što se mijenja.
Obuka neuronske mreže na GPU-u
Prvo ću ukratko objasniti što je CUDA. CUDA (Compute Unified Device Architecture) je paralelna računalna platforma koju je razvila NVIDIA za općenito računalstvo na grafičkim procesorskim jedinicama (GPU). Uz CUDA programeri mogu dramatično ubrzati računalne aplikacije iskorištavanjem snage GPU-a. Ova platforma je već instalirana na našem serveru koji smo kupili.
Najprije definirajmo naš GPU kao prvi vidljivi cuda uređaj.
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 )
Slanje mreže na GPU:
net.to(device)
Također ćemo morati poslati ulaze i ciljeve u svakom koraku GPU-u:
inputs, labels = data[0].to(device), data[1].to(device)
Idemo ponovno uvježbati mrežu na GPU-u:
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')
Ovoga puta mrežni trening je trajao oko 3 minute. Podsjetimo, ista faza na konvencionalnom procesoru trajala je 5 minuta. Razlika nije značajna, to se događa jer naša mreža nije tako velika. Kada koristite velike nizove za obuku, razlika između brzine GPU-a i tradicionalnog procesora će se povećati.
Čini se da je to sve. Što smo uspjeli napraviti:
- Pogledali smo što je GPU i odabrali poslužitelj na kojem je instaliran;
- Postavili smo softversko okruženje za stvaranje neuronske mreže;
- Napravili smo neuronsku mrežu za prepoznavanje slika i istrenirali je;
- Ponovili smo mrežnu obuku pomoću GPU-a i dobili povećanje brzine.
Rado ću odgovoriti na pitanja u komentarima.
Izvor: www.habr.com