آموزش PyTorch برای مبتدیان – مبانی

جهان در حال پیشرفت است و فناوری نیز در خدمت آن است. همه باید با تغییرات سریع تکنولوژی همراه شوند. یکی از حوزه هایی که شاهد سریع ترین و بزرگترین تکامل بوده ، هوش مصنوعی است.

ما در هوش مصنوعی ، ماشین های خود را برای یادگیری آموزش می دهیم تا به نتایج بهتری دست یابند. از جمله شبکه های مولد تخاصمی (GAN) که می توانند تصاویر جدید و مدل های یادگیری عمیق برای ترجمه زبان به متن را ایجاد کنند و همچنین بسیاری از کاربرد های دیگر که می توانند داشته باشند! در این حوزه که سرعت پیشرفت سریعی دارد ، PyTorch به عنوان یک جایگزین برای ساخت این مدل ها بوجود آمده است.

با در نظر گرفتن تمام جوانب مثبت شناخت و یادگیری PyTorch ، ما این مقاله آموزشی را درباره یادگیری عمیق با PyTorch آماده کرده ایم که سرفصل های آن را می توانید در ادامه مشاهده کنید :

PyTorch چیست؟

PyTorch یک کتابخانه مبتنی بر پایتون است که ساخت مدل های یادگیری عمیق و استفاده از آن ها در برنامه های مختلف را تسهیل می کند. اما در واقع ، چیزی فراتر از یک کتابخانه یادگیری عمیق است. PyTorch یک بسته محاسباتی علمی است (همانطور که در اسناد رسمی PyTorch آمده است).

این یک بسته محاسباتی علمی مبتنی بر پایتون است که با دو هدف در اختیار مخاطبان قرار گرفته است :

  1. جایگزینی برای NumPy به منظور استفاده از توان پردازنده های گرافیکی ( GPU )
  2. یک پلتفرم تحقیقات یادگیری عمیق که حداکثر انعطاف پذیری و سرعت را ارائه می دهد

یادگیری عمیق با PyTorch ، یک حرکت برق آسا

PyTorch از تنسور ( Tensor ) به عنوان ساختار داده اصلی خود ، مشابه آرایه Numpy استفاده می کند. ممکن است در مورد این انتخاب خاص از ساختار داده ، تعجب کنید. پاسخ آن در این واقعیت نهفته است که با نرم افزار و سخت افزار مناسب ، تنسورها به عملیات مختلف ریاضی سرعت می بخشند. این عملیات هنگامی که با اعداد بزرگ برای یادگیری عمیق انجام شود ، تفاوت زیادی در سرعت ایجاد می کند.

PyTorch ، مشابه Python ، روی سهولت استفاده متمرکز است و این امکان را برای کاربران با دانش برنامه ریزی بسیار سطحی و مبتدی هم فراهم می کند تا از یادگیری عمیق در پروژه های خود استفاده کنند. همچنین اگر از قبل، هیچ کتابخانه یادگیری عمیقی را یاد نگرفته اید ، می توانید از پایتورچ به عنوان ” اولین کتابخانه یادگیری عمیق ” استفاده کنید.

چرا باید PyTorch را یاد بگیرم؟

در بخش قبلی ، ذکر کردیم که PyTorch بهترین گزینه برای اولین کتابخانه یادگیری عمیق است که باید یاد بگیرید. در این بخش ، توضیح خواهیم داد که چرا اینچنین است. هیچ کم و کاستی در کتابخانه های یادگیری عمیق وجود ندارد :  Keras ، Tensorflow  ،  Caffe و Theano (منسوخ شده)  و بسیاری موارد دیگر. اما چه چیزی PyTorch را متفاوت می کند؟

یک کتابخانه یادگیری عمیق ایده آل باید به راحتی قابل یادگیری و قابل استفاده باشد ، به اندازه کافی انعطاف پذیر باشد تا در برنامه های کاربردی مختلف مورد استفاده قرار گیرد ، کارآمد باشد تا مجموعه داده های عظیم زندگی واقعی را مدیریت کند و برای اینکه بتوانیم نتایج صحیح را حتی در صورت عدم قطعیت در داده های ورودی ارائه دهیم ، از دقت بالایی برخوردار باشد.

