در این مقاله به شما خواهم گفت که چگونه یک محیط یادگیری ماشینی را در 30 دقیقه راه اندازی کنید، یک شبکه عصبی برای تشخیص تصویر ایجاد کنید و سپس همان شبکه را روی یک پردازنده گرافیکی (GPU) اجرا کنید.
ابتدا اجازه دهید تعریف کنیم که شبکه عصبی چیست.
در مورد ما، این یک مدل ریاضی و همچنین تجسم نرم افزار یا سخت افزار آن است که بر اساس اصل سازماندهی و عملکرد شبکه های عصبی بیولوژیکی - شبکه های سلول های عصبی یک موجود زنده ساخته شده است. این مفهوم هنگام مطالعه فرآیندهای رخ داده در مغز و تلاش برای مدل سازی این فرآیندها به وجود آمد.
شبکه های عصبی به معنای معمول کلمه برنامه ریزی نشده اند، بلکه آموزش دیده اند. توانایی یادگیری یکی از مزیت های اصلی شبکه های عصبی نسبت به الگوریتم های سنتی است. از نظر فنی، یادگیری شامل یافتن ضرایب ارتباط بین نورون ها است. در طول فرآیند آموزش، شبکه عصبی قادر است وابستگی های پیچیده بین داده های ورودی و خروجی را شناسایی کند و همچنین تعمیم را انجام دهد.
از دیدگاه یادگیری ماشین، شبکه عصبی یک مورد خاص از روشهای تشخیص الگو، تجزیه و تحلیل متمایز، روشهای خوشهبندی و روشهای دیگر است.
Оборудование
ابتدا بیایید به تجهیزات نگاه کنیم. به سروری نیازمندیم که سیستم عامل لینوکس روی آن نصب شده باشد. تجهیزات مورد نیاز برای راه اندازی سیستم های یادگیری ماشین بسیار قدرتمند و در نتیجه گران هستند. برای کسانی که دستگاه خوبی در دسترس ندارند، توصیه می کنم به پیشنهادات ارائه دهندگان ابر توجه کنند. شما می توانید سرور مورد نیاز را به سرعت اجاره کنید و فقط برای زمان استفاده پرداخت کنید.
در پروژه هایی که نیاز به ایجاد شبکه های عصبی است، از سرورهای یکی از ارائه دهندگان ابر روسی استفاده می کنم. این شرکت سرورهای ابری را مخصوصاً برای یادگیری ماشین با پردازندههای گرافیکی قدرتمند Tesla V100 (GPU) از NVIDIA برای اجاره ارائه میکند. به طور خلاصه: استفاده از یک سرور با GPU می تواند ده ها برابر کارآمدتر (سریع) در مقایسه با سروری با هزینه مشابه که از یک CPU (واحد پردازش مرکزی معروف) برای محاسبات استفاده می کند، باشد. این به دلیل ویژگیهای معماری GPU است که سریعتر با محاسبات کنار میآید.
برای پیاده سازی نمونه های شرح داده شده در زیر، سرور زیر را برای چند روز خریداری کردیم:
- دیسک SSD 150 گیگابایت
- رم 32 گیگابایت
- تسلا V100 پردازنده 16 گیگابایتی با 4 هسته
ما اوبونتو 18.04 را روی دستگاه خود نصب کردیم.
راه اندازی محیط
حالا بیایید همه چیز لازم برای کار را روی سرور نصب کنیم. از آنجایی که مقاله ما در درجه اول برای مبتدیان است، در مورد نکاتی صحبت خواهم کرد که برای آنها مفید خواهد بود.
بسیاری از کارها هنگام تنظیم یک محیط از طریق خط فرمان انجام می شود. اکثر کاربران از ویندوز به عنوان سیستم عامل خود استفاده می کنند. کنسول استاندارد در این سیستم عامل چیزهای زیادی برای دلخواه باقی می گذارد. بنابراین، ما از یک ابزار مناسب استفاده خواهیم کرد
ssh root@server-ip-or-hostname
به جای server-ip-or-hostname، آدرس IP یا نام DNS سرور خود را مشخص کنید. در مرحله بعد رمز عبور را وارد کرده و در صورت موفقیت آمیز بودن اتصال باید پیامی مشابه این دریافت کنیم.
Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-74-generic x86_64)
زبان اصلی برای توسعه مدل های ML پایتون است. و محبوب ترین پلتفرم برای استفاده از آن در لینوکس است
بیایید آن را روی سرور خود نصب کنیم.
ما با بهروزرسانی مدیر بسته محلی شروع میکنیم:
sudo apt-get update
نصب curl (ابزار خط فرمان):
sudo apt-get install curl
آخرین نسخه Anaconda Distribution را دانلود کنید:
cd /tmp
curl –O https://repo.anaconda.com/archive/Anaconda3-2019.10-Linux-x86_64.sh
بیایید نصب را شروع کنیم:
bash Anaconda3-2019.10-Linux-x86_64.sh
در طول مراحل نصب، از شما خواسته می شود تا موافقت نامه مجوز را تأیید کنید. پس از نصب موفقیت آمیز باید این را ببینید:
Thank you for installing Anaconda3!
اکنون چارچوب های زیادی برای توسعه مدل های ML ایجاد شده است؛ ما با محبوب ترین آنها کار می کنیم:
استفاده از فریم ورک به شما امکان می دهد سرعت توسعه را افزایش دهید و از ابزارهای آماده برای کارهای استاندارد استفاده کنید.
در این مثال ما با PyTorch کار خواهیم کرد. بیایید آن را نصب کنیم:
conda install pytorch torchvision cudatoolkit=10.1 -c pytorch
اکنون باید Jupyter Notebook را راه اندازی کنیم، یک ابزار توسعه محبوب برای متخصصان ML. به شما امکان می دهد کد بنویسید و بلافاصله نتایج اجرای آن را مشاهده کنید. Jupyter Notebook همراه Anaconda است و قبلاً روی سرور ما نصب شده است. باید از سیستم دسکتاپ ما به آن متصل شوید.
برای انجام این کار، ابتدا Jupyter را بر روی سروری که پورت 8080 را مشخص می کند راه اندازی می کنیم:
jupyter notebook --no-browser --port=8080 --allow-root
سپس، با باز کردن یک برگه دیگر در کنسول Cmder (منوی بالا - گفتگوی کنسول جدید) از طریق پورت 8080 به سرور از طریق SSH متصل خواهیم شد:
ssh -L 8080:localhost:8080 root@server-ip-or-hostname
وقتی اولین دستور را وارد می کنیم، پیوندهایی برای باز کردن Jupyter در مرورگر به ما پیشنهاد می شود:
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 استفاده کنیم. مسیر کامل را کپی کرده و در نوار آدرس مرورگر محلی رایانه شخصی خود قرار دهید. نوت بوک Jupyter باز خواهد شد.
بیایید یک نوت بوک جدید بسازیم: New - Notebook - Python 3.
بیایید عملکرد صحیح همه اجزایی را که نصب کرده ایم بررسی کنیم. بیایید نمونه کد PyTorch را در Jupyter وارد کرده و اجرا را اجرا کنیم (دکمه Run):
from __future__ import print_function
import torch
x = torch.rand(5, 3)
print(x)
نتیجه باید چیزی شبیه این باشد:
اگر نتیجه مشابهی دارید، پس ما همه چیز را به درستی پیکربندی کرده ایم و می توانیم شروع به توسعه یک شبکه عصبی کنیم!
ایجاد یک شبکه عصبی
ما یک شبکه عصبی برای تشخیص تصویر ایجاد خواهیم کرد. بیایید این را به عنوان پایه در نظر بگیریم
ما از مجموعه داده CIFAR10 در دسترس عموم برای آموزش شبکه استفاده خواهیم کرد. دارای کلاس های: "هواپیما"، "ماشین"، "پرنده"، "گربه"، "گوزن"، "سگ"، "قورباغه"، "اسب"، "کشتی"، "کامیون". تصاویر در CIFAR10 3x32x32 هستند، یعنی تصاویر رنگی 3 کانال 32x32 پیکسل.
برای کار، ما از بسته ایجاد شده توسط PyTorch برای کار با تصاویر - Torchvision استفاده می کنیم.
مراحل زیر را به ترتیب انجام خواهیم داد:
- بارگذاری و عادی سازی مجموعه داده های آموزشی و آزمایشی
- تعریف شبکه عصبی
- آموزش شبکه در مورد داده های آموزشی
- تست شبکه بر روی داده های آزمایشی
- بیایید آموزش و تست را با استفاده از GPU تکرار کنیم
ما تمام کدهای زیر را در Jupyter Notebook اجرا خواهیم کرد.
بارگیری و عادی سازی CIFAR10
کد زیر را در 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')
پاسخ باید این باشد:
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
بیایید چندین تصویر آموزشی را برای آزمایش نمایش دهیم:
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)))
تعریف شبکه عصبی
بیایید ابتدا نحوه عملکرد یک شبکه عصبی برای تشخیص تصویر را در نظر بگیریم. این یک شبکه نقطه به نقطه ساده است. داده های ورودی را می گیرد، آن ها را یکی یکی از چندین لایه عبور می دهد و در نهایت داده های خروجی را تولید می کند.
بیایید یک شبکه مشابه در محیط خود ایجاد کنیم:
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()
ما همچنین یک تابع ضرر و یک بهینه ساز تعریف می کنیم
import torch.optim as optim
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
آموزش شبکه در مورد داده های آموزشی
بیایید آموزش شبکه عصبی خود را شروع کنیم. لطفا توجه داشته باشید که پس از اجرای این کد، باید مدتی صبر کنید تا کار تکمیل شود. من 5 دقیقه طول کشید. آموزش شبکه به زمان نیاز دارد.
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')
نتیجه زیر را می گیریم:
ما مدل آموزش دیده خود را ذخیره می کنیم:
PATH = './cifar_net.pth'
torch.save(net.state_dict(), PATH)
تست شبکه بر روی داده های آزمایشی
ما شبکه را با استفاده از مجموعه ای از داده های آموزشی آموزش دادیم. اما باید بررسی کنیم که آیا شبکه اصلاً چیزی یاد گرفته است یا خیر.
ما این را با پیشبینی برچسب کلاسی که شبکه عصبی خروجی میدهد آزمایش میکنیم و آن را آزمایش میکنیم تا ببینیم آیا درست است یا خیر. اگر پیش بینی درست باشد، نمونه را به لیست پیش بینی های صحیح اضافه می کنیم.
بیایید تصویری از مجموعه آزمایشی را نشان دهیم:
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)))
حالا بیایید از شبکه عصبی بخواهیم که به ما بگوید در این تصاویر چه چیزی وجود دارد:
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)))
نتایج بسیار خوب به نظر می رسد: شبکه به درستی سه عکس از چهار تصویر را شناسایی کرد.
بیایید ببینیم که شبکه چگونه در کل مجموعه داده عمل می کند.
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))
به نظر می رسد شبکه چیزی می داند و کار می کند. اگر کلاس ها را به صورت تصادفی تعیین می کرد، دقت آن 10 درصد می شد.
حالا بیایید ببینیم که شبکه کدام کلاس ها را بهتر شناسایی می کند:
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]))
به نظر می رسد که این شبکه در شناسایی خودروها و کشتی ها بهترین است: دقت 71 درصد.
بنابراین شبکه کار می کند. حالا بیایید سعی کنیم کار آن را به پردازنده گرافیکی (GPU) منتقل کنیم و ببینیم چه تغییری می کند.
آموزش شبکه عصبی روی GPU
ابتدا به طور خلاصه توضیح خواهم داد که CUDA چیست. CUDA (Compute Unified Device Architecture) یک پلت فرم محاسباتی موازی است که توسط NVIDIA برای محاسبات عمومی بر روی واحدهای پردازش گرافیکی (GPU) توسعه یافته است. با CUDA، توسعه دهندگان می توانند با استفاده از قدرت پردازنده های گرافیکی، برنامه های محاسباتی را به طور چشمگیری تسریع کنند. این پلتفرم قبلاً روی سرور ما که خریداری کرده ایم نصب شده است.
بیایید ابتدا GPU خود را به عنوان اولین دستگاه cuda قابل مشاهده تعریف کنیم.
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 )
ارسال شبکه به GPU:
net.to(device)
همچنین باید ورودی ها و اهداف را در هر مرحله به GPU ارسال کنیم:
inputs, labels = data[0].to(device), data[1].to(device)
بیایید دوباره شبکه را روی 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')
این بار آموزش شبکه حدود 3 دقیقه به طول انجامید. به یاد بیاوریم که همان مرحله روی یک پردازنده معمولی 5 دقیقه به طول انجامید. تفاوت قابل توجهی نیست، این اتفاق می افتد زیرا شبکه ما آنقدر بزرگ نیست. هنگام استفاده از آرایه های بزرگ برای آموزش، تفاوت بین سرعت GPU و یک پردازنده سنتی افزایش می یابد.
به نظر می رسد همه چیز همین باشد. کاری که ما موفق شدیم انجام دهیم:
- ما نگاه کردیم که GPU چیست و سروری را که روی آن نصب شده است انتخاب کردیم.
- ما یک محیط نرم افزاری برای ایجاد یک شبکه عصبی راه اندازی کرده ایم.
- ما یک شبکه عصبی برای تشخیص تصویر ایجاد کردیم و آن را آموزش دادیم.
- ما آموزش شبکه را با استفاده از GPU تکرار کردیم و افزایش سرعت دریافت کردیم.
من خوشحال خواهم شد که به سوالات در نظرات پاسخ دهم.
منبع: www.habr.com