Rangkaian saraf pertama anda pada unit pemprosesan grafik (GPU). Panduan Pemula

Rangkaian saraf pertama anda pada unit pemprosesan grafik (GPU). Panduan Pemula
Dalam artikel ini, saya akan memberitahu anda cara menyediakan persekitaran pembelajaran mesin dalam masa 30 minit, mencipta rangkaian saraf untuk pengecaman imej, dan kemudian menjalankan rangkaian yang sama pada pemproses grafik (GPU).

Pertama, mari kita tentukan apa itu rangkaian saraf.

Dalam kes kami, ini adalah model matematik, serta penjelmaan perisian atau perkakasannya, dibina berdasarkan prinsip organisasi dan fungsi rangkaian saraf biologi - rangkaian sel saraf organisma hidup. Konsep ini timbul semasa mengkaji proses yang berlaku dalam otak dan cuba memodelkan proses ini.

Rangkaian saraf tidak diprogramkan dalam erti kata biasa, ia dilatih. Keupayaan untuk belajar adalah salah satu kelebihan utama rangkaian saraf berbanding algoritma tradisional. Secara teknikal, pembelajaran terdiri daripada mencari pekali hubungan antara neuron. Semasa proses latihan, rangkaian saraf dapat mengenal pasti kebergantungan kompleks antara data input dan data output, serta melakukan generalisasi.

Dari sudut pembelajaran mesin, rangkaian saraf ialah kes khas kaedah pengecaman corak, analisis diskriminasi, kaedah pengelompokan dan kaedah lain.

ΠžΠ±ΠΎΡ€ΡƒΠ΄ΠΎΠ²Π°Π½ΠΈΠ΅

Pertama, mari kita lihat peralatan. Kami memerlukan pelayan dengan sistem pengendalian Linux dipasang padanya. Peralatan yang diperlukan untuk mengendalikan sistem pembelajaran mesin agak berkuasa dan, akibatnya, mahal. Bagi mereka yang tidak mempunyai mesin yang bagus, saya mengesyorkan agar anda memberi perhatian kepada tawaran pembekal awan. Anda boleh menyewa pelayan yang diperlukan dengan cepat dan membayar hanya untuk masa penggunaan.

Dalam projek di mana perlu untuk mencipta rangkaian saraf, saya menggunakan pelayan salah satu penyedia awan Rusia. Syarikat itu menawarkan pelayan awan untuk disewa khusus untuk pembelajaran mesin dengan pemproses grafik (GPU) Tesla V100 yang berkuasa daripada NVIDIA. Ringkasnya: menggunakan pelayan dengan GPU boleh menjadi berpuluh-puluh kali lebih cekap (pantas) berbanding pelayan dengan kos serupa yang menggunakan CPU (unit pemprosesan pusat yang terkenal) untuk pengiraan. Ini dicapai kerana ciri-ciri seni bina GPU, yang mengatasi pengiraan dengan lebih cepat.

Untuk melaksanakan contoh yang diterangkan di bawah, kami membeli pelayan berikut selama beberapa hari:

  • Cakera SSD 150 GB
  • RAM 32 GB
  • Pemproses Tesla V100 16 Gb dengan 4 teras

Kami memasang Ubuntu 18.04 pada mesin kami.

Menyediakan persekitaran

Sekarang mari pasang semua yang diperlukan untuk kerja pada pelayan. Oleh kerana artikel kami adalah terutamanya untuk pemula, saya akan bercakap tentang beberapa perkara yang akan berguna kepada mereka.

Banyak kerja semasa menyediakan persekitaran dilakukan melalui baris arahan. Kebanyakan pengguna menggunakan Windows sebagai OS kerja mereka. Konsol standard dalam OS ini meninggalkan banyak perkara yang diingini. Oleh itu, kami akan menggunakan alat yang mudah Cmder/. Muat turun versi mini dan jalankan Cmder.exe. Seterusnya anda perlu menyambung ke pelayan melalui SSH:

ssh root@server-ip-or-hostname

Daripada nama pelayan-ip-atau-hos, nyatakan alamat IP atau nama DNS pelayan anda. Seterusnya, masukkan kata laluan dan jika sambungan berjaya, kami akan menerima mesej yang serupa dengan ini.

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

Bahasa utama untuk membangunkan model ML ialah Python. Dan platform yang paling popular untuk penggunaannya di Linux ialah Anaconda.

Mari pasang pada pelayan kami.

Kami mulakan dengan mengemas kini pengurus pakej tempatan:

sudo apt-get update

Pasang curl (utiliti baris arahan):

sudo apt-get install curl

Muat turun versi terbaru Anaconda Distribution:

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

Mari mulakan pemasangan:

bash Anaconda3-2019.10-Linux-x86_64.sh

Semasa proses pemasangan, anda akan diminta untuk mengesahkan perjanjian lesen. Selepas pemasangan berjaya, anda akan melihat ini:

Thank you for installing Anaconda3!

Banyak rangka kerja kini telah dicipta untuk pembangunan model ML; kami bekerja dengan yang paling popular: PyTorch ΠΈ Aliran Tensor.

Menggunakan rangka kerja membolehkan anda meningkatkan kelajuan pembangunan dan menggunakan alat siap sedia untuk tugasan standard.

Dalam contoh ini kita akan bekerja dengan PyTorch. Mari pasang:

conda install pytorch torchvision cudatoolkit=10.1 -c pytorch

Kini kami perlu melancarkan Jupyter Notebook, alat pembangunan popular untuk pakar ML. Ia membolehkan anda menulis kod dan segera melihat hasil pelaksanaannya. Jupyter Notebook disertakan dengan Anaconda dan sudah dipasang pada pelayan kami. Anda perlu menyambung kepadanya daripada sistem desktop kami.

Untuk melakukan ini, kami mula-mula akan melancarkan Jupyter pada pelayan yang menentukan port 8080:

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

Seterusnya, membuka tab lain dalam konsol Cmder kami (menu atas - Dialog konsol baharu) kami akan menyambung melalui port 8080 ke pelayan melalui SSH:

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

Apabila kami memasukkan arahan pertama, kami akan ditawarkan pautan untuk membuka Jupyter dalam penyemak imbas kami:

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

Mari gunakan pautan untuk localhost:8080. Salin laluan penuh dan tampalkannya ke dalam bar alamat penyemak imbas tempatan PC anda. Buku Nota Jupyter akan dibuka.

Mari buat buku nota baharu: Baharu - Buku Nota - Python 3.

Mari kita semak operasi yang betul bagi semua komponen yang kami pasang. Mari masukkan contoh kod PyTorch ke dalam Jupyter dan jalankan pelaksanaan (butang Run):

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

Hasilnya sepatutnya seperti ini:

Rangkaian saraf pertama anda pada unit pemprosesan grafik (GPU). Panduan Pemula

Jika anda mempunyai hasil yang serupa, maka kami telah mengkonfigurasi semuanya dengan betul dan kami boleh mula membangunkan rangkaian saraf!

Mewujudkan rangkaian saraf

Kami akan mencipta rangkaian saraf untuk pengecaman imej. Mari kita ambil ini sebagai asas panduan.

Kami akan menggunakan set data CIFAR10 yang tersedia untuk umum untuk melatih rangkaian. Ia mempunyai kelas: "kapal terbang", "kereta", "burung", "kucing", "rusa", "anjing", "katak", "kuda", "kapal", "trak". Imej dalam CIFAR10 ialah 3x32x32, iaitu imej warna 3 saluran 32x32 piksel.

Rangkaian saraf pertama anda pada unit pemprosesan grafik (GPU). Panduan Pemula
Untuk kerja, kami akan menggunakan pakej yang dibuat oleh PyTorch untuk bekerja dengan imej - torchvision.

Kami akan melakukan langkah-langkah berikut mengikut urutan:

  • Memuatkan dan menormalkan set data latihan dan ujian
  • Definisi Rangkaian Neural
  • Latihan rangkaian mengenai data latihan
  • Ujian rangkaian pada data ujian
  • Mari ulangi latihan dan ujian menggunakan GPU

Kami akan melaksanakan semua kod di bawah dalam Buku Nota Jupyter.

Memuatkan dan menormalkan CIFAR10

Salin dan jalankan kod berikut dalam 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')

Jawapannya sepatutnya:

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

Mari paparkan beberapa imej latihan untuk ujian:


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

Rangkaian saraf pertama anda pada unit pemprosesan grafik (GPU). Panduan Pemula

Definisi Rangkaian Neural

Mari kita pertimbangkan dahulu cara rangkaian saraf untuk pengecaman imej berfungsi. Ini adalah rangkaian point-to-point yang mudah. Ia mengambil data input, melewatinya melalui beberapa lapisan satu demi satu, dan kemudian akhirnya menghasilkan data output.

Rangkaian saraf pertama anda pada unit pemprosesan grafik (GPU). Panduan Pemula