PyTorch در تمام این معیارهای ذکر شده در بالا عملکرد بسیار خوبی دارد. سبک کدنویسی ” pythonic ” ، یادگیری و استفاده از آن را تسهیل می کند. سرعت GPU ، پشتیبانی از محاسبه توزیع شده و محاسبه خودکار گرادیان ، به انجام خودکار بازگشت به عقب کمک می کند.

البته ، به خاطر پایتون ، با خطر کند بودن زمان اجرا مواجه هستیم اما API  با عملکرد بالا C ++  (libtorch) آن را از بین می برد. این امر باعث می شود انتقال از تحقیق و توسعه به تولید ، بسیار روان باشد که این دلیل دیگری است برای استفاده از PyTorch !

بیایید نتایج جالب توجهی را که می توان با استفاده از یک برنامه PyTorch بدست آورد بررسی کنیم.

کاربرد PyTorch
کاربرد دیگر از PyTorch

برای اینکه شما را بیشتر درگیر PyTorch کنیم ، در اینجا لیستی گسترده از پروژه های بسیار جالب PyTorch آورده شده است.

مروری بر کتابخانه PyTorch

حال که با PyTorch و ویژگی های منحصر به فرد آن آشنا شدیم ، بیایید نگاهی به ساختار اصلی یک پروژه PyTorch بیندازیم. شکل زیر یک گردش کار معمولی همراه با ماژول های مهم مرتبط با هر مرحله را توصیف می کند.

نحوه کار PyTorch

گردش کار اصلی PyTorch

ماژول های مهم PyTorch که ما در اینجا به طور خلاصه در مورد آن ها بحث خواهیم کرد عبارتند از: torch.nn  ، torch.optim ، torch.utils و torch.autograd

۱- بارگذاری و مدیریت داده ها

اولین قدم در هر پروژه یادگیری عمیق، بارگذاری و مدیریت داده هاست. PyTorch برای این کار، ابزارهایی را از طریق torch.utils.data در اختیار کاربر قرار می دهد.

دو کلاس مهم در این ماژول Dataset و DataLoader هستند.

  • Dataset از روی نوع داده Tensor ساخته شده است و در درجه اول برای مجموعه داده های سفارشی استفاده می شود.
  • DataLoader زمانی مورد استفاده قرار می‌گیرد که یک مجموعه داده بزرگ داشته باشید و بخواهید داده ها را از یک مجموعه داده در پس زمینه بارگذاری کنید تا آماده و منتظر حلقه آموزش باشد.

اگر به چندین ماشین یا GPU دسترسی داشته باشیم، می توانیم از torch.nn.DataParallel و torch.distributed استفاده کنیم.

۲- ساخت شبکه عصبی

از ماژول torch.nn برای ایجاد شبکه های عصبی استفاده می شود، که همه لایه های متداول شبکه عصبی ، مانند لایه های کاملاً متصل ، لایه های کانولوشن ، توابع فعالسازی و هزینه و غیره را فراهم می کند.

وقتی معماری شبکه ایجاد شد و داده ها برای تغذیه شبکه آماده شدند ، ما به تکنیک هایی برای به روزرسانی وزن ها و بایاس ها نیاز داریم تا شبکه شروع به یادگیری کند. این برنامه ها در ماژول torch.optim ارائه می شوند. به همین ترتیب ، برای مشتق گیری خودکار که در هنگام بازگشت به عقب لازم است ، ما از ماژول torch.autograd استفاده می کنیم.

۳- استنباط و سازگاری مدل

بعد از اینکه مدل آموزش داده شد ، می توان از آن برای پیش بینی خروجی موارد آزمایشی یا حتی مجموعه داده های جدید استفاده کرد. این فرآیند استنباط مدل نامیده می شود.

PyTorch همچنین TorchScript را ارائه می دهد که می تواند برای اجرای مدل ها ، مستقل از زمان اجرای پایتون مورد استفاده قرار گیرد. این را می توان به عنوان یک ماشین مجازی تصور کرد که دارای دستورالعمل های عمدتاً مختص تنسورها است.

