مقدمه
در بخش اول، با ویژگیهای کلیدی PyTorch از جمله گرافهای پویا، پشتیبانی از پردازنده گرافیکی و اکوسیستم غنی آن آشنا شدید.
پیشنهاد میشود ابتدا مقاله بخش اول را بخوانید.
حالا وقت آن رسیده که وارد عمل شویم و با مفاهیم پایهای PyTorch آشنا شویم. در این بخش، نحوه نصب PyTorch، کار با تنسورها، ساخت یک شبکه عصبی ساده و آموزش آن روی یک مجموعه داده نمونه را قدم به قدم بررسی میکنیم. هدف این است که شما با اعتماد به نفس وارد دنیای یادگیری عمیق شوید.
نصب و راهاندازی PyTorch
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121برای اطمینان از نصب صحیح، کد زیر را اجرا کنید:
import torch
print("torch version:", torch.__version__)
print("cuda availability:", torch.cuda.is_available())
torch.cuda.device_count()
curdev = torch.cuda.current_device()
torch.cuda.device(curdev)
print("GPU type:", torch.cuda.get_device_name(curdev))
اگر GPU ندارید، میتوانید نسخه CPU را با حذف بخش CUDA نصب کنید:
pip install torch torchvision torchaudio
تسلط بر تنسورها: قلب PyTorch
import torch
# ایجاد تنسور اولیه
weights = torch.tensor([[0.5, -0.2],
[1.3, 0.8]], requires_grad=True)
# داده ورودی
inputs = torch.tensor([[1.0, 2.0],
[3.0, 4.0]])
# محاسبه خروجی
outputs = torch.matmul(inputs, weights) # ضرب ماتریسی
loss = outputs.sum() # تابع خطا
# محاسبه گرادیانها
loss.backward()
print("گرادیانهای وزنها:")
print(weights.grad)
طراحی شبکههای عصبی
-
لایهها را به صورت ماژولار تعریف کنید،
-
جریان داده را در متد forward کنترل نمایید
-
و از مکانیزمهای خودکار PyTorch استفاده کامل ببرید.
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) # 3 کانال ورودی (RGB)، 6 کانال خروجی، فیلتر 5x5
self.pool = nn.MaxPool2d(2, 2) # MaxPooling با پنجره 2x2 و گام (stride) 2
self.fc1 = nn.Linear(6 * 30 * 30, 120) # لایه خطی (تغییر ابعاد متناسب با خروجی conv1)
def forward(self, x):
x = self.pool(F.relu(self.conv1(x))) # کانولوشن → ReLU → MaxPooling
x = x.view(-1, 6 * 30 * 30) # تغییر شکل به بردار برای لایه خطی
x = F.relu(self.fc1(x)) # لایه خطی → ReLU
return x- لایههای کانولوشنی
nn.Conv2d(
in_channels=3, # مثلاً 3 کانال برای تصاویر RGB
out_channels=16, # 16 فیلتر برای استخراج ۱۶ ویژگی مختلف
kernel_size=3, # فیلتر 3x3
stride=1, # گام 1 پیکسل
padding=1 # حفظ ابعاد فضایی
)
-
لایههای بازگشتی (RNN/LSTM):
- اتصالهای باقیمانده (Residual Connections):
- مکانیزم توجه (Attention):
- لایههای نرمالسازی (BatchNorm/LayerNorm):
- Droput
- لایههای تماممتصل (Linear):
- لایههای Pooling:
در کد زیر تمام کدهای بخشهای توضیح داده شده را مشاهده میکنید.
nn.LSTM(
input_size=100, # بعد کلمات
hidden_size=50, # بعد فضای پنهان
num_layers=2, # 2 لایه LSTM روی هم
batch_first=True # فرمت (batch, sequence, features)
)
class ResidualBlock(nn.Module):
def forward(self, x):
residual = x
x = F.relu(self.conv1(x))
x = self.conv2(x)
x += residual # اتصال باقیمانده
return F.relu(x)
# مکانیزم توجه
scores = torch.matmul(Q, K.transpose(1, 2)) # محاسبه اهمیت
attention = F.softmax(scores, dim=-1) # نرمالسازی به احتمال
#لایههای نرمالسازی
nn.BatchNorm2d(64) # برای لایههای کانولوشنی
nn.LayerNorm(128) # برای ترنسفورمرها
#Dropout
nn.Dropout(0.5) # 50% نورونها در آموزش غیرفعال میشوند
#linear
nn.Linear(
in_features=256, # بعد ورودی
out_features=10 # تعداد کلاسها
)
#pooling
nn.MaxPool2d(2, 2) # پنجره 2x2 با گام 2
nn.AvgPool2d(2) # میانگینگیری روی 2x2
آموزش شبکههای عصبی در PyTorch
- آمادهسازی دادهها
import torch
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
# تعریف پیشپردازشها
transform = transforms.Compose([
transforms.ToTensor(), # تبدیل تصویر به تنسور
# نرمالسازی با میانگین و انحراف معیار MNIST
transforms.Normalize((0.1307,), (0.3081,))
])
# بارگذاری دادههای آموزشی و آزمایشی
train_dataset = datasets.MNIST(
root='./data', train=True, download=True, transform=transform)
test_dataset = datasets.MNIST(
root='./data', train=False, download=True, transform=transform)
# تعریف DataLoader
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)
DataLoader: دادهها را بهصورت دستهای بارگذاری میکند و قابلیتهایی مثل همزدن دادهها (shuffle) را فراهم میکند.
- تعریف مدل
import torch.nn as nn
import torch.nn.functional as F
class MNISTNet(nn.Module):
def __init__(self):
super(MNISTNet, self).__init__()
self.conv1 = nn.Conv2d(1, 16, 3) # 1 کانال ورودی (تصاویر خاکستری)
self.conv2 = nn.Conv2d(16, 32, 3)
self.pool = nn.MaxPool2d(2, 2)
self.fc1 = nn.Linear(32 * 5 * 5, 128)
self.fc2 = nn.Linear(128, 10) # 10 کلاس برای اعداد 0 تا 9
def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = x.view(-1, 32 * 5 * 5) # تغییر شکل برای لایه خطی
x = F.relu(self.fc1(x))
x = self.fc2(x) # خروجی خام (logits)
return x
سپس مرحله بعدی
مراحل 3 و 4 در کد زیر نشان داده شده است:
#3
import torch.optim as optim
model = MNISTNet()
criterion = nn.CrossEntropyLoss() # تابع خطا
optimizer = optim.Adam(model.parameters(), lr=0.001) # بهینهساز
#4
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = model.to(device) # انتقال مدل به GPU (در صورت موجود بودن)
def train(model, train_loader, criterion, optimizer, epoch):
model.train() # حالت آموزشی
running_loss = 0.0
for i, (images, labels) in enumerate(train_loader):
images, labels = images.to(device), labels.to(device)
# صفر کردن گرادیانها
optimizer.zero_grad()
# پیشرو (Forward)
outputs = model(images)
loss = criterion(outputs, labels)
# پسرو (Backward) و بهروزرسانی
loss.backward()
optimizer.step()
running_loss += loss.item()
if i % 200 == 199: # چاپ هر 200 دسته
print(
f'[Epoch {epoch}, Batch {i+1}] Loss: {running_loss / 200:.3f}')
running_loss = 0.0
# اجرای آموزش برای 5 دوره
for epoch in range(1, 6):
train(model, train_loader, criterion, optimizer, epoch)
-
ارزیابی مدل
def test(model, test_loader, criterion):
model.eval() # حالت ارزیابی
test_loss = 0
correct = 0
with torch.no_grad(): # غیرفعال کردن محاسبه گرادیان
for images, labels in test_loader:
images, labels = images.to(device), labels.to(device)
outputs = model(images)
test_loss += criterion(outputs, labels).item()
# کلاس با بالاترین احتمال
pred = outputs.argmax(dim=1, keepdim=True)
correct += pred.eq(labels.view_as(pred)).sum().item()
test_loss /= len(test_loader.dataset)
accuracy = 100. * correct / len(test_loader.dataset)
print(
f'Test set: Average loss: {test_loss:.4f}, Accuracy: {correct}/{len(test_loader.dataset)} ({accuracy:.2f}%)')
# اجرای ارزیابی
test(model, test_loader, criterion)
خروجی نمونه ممکن است چیزی شبیه این باشد که نشاندهنده دقت بالای مدل روی مجموعه داده MNIST است:
Test set: Average loss: 0.0009, Accuracy: 9876/10000 (98.76%)
جمعبندی
در این مقاله، شما را قدم به قدم با دنیای PyTorch آشنا کردیم. از نصب و کار با تنسورها شروع کردیم، سپس به طراحی و آموزش شبکههای عصبی پرداختیم. با ما همراه باشید تا در بخش سوم به مفاهیم پیشرفتهتری مانند انتقال یادگیری و مدیریت حافظه خواهیم پرداخت.
سوالات متداول
-
تنسور در پایتورچ چیست؟
- Autograd در PyTorch چیست؟
-
علت استفاده از Module در پایتورچ چیست؟
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
ثبت نظر