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