همچنین می توانید مدل آموزش دیده با استفاده از PyTorch را به فرمت هایی مانند ONNX تبدیل کنید ، که به شما امکان می دهد از این مدل ها در سایر چارچوب های یادگیری عمیق مانند MXNet  ، CNTK ، Caffe2 نیز استفاده کنید. همچنین می توانید مدل های onnx را به Tensorflow تبدیل کنید.

معرفی تنسورها

تاکنون در این آموزش ، در مورد اینکه چرا شما باید PyTorch را یاد بگیرید بحث کردیم و اکنون زمان شروع کار است. ما این کار را با تنسور ها ( Tensors ) آغاز خواهیم کرد ، یعنی ساختار اصلی داده مورد استفاده در  PyTorch .

در واقع، تنسور یک نام فانتزی است که به ماتریس ها اختصاص داده می شود. اگر با آرایه های NumPy آشنا باشید ، درک و استفاده از تنسور های PyTorch بسیار آسان خواهد بود. یک مقدار اسکالر با یک تنسور صفر بُعدی نشان داده می شود. به طور مشابه ، سطر یا ستون یک ماتریس با استفاده از یک تنسور یک بُعدی نشان داده می شود و به همین ترتیب الی آخر. در زیر چند نمونه از تنسور با ابعاد مختلف برای تجسم و درک آن ها نشان داده شده است.

تنسور ها در PyTorch

ابعاد تنسورها در PyTorch

قبل از اینکه با معرفی تنسورها شروع کنیم ، بیایید PyTorch 1.1.0 را با اجرای دستور زیر نصب کنیم.

conda install -c pytorch pytorch-cpu

تمام شد ، شما هم اکنون PyTorch را برای استفاده آماده کرده اید! حالا بیایید شروع کنیم. ما به شما پیشنهاد می کنیم از Google Colab استفاده کنید. نوع زمان اجرا GPU را از فهرست انتخاب کنید.

اولین تنسور خود را بسازید

بیایید ببینیم چگونه می توانیم یک تنسور PyTorch ایجاد کنیم. ابتدا PyTorch را فراخوانی خواهیم کرد.

import torch

# Create a Tensor with just ones in a column
a = torch.ones(5)

# Print the tensor we created
print(a)

# tensor([1., 1., 1., 1., 1.])

# Create a Tensor with just zeros in a column
b = torch.zeros(5)
print(b)

# tensor([0., 0., 0., 0., 0.])

ما می توانیم به طور مشابه، تنسور را با مقادیر سفارشی ایجاد کنیم، همانطور که در زیر نشان داده شده است.

c = torch.tensor([1.0, 2.0, 3.0, 4.0, 5.0])
print(c)

# tensor([1., 2., 3., 4., 5.])

در تمام موارد فوق ، ما بردارها یا تنسورهای یک بُعدی ایجاد کردیم. اکنون ، بیایید چند تنسور از ابعاد بالاتر ایجاد کنیم.

d = torch.zeros(3,2)
print(d)

# tensor([[0., 0.],
#        [۰٫, ۰٫],
#        [۰٫, ۰٫]])

e = torch.ones(3,2)
print(e)

# tensor([[1., 1.],
#        [۱٫, ۱٫],
#        [۱٫, ۱٫]])

f = torch.tensor([[1.0, 2.0],[3.0, 4.0]])
print(f)

# tensor([[1., 2.],
#        [۳٫, ۴٫]])

# ۳D Tensor
g = torch.tensor([[[1., 2.], [3., 4.]], [[5., 6.], [7., 8.]]])
print(g)

# tensor([[[1., 2.],
#         [۳٫, ۴٫]],
#
#        [[۵٫, ۶٫],
#         [۷٫, ۸٫]]])

ما همچنین می توانیم با استفاده از روش .shape شکل تنسور را پیدا کنیم.

print(f.shape)
# torch.Size([2, 2])

print(e.shape)
# torch.Size([3, 2])

print(g.shape)
# torch.Size([2, 2, 2])

دسترسی به یک عنصر در تنسور

