Bir grafik işlem birimindeki (GPU) ilk sinir ağınız. Yeni başlayanların rehberi

Bir grafik işlem birimindeki (GPU) ilk sinir ağınız. Yeni başlayanların rehberi
Bu yazımda size 30 dakikada makine öğrenimi ortamı kurmayı, görüntü tanıma için sinir ağı oluşturmayı ve ardından aynı ağı bir grafik işlemcide (GPU) nasıl çalıştıracağınızı anlatacağım.

Öncelikle sinir ağının ne olduğunu tanımlayalım.

Bizim durumumuzda bu, biyolojik sinir ağlarının - canlı bir organizmanın sinir hücrelerinin ağları - organizasyonu ve işleyişi ilkesine dayanan bir matematiksel modelin yanı sıra yazılım veya donanım düzenlemesidir. Bu kavram beyinde meydana gelen süreçleri incelerken ve bu süreçleri modellemeye çalışırken ortaya çıktı.

Sinir ağları kelimenin genel anlamıyla programlanmaz, eğitilir. Öğrenme yeteneği, sinir ağlarının geleneksel algoritmalara göre temel avantajlarından biridir. Teknik olarak öğrenme, nöronlar arasındaki bağlantıların katsayılarını bulmaktan ibarettir. Eğitim süreci sırasında sinir ağı, giriş verileri ile çıkış verileri arasındaki karmaşık bağımlılıkları tanımlayabilmenin yanı sıra genelleme de yapabilir.

Makine öğrenimi açısından bakıldığında, bir sinir ağı, örüntü tanıma yöntemlerinin, diskriminant analizinin, kümeleme yöntemlerinin ve diğer yöntemlerin özel bir durumudur.

Оборудование

Öncelikle ekipmanlara bakalım. Linux işletim sisteminin kurulu olduğu bir sunucuya ihtiyacımız var. Makine öğrenimi sistemlerini çalıştırmak için gereken ekipman oldukça güçlü ve dolayısıyla pahalıdır. Elinde iyi bir makine olmayanlar için bulut sağlayıcıların tekliflerine dikkat etmenizi öneririm. İhtiyacınız olan sunucuyu hızlı bir şekilde kiralayabilir ve yalnızca kullanım süresi kadar ödeme yapabilirsiniz.

Sinir ağları oluşturmanın gerekli olduğu projelerde Rus bulut sağlayıcılarından birinin sunucularını kullanıyorum. Şirket, NVIDIA'nın güçlü Tesla V100 grafik işlemcilerine (GPU) sahip, özellikle makine öğrenimi için kiralık bulut sunucuları sunuyor. Kısacası: GPU'lu bir sunucu kullanmak, hesaplamalar için CPU (tanınmış merkezi işlem birimi) kullanan benzer maliyetli bir sunucuya kıyasla onlarca kat daha verimli (hızlı) olabilir. Bu, hesaplamalarla daha hızlı başa çıkabilen GPU mimarisinin özellikleri sayesinde elde edilir.

Aşağıda açıklanan örnekleri uygulamak için birkaç günlüğüne aşağıdaki sunucuyu satın aldık:

  • SSD diski 150 GB
  • Bellek 32 GB
  • Tesla V100 16 Gb işlemci, 4 çekirdekli

Makinemize Ubuntu 18.04 kurduk.

Çevreyi ayarlama

Şimdi sunucuda çalışmak için gereken her şeyi yükleyelim. Yazımız öncelikle yeni başlayanlara yönelik olduğu için onlara faydalı olacak bazı noktalardan bahsedeceğim.

Bir ortam kurarken yapılan işlerin çoğu komut satırı aracılığıyla yapılır. Kullanıcıların çoğu Windows'u çalışma işletim sistemi olarak kullanıyor. Bu işletim sistemindeki standart konsol arzulanan çok şey bırakıyor. Bu nedenle uygun bir araç kullanacağız Komutan/. Mini sürümü indirin ve Cmder.exe'yi çalıştırın. Daha sonra sunucuya SSH aracılığıyla bağlanmanız gerekir:

ssh root@server-ip-or-hostname

Sunucu-ip-veya-anasistem adı yerine sunucunuzun IP adresini veya DNS adını belirtin. Daha sonra şifreyi girin ve bağlantı başarılı olursa buna benzer bir mesaj almalıyız.

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

ML modellerini geliştirmenin ana dili Python'dur. Ve Linux'ta kullanımı için en popüler platform Dev piton.

Sunucumuza yükleyelim.

Yerel paket yöneticisini güncelleyerek başlıyoruz:

sudo apt-get update

