Rrjeti juaj i parë nervor në procesorin grafik (GPU). Udhëzues për fillestarë

Rrjeti juaj i parë nervor në procesorin grafik (GPU). Udhëzues për fillestarë
Në këtë artikull, do t'ju tregoj se si të konfiguroni një mjedis për mësimin e makinave për 30 minuta, të krijoni një rrjet nervor për njohjen e imazheve dhe pastaj ta ekzekutoni të njëjtin rrjet në një procesor grafik (GPU).

Së pari, le të përcaktojmë se çfarë është një rrjet nervor.

Në rastin tonë, ky është një model matematikor, si dhe një zbatim i tij programor ose harduerik, i ndërtuar sipas parimeve të organizimit dhe funksionimit të rrjeteve nervore biologjike - rrjetet e qelizave nervore në një organizëm të gjallë. Ky koncept lindi gjatë studimit të proceseve që ndodhin në tru dhe përpjekjeve për t'i modeli këto procese.

Rrjetet nervore nuk programohen në kuptimin e zakonshëm të fjalës; ato mësohen. Mundësia për të mësuar është një nga avantazhet kryesore të rrjeteve nervore krahasuar me algoritmet tradicionale. Teknikisht, të mësuarit përfshin gjetjen e koeficientëve të lidhjeve midis neuroneve. Gjatë procesit të të mësuarit, një rrjet nervor mund të identifikojë varësi të ndërlikuara midis të dhënave hyrëse dhe atyre dalëse, si dhe të kryejë përgjithësime.

Sipas pikëpamjes së mësimit të makinave, një rrjet nervor përbën një rast të veçantë të metodave të njohjes së modeleve, analizës diskriminuese, metodave të klasifikimit dhe metodave të tjera.

Pajisje

Së pari, le të merremi me pajisjet. Ne na nevojitet një server me një sistem operativ Linux të instaluar në të. Pajisjet për sistemet e mësimit të makinave kërkojnë të jenë mjaft të fuqishme dhe për pasojë, të shtrenjta. Ata që nuk kanë një makinë të mirë në dorë, u rekomandoj të shqyrtojnë ofertat e ofruesve të cloud. Serverin e nevojshëm mund ta merrni me qira shpejt dhe të paguani vetëm për kohën e përdorimit.

Në projektet ku nevojitet krijimi i rrjeteve nervore, unë përdor serverë nga një nga ofruesit e cloud në Rusi. Kompania ofron serverë cloud në qira të dizajnuar veçanërisht për mësimin e makinave me procesorë grafikë të fuqishëm (GPU) Tesla V100 nga NVIDIA. Në një përmbledhje: përdorimi i një serveri me GPU mund të jetë disa herë më efikas (i shpejtë) në krahasim me një server të ngjashëm në kosto ku për llogaritjet përdoret CPU (procesori qendror që është i njohur për të gjithë). Kjo arrihet përmes veçorive të arkitekturës së GPU-së, e cila e bën llogaritjen më të shpejtë.

Për të realizuar shembujt e përshkruar më poshtë, ne blëmë një server të tillë për disa ditë:

  • TĂ« dhĂ«na SSD 150 GB
  • RAM 32 GB
  • Procesori Tesla V100 16 Gb me 4 bĂ«rthama

Në makinë na u instalua Ubuntu 18.04.

Instalojmë mjedisin

Tani do të instalojmë në server gjithçka e nevojshme për punë. Duke qenë se artikulli ynë është kryesisht për fillestarët, do të flas për disa pika që do t'i shërbejnë ata.

Pjesa më e madhe e punës gjatë konfigurimit të mjedisit bëhet përmes komandës. Shumica e përdoruesve si sistem operativ punues përdorin Windows. Konsola standarde në këtë OS lë për të dëshiruar. Prandaj do të përdorim një instrument të përshtatshëm. Cmder/. Shkarkojmë versionin mini dhe hapim Cmder.exe. Më pas është e nevojshme të lidhemi me serverin përmes protokollit SSH:

ssh root@server-ip-or-hostname

Në vend të server-ip-or-hostname, jepni adresën IP ose emrin DNS të serverit tuaj. Më pas shkruani fjalëkalimin dhe, nëse lidheni me sukses, duhet të merrni një mesazh të tillë.

Mirë se erdhët në Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-74-generic x86_64)

Gjuha kryesore për zhvillimin e modeleve ML është Python. Dhe platforma më e njohur për ta përdorur në Linux është Anaconda.

Do ta instalojmë atë në serverin tonë.

Fillojmë me aktualizimin e menaxherit të pakot lokal:

sudo apt-get update

Instalojmë curl (programin ndihmës të komandës):

sudo apt-get install curl

Shkarkojmë versionin më të fundit të Anaconda Distribution:

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

Fillojmë instalimin:

bash Anaconda3-2019.10-Linux-x86_64.sh

Gjatë instalimit do t'ju duhet të konfirmoni marrëveshjen e licencës. Pas instalimit të suksesshëm, duhet të shihni këtë:

Faleminderit që instaluat Anaconda3!

Për zhvillimin e modeleve ML tani janë krijuar shumë framework-e, ne punojmë me ato më të njohura: PyTorch dhe Tensorflow.

Përdorimi i framework-ut lejon të rritet shpejtësia e zhvillimit dhe të përdoren tashmë mjete të gatshme për detyra standarde.

Në këtë shembull do të punojmë me PyTorch. Le të instalojmë atë:

conda install pytorch torchvision cudatoolkit=10.1 -c pytorch

Tani na nevojitet tĂ« fillojmĂ« Jupyter Notebook — njĂ« instrument zhvillimi popullor pĂ«r specialistĂ«t e ML. Ai lejon tĂ« shkruajmĂ« kod dhe tĂ« shohim menjĂ«herĂ« rezultatet e ekzekutimit tĂ« tij. Jupyter Notebook Ă«shtĂ« pjesĂ« e Anaconda dhe tashmĂ« Ă«shtĂ« instaluar nĂ« serverin tonĂ«. Duhet tĂ« lidhemi me tĂ« nga sistemi ynĂ« tĂ« desktopit.

Për këtë, fillimisht do ta nisnim Jupyter në serverin duke caktuar portin 8080:

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

MĂ« pas, hapim njĂ« skedĂ« tjetĂ«r nĂ« konsolĂ«n tonĂ« Cmder (menyja e sipĂ«rme — dialogu New console) dhe lidhim pĂ«rmes portit 8080 me serverin pĂ«rmes SSH:

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

Kur të futim koman ndihmëse, do na ofrohen lidhje për të hapur Jupyter në shfletuesin tonë:

Për të aksesuar notebook-un, hapni këtë skedë në shfletues:
        file://root/.local/share/jupyter/runtime/nbserver-18788-open.html
    Ose kopjoni dhe ngjitni njërin nga këto URL:
        http://localhost:8080/?token=cca0bd0b30857821194b9018a5394a4ed2322236f116d311
     ose http://127.0.0.1:8080/?token=cca0bd0b30857821194b9018a5394a4ed2322236f116d311

Do të përdorim lidhjen për localhost:8080. Kopjoni rrugën e plotë dhe ngjitni atë në shiritin e adresës së shfletuesit tuaj lokal. Jupyter Notebook do të hapet.

TĂ« krijojmĂ« njĂ« notebook tĂ« ri: New — Notebook — Python 3.

Do të verifikojmë funksionimin e saktë të të gjithë komponenteve që kemi instaluar. Do të fusim në Jupyter një shembull të kodit PyTorch dhe do të fillojmë ekzekutimin (butoni Run):

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

Rezultati duhet të jetë diçka e tillë:

Rrjeti juaj i parë nervor në procesorin grafik (GPU). Udhëzues për fillestarë