اکنون که چند تنسور ایجاد کردیم ، بیایید ببینیم که چگونه می توانیم به یک عنصر در یک تنسور دسترسی پیدا کنیم. ابتدا بیایید ببینیم چگونه این کار را برای بردار تنسور یک بُعدی انجام می دهیم.

# Get element at index 2
print(c[2])

# tensor(3.)

در مورد تنسور دو بُعدی یا سه بُعدی چطور؟ آنچه را که ما در قسمت قبلی در مورد بُعد یک تنسور ذکر کردیم را به یاد بیاورید. برای دسترسی به یک عنصر خاص در یک تنسور ، باید شاخص هایی مثل بُعد تنسور را مشخص کنیم. به همین دلیل برای تنسور c فقط باید یک شاخص را مشخص کنیم.

# All indices starting from 0

# Get element at row 1, column 0
print(f[1,0])
# We can also use the following
print(f[1][0])

# tensor(3.)

# Similarly for 3D Tensor
print(g[1,0,0])
print(g[1][0][0])

# tensor(5.)

اما اگر بخواهید به یک ردیف کامل در یک تنسور دو بُعدی دسترسی پیدا کنید ، چه می کنید؟ ما می توانیم به همان نحوی که در آرایه های NumPy استفاده می کنیم استفاده کنیم.

# All elements
print(f[:])

# All elements from index 1 to 2 (inclusive)
print(c[1:3])

# All elements till index 4 (exclusive)
print(c[:4])

# First row
print(f[0,:])

# Second column
print(f[:,1])

تشیخص نوع داده از عناصر

هر زمان که یک تنسور ایجاد کنیم ، PyTorch نوع داده عناصر تنسور را به گونه ای تعیین می کند که نوع داده بتواند همه عناصر تنسور را پوشش دهد. ما می توانیم با ایجاد نوع داده هنگام ایجاد تنسور ، این مورد را نادیده بگیریم.

int_tensor = torch.tensor([[1,2,3],[4,5,6]])
print(int_tensor.dtype)

# torch.int64

# What if we changed any one element to floating point number?
int_tensor = torch.tensor([[1,2,3],[4.,5,6]])
print(int_tensor.dtype)

# torch.float32

print(int_tensor)

# tensor([[1., 2., 3.],
#        [۴٫, ۵٫, ۶٫]])


# This can be overridden as follows
int_tensor = torch.tensor([[1,2,3],[4.,5,6]], dtype=torch.int32)
print(int_tensor.dtype)

# torch.int32

print(int_tensor)

# tensor([[1, 2, 3],
#        [۴, ۵, ۶]], dtype=torch.int32)

تنسور به / از آرایه NumPy

هر زمان که یک تنسور ایجاد کنیم ، PyTorch نوع داده عناصر تنسور را به گونه ای تعیین می کند که نوع داده بتواند همه عناصر تنسور را پوشش دهد. ما می توانیم با ایجاد نوع داده هنگام ایجاد تنسور ، این مورد را نادیده بگیریم.

ما بارها اشاره کردیم که آرایه های PyTorch Tensors و NumPy کاملاً شبیه به هم هستند. این سوال زمانی ایجاد می شود که امکان تبدیل یک ساختار داده به ساختار دیگر وجود داشته باشد. بیایید ببینیم که چگونه می توانیم این کار را انجام دهیم.

# Import NumPy
import numpy as np

# Tensor to Array
f_numpy = f.numpy()
print(f_numpy)

# array([[1., 2.],
#       [۳٫, ۴٫]], dtype=float32)

# Array to Tensor
h = np.array([[8,7,6,5],[4,3,2,1]])
h_tensor = torch.from_numpy(h)
print(h_tensor)

# tensor([[8, 7, 6, 5],
#        [۴, ۳, ۲, ۱]])

عملیات حسابی روی تنسورها

اکنون زمان گام بعدی است. بیایید ببینیم که چگونه می توانیم روی تنسور های PyTorch عملیات حسابی انجام دهیم.

# Create tensor
tensor1 = torch.tensor([[1,2,3],[4,5,6]])
tensor2 = torch.tensor([[-1,2,-3],[4,-5,6]])

# Addition
print(tensor1+tensor2)
# We can also use
print(torch.add(tensor1,tensor2))