Curl'ü (komut satırı yardımcı programı) yükleyin:

sudo apt-get install curl

Anaconda Dağıtımının en son sürümünü indirin:

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

Kuruluma başlayalım:

bash Anaconda3-2019.10-Linux-x86_64.sh

Kurulum işlemi sırasında lisans sözleşmesini onaylamanız istenecektir. Başarılı kurulumdan sonra şunu görmelisiniz:

Thank you for installing Anaconda3!

Makine öğrenimi modellerinin geliştirilmesi için artık birçok çerçeve oluşturulmuştur; en popülerleriyle çalışıyoruz: PyTorch и tensör akışı.

Çerçeveyi kullanmak, geliştirme hızını artırmanıza ve standart görevler için hazır araçları kullanmanıza olanak tanır.

Bu örnekte PyTorch ile çalışacağız. Hadi kuralım:

conda install pytorch torchvision cudatoolkit=10.1 -c pytorch

Şimdi makine öğrenimi uzmanları için popüler bir geliştirme aracı olan Jupyter Notebook'u başlatmamız gerekiyor. Kod yazmanıza ve uygulamanın sonuçlarını anında görmenize olanak tanır. Jupyter Notebook Anaconda'ya dahildir ve sunucumuzda zaten yüklüdür. Masaüstü sistemimizden bağlanmanız gerekiyor.

Bunu yapmak için önce Jupyter'ı 8080 numaralı bağlantı noktasını belirterek sunucuda başlatacağız:

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

Daha sonra, Cmder konsolumuzda başka bir sekme açarak (üst menü - Yeni konsol iletişim kutusu), 8080 numaralı bağlantı noktası üzerinden SSH aracılığıyla sunucuya bağlanacağız:

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

İlk komutu girdiğimizde, Jupyter'ı tarayıcımızda açmamız için bize bağlantılar sunulacak:

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

Localhost:8080 bağlantısını kullanalım. Tam yolu kopyalayın ve bilgisayarınızın yerel tarayıcısının adres çubuğuna yapıştırın. Jüpyter Not Defteri açılacaktır.

Yeni bir not defteri oluşturalım: Yeni - Not Defteri - Python 3.

Kurduğumuz tüm bileşenlerin doğru çalışıp çalışmadığını kontrol edelim. Örnek PyTorch kodunu Jupyter'a girelim ve yürütmeyi çalıştıralım (Çalıştır düğmesi):

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

Sonuç şöyle bir şey olmalı:

Bir grafik işlem birimindeki (GPU) ilk sinir ağınız. Yeni başlayanların rehberi

Benzer bir sonuca sahipseniz, her şeyi doğru yapılandırdık ve bir sinir ağı geliştirmeye başlayabiliriz!

Sinir ağı oluşturma

Görüntü tanıma için bir sinir ağı oluşturacağız. Bunu esas alalım liderlik.

Ağı eğitmek için halka açık CIFAR10 veri setini kullanacağız. Sınıfları vardır: “uçak”, “araba”, “kuş”, “kedi”, “geyik”, “köpek”, “kurbağa”, “at”, “gemi”, “kamyon”. CIFAR10'daki görüntüler 3x32x32 yani 3x32 piksellik 32 kanallı renkli görüntülerdir.

Bir grafik işlem birimindeki (GPU) ilk sinir ağınız. Yeni başlayanların rehberi
İş için, görüntülerle çalışmak üzere PyTorch tarafından oluşturulan torchvision paketini kullanacağız.

Aşağıdaki adımları sırasıyla gerçekleştireceğiz:

  • Eğitim ve test veri setlerini yükleme ve normalleştirme
  • Sinir Ağı Tanımı
  • Eğitim verileriyle ilgili ağ eğitimi
  • Test verileri üzerinde ağ testi
  • GPU kullanarak eğitim ve testleri tekrarlayalım

Aşağıdaki kodun tamamını Jupyter Notebook'ta çalıştıracağız.

CIFAR10'u yükleme ve normalleştirme

Jupyter'da aşağıdaki kodu kopyalayıp çalıştırın:


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

Cevap şöyle olmalıdır:

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

Test için birkaç eğitim görseli gösterelim:


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

Bir grafik işlem birimindeki (GPU) ilk sinir ağınız. Yeni başlayanların rehberi

Sinir Ağı Tanımı

Öncelikle görüntü tanımaya yönelik bir sinir ağının nasıl çalıştığını ele alalım. Bu basit bir noktadan noktaya ağdır. Giriş verilerini alır, birkaç katmandan teker teker geçirir ve sonunda çıktı verilerini üretir.