Mari kita cipta rangkaian yang serupa dalam persekitaran kita:


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

Kami juga mentakrifkan fungsi kehilangan dan pengoptimum


import torch.optim as optim

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

Latihan rangkaian mengenai data latihan

Mari mulakan latihan rangkaian saraf kita. Sila ambil perhatian bahawa selepas anda menjalankan kod ini, anda perlu menunggu sedikit masa sehingga kerja selesai. Saya mengambil masa 5 minit. Ia mengambil masa untuk melatih rangkaian.

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

Kami mendapat keputusan berikut:

Rangkaian saraf pertama anda pada unit pemprosesan grafik (GPU). Panduan Pemula

Kami menyimpan model terlatih kami:

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

Ujian rangkaian pada data ujian

Kami melatih rangkaian menggunakan satu set data latihan. Tetapi kita perlu menyemak sama ada rangkaian telah mempelajari apa-apa sama sekali.

Kami akan menguji ini dengan meramalkan label kelas yang dikeluarkan oleh rangkaian saraf dan mengujinya untuk melihat sama ada ia benar. Jika ramalan itu betul, kami menambah sampel pada senarai ramalan yang betul.
Mari tunjukkan imej dari set ujian:

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

Rangkaian saraf pertama anda pada unit pemprosesan grafik (GPU). Panduan Pemula

Sekarang mari kita tanya rangkaian saraf untuk memberitahu kami apa yang ada dalam gambar ini:


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

Rangkaian saraf pertama anda pada unit pemprosesan grafik (GPU). Panduan Pemula

Hasilnya kelihatan agak baik: rangkaian mengenal pasti tiga daripada empat gambar dengan betul.

Mari lihat prestasi rangkaian merentas keseluruhan set data.


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

Rangkaian saraf pertama anda pada unit pemprosesan grafik (GPU). Panduan Pemula

Nampaknya rangkaian mengetahui sesuatu dan berfungsi. Jika dia menentukan kelas secara rawak, ketepatannya ialah 10%.

Sekarang mari kita lihat kelas mana yang dikenal pasti oleh rangkaian dengan lebih baik:

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

Rangkaian saraf pertama anda pada unit pemprosesan grafik (GPU). Panduan Pemula

Nampaknya rangkaian itu paling baik dalam mengenal pasti kereta dan kapal: 71% ketepatan.

Jadi rangkaian berfungsi. Sekarang mari cuba pindahkan kerjanya ke pemproses grafik (GPU) dan lihat perubahannya.

Melatih rangkaian saraf pada GPU

Pertama, saya akan menerangkan secara ringkas apa itu CUDA. CUDA (Compute Unified Device Architecture) ialah platform pengkomputeran selari yang dibangunkan oleh NVIDIA untuk pengkomputeran am pada unit pemprosesan grafik (GPU). Dengan CUDA, pembangun boleh mempercepatkan aplikasi pengkomputeran secara mendadak dengan memanfaatkan kuasa GPU. Platform ini telah pun dipasang pada pelayan kami yang kami beli.

Mari kita tentukan GPU kita sebagai peranti cuda pertama yang boleh dilihat.

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 )

Rangkaian saraf pertama anda pada unit pemprosesan grafik (GPU). Panduan Pemula

Menghantar rangkaian ke GPU:

net.to(device)

Kami juga perlu menghantar input dan sasaran pada setiap langkah kepada GPU:

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

Mari kita latih semula rangkaian pada 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')

Kali ini, latihan rangkaian mengambil masa kira-kira 3 minit. Mari kita ingat bahawa peringkat yang sama pada pemproses konvensional berlangsung selama 5 minit. Perbezaannya tidak ketara, ini berlaku kerana rangkaian kami tidak begitu besar. Apabila menggunakan tatasusunan besar untuk latihan, perbezaan antara kelajuan GPU dan pemproses tradisional akan meningkat.

Nampaknya itu sahaja. Apa yang kami berjaya lakukan:

  • Kami melihat apa itu GPU dan memilih pelayan yang dipasang;
  • Kami telah menyediakan persekitaran perisian untuk mencipta rangkaian saraf;
  • Kami mencipta rangkaian saraf untuk pengecaman imej dan melatihnya;
  • Kami mengulangi latihan rangkaian menggunakan GPU dan menerima peningkatan dalam kelajuan.

Saya dengan senang hati akan menjawab soalan dalam komen.

Sumber: www.habr.com

Tambah komen