NĂ«se keni njĂ« rezultat tĂ« ngjashĂ«m — atĂ«herĂ« e kemi konfigurimin e saktĂ« dhe mund tĂ« fillojmĂ« me zhvillimin e rrjetit nervor!

Krijojmë një rrjet nervor

Do të krijojmë një rrjet nervor për njohjen e imazheve. Do të marrim këtë si bazë manual.

PĂ«r trajnimin e rrjetit do tĂ« pĂ«rdorim njĂ« set tĂ« dhĂ«nash tĂ« hapura, CIFAR10. Ai ka klasat: «avioni», «automobili», «zogu», «maca», «gjahu», «qeni», «frĂ«ngjia», «kalorĂ«si», «anija», «kamioni». Imazhet nĂ« CIFAR10 kanĂ« madhĂ«si 3x32x32, pra janĂ« imazhe me ngjyra me 3 kanale, me pĂ«rmasat 32×32 piksel.

Rrjeti juaj i parë nervor në procesorin grafik (GPU). Udhëzues për fillestarë
PĂ«r punĂ« do tĂ« pĂ«rdorim paketĂ«n e krijuar nĂ« PyTorch pĂ«r tĂ« punuar me imazhet — torchvision.

Do të kryejmë hapat e mëposhtëm në rend:

  • Shkarkimi dhe normalizimi i setit tĂ« tĂ« dhĂ«nave pĂ«r trajnim dhe testim
  • PĂ«rcaktimi i rrjetit nervor
  • Trajnimi i rrjetit me tĂ« dhĂ«nat e trajnimit
  • Testimi i rrjetit me tĂ« dhĂ«nat e testimit
  • Do ta pĂ«rsĂ«risim trajnimin dhe testimin me pĂ«rdorimin e GPU-sĂ«

I gjithë kodi i mësipërm do ta kryejmë në Jupyter Notebook.

Shkarkimi dhe normalizimi i CIFAR10

Kopjoni dhe ekzekutoni në Jupyter kodin e mëposhtëm:


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

Përgjigjja duhet të jetë kështu:

Po shkarkoj https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz te ./data/cifar-10-python.tar.gz
Duke e nxjerrë ./data/cifar-10-python.tar.gz në ./data
Skedarët tashmë janë shkarkuar dhe verifikuar

Le të shfaqim disa imazhe trajnimi për verifikim:


import matplotlib.pyplot as plt
import numpy as np

# funksionet për të treguar një imazh

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

# merr disa imazhe të rastësishme të trajnimit
dataiter = iter(trainloader)
images, labels = dataiter.next()

# shfaq imazhet
imshow(torchvision.utils.make_grid(images))
# print etiketat
print(' '.join('%5s' % classes[labels[j]] for j in range(4)))

Rrjeti juaj i parë nervor në procesorin grafik (GPU). Udhëzues për fillestarë

Përcaktimi i rrjetit nervor

Le të shqyrtojmë më parë se si funksionon një rrjet nervor për njohjen e imazheve. Ky është një rrjet i thjeshtë me lidhje direkte. Ai merr të dhënat hyrëse, i kalon ato përmes disa shtresash njëra pas tjetrës, dhe më në fund jep rezultatet.

Rrjeti juaj i parë nervor në procesorin grafik (GPU). Udhëzues për fillestarë

Le ta krijojmë një rrjet të tillë në ambientin tonë:


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

Po ashtu, le të përcaktojmë funksionin e humbjes dhe optimizuesin


import torch.optim as optim

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

Trajnimi i rrjetit me të dhënat e trajnimit

Nisemi me trajnimin e rrjetit tonë nervor. Vërej se pasi të ekzekuash këtë kod, do të duhet të presësh për një kohë deri në përfundimin e punës. Mua më mori 5 minuta. Për të trajnuar rrjetin, duhen kohë.

 për epokë në rang (2): # përsëritni përmbledhjen disa herë

 humbja_e_aktivitetit = 0.0
 për i, të dhëna në enumerate(trainloader, 0):
 # merrni hyrjet; të dhënat janë një listë e [hyrjeve, etiketave]
 hyrjet, etiketat = të dhëna

 # zero gradienët e parametrave
 optimizer.zero_grad()

 # përparë + prapa + optimizo
 daljet = net(hyrjet)
 humbja = kriteri(daljet, etiketat)
 humbja.backward()
 optimizer.step()

 # printoni statistikat
 humbja_e_aktivitetit += humbja.item()
 nëse i % 2000 == 1999: # printoni çdo 2000 mini-batch
 print('[%d, ] humbje: %.3f' %
 (epokë + 1, i + 1, humbja_e_aktivitetit / 2000))
 humbja_e_aktivitetit = 0.0

print('Trajnimi përfundoi')

Do të marrim një rezultat të tillë:

Rrjeti juaj i parë nervor në procesorin grafik (GPU). Udhëzues për fillestarë

Ruajmë modelin tonë të trajnuar:

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

Testimi i rrjetit me të dhënat e testimit

Kemi trajnuar rrjetin duke përdorur grupin e të dhënave të trajnimit. Por na nevojitet të verifikojmë nëse rrjeti ka mësuar diçka.

Ne do ta kontrollojmë këtë duke parashikuar etiketën e klasës që rrjeti nervor prodhon dhe duke e verifikuar atë për saktësi. Nëse parashikimi është i saktë, ne e shtojmë mostrat në listën e parashikimeve të sakta.
Le të tregojmë një imazh nga grupi testues:

dataiter = iter(testloader)
imazhet, etiketat = dataiter.next()

# printo imazhet
imshow(torchvision.utils.make_grid(imazhet))
print('E vërteta: ', ' '.join('%5s' % classes[etiketat[j]] për j në gamë(4)))

Rrjeti juaj i parë nervor në procesorin grafik (GPU). Udhëzues për fillestarë

Tani le t'i kërkojmë rrjetit nervor të na tregojë se çfarë ka në këto imazhe:


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

daljet = net(imazhet)

_, parashikuar = torch.max(daljet, 1)

print('Parashikuar: ', ' '.join('%5s' % classes[parashikuar[j]]
                              për j në gamë(4)))

Rrjeti juaj i parë nervor në procesorin grafik (GPU). Udhëzues për fillestarë

Rezultatet duken mjaft të mira: rrjeti ka identifikuar saktë tre imazhe nga katër.

Le të shohim si funksionon rrjeti në të gjithë grupin e të dhënave.


i saktë = 0
total = 0
me torch.no_grad():
    për të dhënat në testloader:
        imazhet, etiketat = të dhënat
        daljet = net(imazhet)
        _, parashikuar = torch.max(daljet.data, 1)
        total += etiketat.size(0)
        i saktë += (parashikuar == etiketat).sum().item()

print('Saktësia e rrjetit në 10000 imazhet e testit: %d %%' % (
    100 * i saktë / total))

Rrjeti juaj i parë nervor në procesorin grafik (GPU). Udhëzues për fillestarë

Duket se rrjeti di diçka dhe funksionon. Nëse ai do të parashikonte klasat me rastësi, saktësia do të ishte 10%.

Tani le të shohim se cilat klasa rrjeti identifikon më mirë:

klasa_e_saktë = list(0. për i në rang (10))
klasa_total = list(0. për i në rang (10))
me torch.no_grad():
 për të dhëna në testloader:
 imazhe, etiketat = të dhëna
 daljet = net(imazhe)
 _, parashikuar = torch.max(daljet, 1)
 c = (parashikuar == etiketat).squeeze()
 për i në rang (4):
 etiketë = etiketat[i]
 klasa_e_saktë[etiketë] += c[i].item()
 klasa_total[etiketë] += 1


për i në rang (10):
 print('Saktësia e %5s : %%' % (
 klasat[i], 100 * klasa_e_saktë[i] / klasa_total[i]))

Rrjeti juaj i parë nervor në procesorin grafik (GPU). Udhëzues për fillestarë

Duket se rrjeti e identifikon më së miri automjetet dhe anijet: 71% saktësi.

Pra, rrjeti funksionon. Tani le të përpiqemi ta transferojmë funksionin e tij në një procesor grafik (GPU) dhe të shohim çfarë do të ndryshojë.

Trajnimi i rrjetit nervor në GPU

Fillimi i parë do të shpjegoj shkurt se çfarë është CUDA. CUDA (Compute Unified Device Architecture) është një platformë për llogaritjet paralele, e zhvilluar nga NVIDIA, për llogaritjet e përgjithshme në procesorët grafikë (GPU). Me ndihmën e CUDA-s, zhvilluesit mund të përshpejtojnë ndjeshëm aplikacionet e llogaritjes, duke shfrytëzuar mundësitë e procesorëve grafikë. Në serverin tonë, që kemi blerë, kjo platformë është tashmë e instaluar.

Le të fillojmë së pari duke e definuar GPU-në tonë si pajisjen e parë të dukshme cuda.

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
# Duke supozuar që jemi në një makinë CUDA, kjo duhet të printojë një pajisje CUDA:
print(device)

Rrjeti juaj i parë nervor në procesorin grafik (GPU). Udhëzues për fillestarë

Dërgojmë rrjetin në GPU:

net.to(device)

Po ashtu, do të na duhet të dërgojmë hyrjet dhe qëllimet në çdo hap dhe në GPU:

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

Le të fillojmë trajnimin e rrjetit tashmë në GPU:

importo torch.optim si optim

kriteri = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
për epokë në rang (2): # përsëritni përmbledhjen disa herë

 humbja_e_aktivitetit = 0.0
 për i, të dhëna në enumerate(trainloader, 0):
 # merrni hyrjet; të dhënat janë një listë e [hyrjeve, etiketave]
 hyrjet, etiketat = të dhëna[0].to(device), të dhëna[1].to(device)

 # zero gradienët e parametrave
 optimizer.zero_grad()

 # përparë + prapa + optimizo
 daljet = net(hyrjet)
 humbja = kriteri(daljet, etiketat)
 humbja.backward()
 optimizer.step()

 # printoni statistikat
 humbja_e_aktivitetit += humbja.item()
 nëse i % 2000 == 1999: # printoni çdo 2000 mini-batch
 print('[%d, ] humbje: %.3f' %
 (epokë + 1, i + 1, humbja_e_aktivitetit / 2000))
 humbja_e_aktivitetit = 0.0

print('Trajnimi përfundoi')

Këtë herë, trajnimi i rrjetit zgjati rreth 3 minuta. Kujtojmë se po ai hap në një procesor të zakonshëm zgjati 5 minuta. Diferenca nuk është e madhe, kjo ndodh për shkak se rrjeti ynë nuk është kaq i madh. Ndërsa përdoren grupe më të mëdha për trajnim, diferenca ndërmjet shpejtësisë së punës së GPU-së dhe procesorit tradicional do të rritet.

Duket se pĂ«r kĂ«tĂ« Ă«shtĂ« gjithçka. ÇfarĂ« arritĂ«m tĂ« bĂ«jmĂ«:

  • Ne shqyrtuam se çfarĂ« Ă«shtĂ« GPU dhe zgjodhĂ«m serverin nĂ« tĂ« cilin Ă«shtĂ« instaluar;
  • Ne konfiguruam mjedisin programor pĂ«r krijimin e njĂ« rrjeti nervor;
  • Ne krijuam njĂ« rrjet nervor pĂ«r njohjen e imazheve dhe e trajnuam atĂ«;
  • Ne pĂ«rsĂ«ritĂ«m trajnimin e rrjetit duke pĂ«rdorur GPU dhe arritĂ«m njĂ« rritje nĂ« shpejtĂ«si.

Do të jem i lumtur të përgjigjem në pyetje në komentet.

Burimi: habr.com

Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS đŸ”„ Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS | ProHoster