Bir grafik işlem birimindeki (GPU) ilk sinir ağınız. Yeni başlayanların rehberi

Ortamımızda benzer bir ağ oluşturalım:


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

Ayrıca bir kayıp fonksiyonu ve bir optimize edici tanımlıyoruz


import torch.optim as optim

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

Eğitim verileriyle ilgili ağ eğitimi

Sinir ağımızı eğitmeye başlayalım. Lütfen bu kodu çalıştırdıktan sonra iş tamamlanana kadar bir süre beklemeniz gerekeceğini unutmayın. 5 dakikamı aldı. Ağı eğitmek zaman alır.

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

Aşağıdaki sonucu elde ederiz:

Bir grafik işlem birimindeki (GPU) ilk sinir ağınız. Yeni başlayanların rehberi

Eğitilmiş modelimizi kaydediyoruz:

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

Test verileri üzerinde ağ testi

Ağı bir dizi eğitim verisi kullanarak eğittik. Ancak ağın herhangi bir şey öğrenip öğrenmediğini kontrol etmemiz gerekiyor.

Bunu, sinir ağının çıkardığı sınıf etiketini tahmin ederek ve bunun doğru olup olmadığını test ederek test edeceğiz. Tahmin doğruysa örneği doğru tahminler listesine ekliyoruz.
Test setinden bir görüntü gösterelim:

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

Bir grafik işlem birimindeki (GPU) ilk sinir ağınız. Yeni başlayanların rehberi

Şimdi sinir ağından bize bu resimlerde ne olduğunu söylemesini isteyelim:


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

Bir grafik işlem birimindeki (GPU) ilk sinir ağınız. Yeni başlayanların rehberi

Sonuçlar oldukça iyi görünüyor: Ağ, dört resimden üçünü doğru bir şekilde tanımladı.

Ağın tüm veri kümesinde nasıl performans gösterdiğini görelim.


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

Bir grafik işlem birimindeki (GPU) ilk sinir ağınız. Yeni başlayanların rehberi

Ağın bir şeyler bildiği ve çalıştığı anlaşılıyor. Sınıfları rastgele belirleseydi doğruluk %10 olurdu.

Şimdi ağın hangi sınıfları daha iyi tanımladığını görelim:

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

Bir grafik işlem birimindeki (GPU) ilk sinir ağınız. Yeni başlayanların rehberi

Ağın arabaları ve gemileri tanımlamada en iyi olduğu görülüyor: %71 doğruluk.

Yani ağ çalışıyor. Şimdi çalışmasını grafik işlemciye (GPU) aktarmayı deneyelim ve nelerin değiştiğini görelim.

GPU'da bir sinir ağını eğitmek

Öncelikle CUDA'nın ne olduğunu kısaca anlatacağım. CUDA (Compute Unified Device Architecture), NVIDIA tarafından grafik işlem birimlerinde (GPU'lar) genel bilgi işlem için geliştirilmiş bir paralel bilgi işlem platformudur. CUDA ile geliştiriciler GPU'ların gücünden yararlanarak bilgi işlem uygulamalarını önemli ölçüde hızlandırabilirler. Bu platform zaten satın aldığımız sunucumuzda kuruludur.

Öncelikle GPU'muzu ilk görünen cuda cihazı olarak tanımlayalım.

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 )

Bir grafik işlem birimindeki (GPU) ilk sinir ağınız. Yeni başlayanların rehberi

Ağı GPU'ya gönderme:

net.to(device)

Ayrıca her adımda girdileri ve hedefleri GPU'ya göndermemiz gerekecek:

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

Ağı GPU üzerinde yeniden eğitelim:

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

Bu kez ağ eğitimi yaklaşık 3 dakika sürdü. Geleneksel bir işlemcide aynı aşamanın 5 dakika sürdüğünü hatırlayalım. Fark çok önemli değil, bunun nedeni ağımızın çok büyük olmaması. Eğitim için büyük diziler kullanıldığında GPU'nun hızı ile geleneksel işlemci arasındaki fark artacaktır.

Hepsi bu kadar gibi görünüyor. Ne yapmayı başardık:

  • GPU'nun ne olduğuna baktık ve kurulu olduğu sunucuyu seçtik;
  • Sinir ağı oluşturmak için bir yazılım ortamı kurduk;
  • Görüntü tanıma için bir sinir ağı oluşturduk ve onu eğittik;
  • Ağ eğitimini GPU kullanarak tekrarladık ve hızda artış elde ettik.

Yorumlardaki soruları cevaplamaktan mutluluk duyacağım.

Kaynak: habr.com

Yorum ekle