# tensor([[ 0,  4,  0],
#        [ ۸,  ۰, ۱۲]])

# Subtraction
print(tensor1-tensor2)
# We can also use
print(torch.sub(tensor1,tensor2))

# tensor([[ 2,  0,  6],
#        [ ۰, ۱۰,  ۰]])

# Multiplication
# Tensor with Scalar
print(tensor1 * 2)
# tensor([[ 2,  4,  6],
#        [ ۸, ۱۰, ۱۲]])

# Tensor with another tensor
# Elementwise Multiplication
print(tensor1 * tensor2)
# tensor([[ -1,   4,  -9],
#        [ ۱۶, -۲۵,  ۳۶]])

# Matrix multiplication
tensor3 = torch.tensor([[1,2],[3,4],[5,6]])
print(torch.mm(tensor1,tensor3))
# tensor([[22, 28],
#        [۴۹, ۶۴]])

# Division
# Tensor with scalar
print(tensor1/2)
# tensor([[0, 1, 1],
#        [۲, ۲, ۳]])

# Tensor with another tensor
# Elementwise division
print(tensor1/tensor2)
# tensor([[-1,  1, -1],
#        [ ۱, -۱,  ۱]])

تنسور CPU و GPU

PyTorch برای CPU و GPU ، اجرای متفاوتی از تنسور دارد. برای انجام محاسبات سنگین موازی و سریع می توان هر تنسوری را به GPU تبدیل کرد. تمام عملیاتی که روی تنسور انجام می شود با استفاده از روال های خاص GPU از طریق PyTorch انجام می شود.

اگر به GPU دسترسی ندارید ، می توانید این مثال ها را در Google Colab انجام دهید و زمان اجرا را روی GPU انتخاب کنید.

ابتدا بیایید ببینیم که چگونه می توان یک تنسور برای GPU ایجاد کرد.

# Create a tensor for CPU
# This will occupy CPU RAM
tensor_cpu = torch.tensor([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]], device='cpu')

# Create a tensor for GPU
# This will occupy GPU RAM
tensor_gpu = torch.tensor([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]], device='cuda')

اگر از Google Colab استفاده می کنید ، در گوشه بالا سمت راست روی RAM consumption meter  کلیک کنید و به محض ایجاد tensor_gpu ، شاهد افزایش مصرف GPU RAM خواهید بود.

درست مانند عملیات ایجاد تنسور ، عملیات انجام شده برای تنسورهای CPU و GPU نیز متفاوت است و RAM را مطابق با دستگاه مشخص شده مصرف می کند.

# This uses CPU RAM
tensor_cpu = tensor_cpu * 5

# This uses GPU RAM
# Focus on GPU RAM Consumption
tensor_gpu = tensor_gpu * 5

نکته کلیدی که در اینجا باید به آن توجه شود این است که هیچ اطلاعاتی در عملیات تنسور GPU به CPU منتقل نمی شود (مگر اینکه ما تنسور را چاپ کنیم یا به آن دسترسی پیدا کنیم).

همانطور که در زیر نشان داده شده است ، می توانیم تنسور GPU را به CPU و بالعکس منتقل کنیم.

# Move GPU tensor to CPU
tensor_gpu_cpu = tensor_gpu.to(device='cpu')

# Move CPU tensor to GPU
tensor_cpu_gpu = tensor_cpu.to(device='cuda')

و تمام !

به عنوان یک جمع بندی سریع ، در این آموزش ما در مورد PyTorch ، منحصر به فرد بودن آن و اینکه چرا باید آن را یاد بگیرید بحث کردیم. همچنین بطور مفصل به روند کار PyTorch و نوع داده تنسور PyTorch پرداختیم.

در پست آموزشی بعدی خواهیم دید که چگونه می توان با کمک TorchVision از مدل های از قبل آموزش دیده استفاده کرد.

بیشتر بخوانید :

منبع Learn OpenCV

درباره‌ی امیر اقتدائی

همچنین ببینید

هوش مصنوعی در دنیای رباتیک

هوش مصنوعی در دنیای رباتیک

در طی سال ها، در بسیاری از فیلم های علمی تخیلی دیده ایم که یک …

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *