🔥 مبانی PyTorch
PyTorch یک کتابخانه متنباز برای یادگیری ماشین و یادگیری عمیق است که توسط آزمایشگاه تحقیقات هوش مصنوعی فیسبوک (FAIR) توسعه داده شده است [citation:1]. PyTorch با ارائه محاسبات داینامیک (Dynamic Computation Graphs) و رابط کاربری پایتونیک، به یکی از محبوبترین فریمورکهای تحقیق و توسعه در حوزه هوش مصنوعی تبدیل شده است [citation:4][citation:8].
پیشنیاز: آشنایی با Python، NumPy و مفاهیم پایه شبکههای عصبی.
🔹 نصب و import
# نصب (در محیط واقعی)
# pip install torch torchvision torchaudio
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
# بررسی نسخه و GPU
print(f"PyTorch version: {torch.__version__}")
print("CUDA Available:", torch.cuda.is_available())
if torch.cuda.is_available():
print(f"CUDA Device: {torch.cuda.get_device_name(0)}")
print("PyTorch imported successfully!")
🔹 مفاهیم پایه: Tensor
Tensor ساختار داده اصلی در PyTorch است که بسیار شبیه به آرایههای NumPy عمل میکند، با این تفاوت که میتواند روی GPU اجرا شود [citation:2][citation:6].
import torch
import numpy as np
# ===== ایجاد Tensor از داده =====
data = [[1, 2], [3, 4]]
tensor_from_data = torch.tensor(data)
print("Tensor from data:\n", tensor_from_data)
# ===== ایجاد Tensor از NumPy =====
np_array = np.array(data)
tensor_from_np = torch.from_numpy(np_array)
print("\nTensor from NumPy:\n", tensor_from_np)
# ===== ایجاد Tensor با مقدار ثابت =====
zeros = torch.zeros(3, 4)
ones = torch.ones(2, 3)
eye = torch.eye(4)
print("\nZeros tensor:\n", zeros)
print("\nOnes tensor:\n", ones)
print("\nIdentity matrix:\n", eye)
# ===== ایجاد Tensor تصادفی =====
rand_tensor = torch.rand(3, 4)
print("\nRandom tensor:\n", rand_tensor)
# ===== ویژگیهای Tensor =====
print(f"\nShape: {rand_tensor.shape}")
print(f"Datatype: {rand_tensor.dtype}")
print(f"Device: {rand_tensor.device}")
🔹 عملیات روی Tensorها
import torch
tensor = torch.tensor([[1, 2, 3], [4, 5, 6]])
# ===== Indexing و Slicing =====
print("Original tensor:\n", tensor)
print("\nFirst row:", tensor[0])
print("First column:", tensor[:, 0])
print("Element (1, 2):", tensor[1][2])
# ===== عملیات ریاضی =====
print(f"\nAddition: {tensor + 10}")
print(f"Multiplication: {tensor * 2}")
print(f"Power: {tensor ** 2}")
# ===== عملیات ماتریسی =====
t1 = torch.tensor([[1, 2], [3, 4]])
t2 = torch.tensor([[5, 6], [7, 8]])
print("\nMatrix multiplication:\n", torch.matmul(t1, t2))
print("Element-wise multiplication:\n", t1 * t2)
# ===== تغییر شکل =====
reshaped = tensor.reshape(3, 2)
print("\nReshaped (3x2):\n", reshaped)
flattened = tensor.flatten()
print("Flattened:", flattened)
# ===== انتقال به GPU (اگر موجود باشد) =====
device = "cuda" if torch.cuda.is_available() else "cpu"
tensor_on_gpu = tensor.to(device)
print(f"\nTensor on: {tensor_on_gpu.device}")
🔹 Autograd (محاسبه خودکار گرادیان)
Autograd موتور محاسبه گرادیان در PyTorch است که به صورت خودکار مشتقات را برای بهروزرسانی وزنهای شبکه محاسبه میکند [citation:1][citation:6].
import torch
# ===== ایجاد Tensor با requires_grad =====
x = torch.tensor(3.5, requires_grad=True)
print(f"x: {x}")
# ===== تعریف تابع =====
y = (x - 1) * (x - 2) * (x - 3)
print(f"y: {y}")
# ===== محاسبه گرادیان =====
y.backward()
print(f"Gradient dy/dx: {x.grad}")
# ===== مثال با Tensor =====
x_tensor = torch.tensor([[1., -1.], [1., 1.]], requires_grad=True)
out = x_tensor.pow(2).sum()
out.backward()
print("\nGradient for matrix:\n", x_tensor.grad)
🔹 ساخت مدل با nn.Module
همه مدلهای PyTorch با ارثبری از کلاس nn.Module ساخته میشوند [citation:1][citation:5][citation:9].
import torch
import torch.nn as nn
import torch.nn.functional as F
# ===== تعریف مدل =====
class SimpleNetwork(nn.Module):
def __init__(self):
super(SimpleNetwork, self).__init__()
self.fc1 = nn.Linear(784, 128) # 28x28 = 784 ورودی
self.fc2 = nn.Linear(128, 64) # لایه پنهان
self.fc3 = nn.Linear(64, 10) # 10 خروجی (اعداد 0 تا 9)
self.dropout = nn.Dropout(0.2)
def forward(self, x):
x = x.view(-1, 784) # صاف کردن تصویر
x = F.relu(self.fc1(x))
x = self.dropout(x)
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
# ===== ایجاد مدل =====
model = SimpleNetwork()
print("Model architecture:")
print(model)
# ===== محاسبه تعداد پارامترها =====
total_params = sum(p.numel() for p in model.parameters())
print(f"\nTotal parameters: {total_params:,}")
🔹 آموزش مدل با دیتاست MNIST
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
# ===== ۱. پیشپردازش داده =====
transform = transforms.Compose([
transforms.ToTensor(), # تبدیل تصویر به Tensor
transforms.Normalize((0.5,), (0.5,)) # نرمالسازی به محدوده [-1, 1]
])
# ===== ۲. بارگذاری داده =====
train_dataset = datasets.MNIST(
root='./data', train=True, download=True, transform=transform
)
test_dataset = datasets.MNIST(
root='./data', train=False, download=True, transform=transform
)
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)
print(f"Train samples: {len(train_dataset)}")
print(f"Test samples: {len(test_dataset)}")
# ===== ۳. تعریف مدل =====
class SimpleNetwork(nn.Module):
def __init__(self):
super(SimpleNetwork, self).__init__()
self.fc1 = nn.Linear(784, 128)
self.fc2 = nn.Linear(128, 64)
self.fc3 = nn.Linear(64, 10)
self.dropout = nn.Dropout(0.2)
def forward(self, x):
x = x.view(-1, 784)
x = F.relu(self.fc1(x))
x = self.dropout(x)
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
model = SimpleNetwork()
# ===== ۴. تنظیم Loss و Optimizer =====
criterion = nn.CrossEntropyLoss() # تابع ضرر برای طبقهبندی
optimizer = optim.Adam(model.parameters(), lr=0.001) # بهینهساز Adam
# ===== ۵. حلقه آموزش =====
epochs = 5
print("\nStarting training...")
for epoch in range(epochs):
model.train()
running_loss = 0.0
correct = 0
total = 0
for images, labels in train_loader:
# صفر کردن گرادیانها
optimizer.zero_grad()
# پیشبینی
outputs = model(images)
# محاسبه ضرر
loss = criterion(outputs, labels)
# محاسبه گرادیان (backpropagation)
loss.backward()
# بهروزرسانی وزنها
optimizer.step()
running_loss += loss.item()
_, predicted = torch.max(outputs, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
train_acc = 100 * correct / total
print(f"Epoch [{epoch+1}/{epochs}] - Loss: {running_loss/len(train_loader):.4f}, Accuracy: {train_acc:.2f}%")
print("Training completed!")
# ===== ۶. ارزیابی روی داده تست =====
model.eval()
correct = 0
total = 0
with torch.no_grad():
for images, labels in test_loader:
outputs = model(images)
_, predicted = torch.max(outputs, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
test_acc = 100 * correct / total
print(f"\nTest Accuracy: {test_acc:.2f}%")
🔹 ذخیره و بازیابی مدل
import torch
import torch.nn as nn
# ===== تعریف مدل (برای مثال) =====
class SimpleModel(nn.Module):
def __init__(self):
super(SimpleModel, self).__init__()
self.fc = nn.Linear(10, 5)
def forward(self, x):
return self.fc(x)
model = SimpleModel()
# ===== ذخیره کل مدل =====
torch.save(model, 'model_full.pt')
print("Model saved as 'model_full.pt'")
# ===== ذخیره فقط state_dict =====
torch.save(model.state_dict(), 'model_weights.pt')
print("Weights saved as 'model_weights.pt'")
# ===== بارگذاری کل مدل =====
loaded_model = torch.load('model_full.pt')
print("Full model loaded successfully!")
# ===== بارگذاری state_dict =====
new_model = SimpleModel()
new_model.load_state_dict(torch.load('model_weights.pt'))
new_model.eval()
print("Weights loaded successfully!")
# ===== ذخیره checkpoint شامل optimizer و epoch =====
checkpoint = {
'epoch': 10,
'model_state_dict': model.state_dict(),
'optimizer_state_dict': optimizer.state_dict(),
'loss': 0.5
}
torch.save(checkpoint, 'checkpoint.pt')
print("Checkpoint saved successfully!")
# ===== بارگذاری checkpoint =====
# checkpoint = torch.load('checkpoint.pt')
# model.load_state_dict(checkpoint['model_state_dict'])
# optimizer.load_state_dict(checkpoint['optimizer_state_dict'])
# epoch = checkpoint['epoch']
# loss = checkpoint['loss']
🔹 استفاده از GPU برای تسریع
import torch
import torch.nn as nn
# ===== بررسی در دسترس بودن GPU =====
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"Using device: {device}")
# ===== انتقال مدل به GPU =====
class SimpleNetwork(nn.Module):
def __init__(self):
super(SimpleNetwork, self).__init__()
self.fc = nn.Linear(100, 10)
def forward(self, x):
return self.fc(x)
model = SimpleNetwork()
model = model.to(device) # انتقال مدل به GPU
# ===== انتقال داده به GPU =====
sample_input = torch.randn(32, 100) # batch=32, features=100
sample_input = sample_input.to(device) # انتقال داده به GPU
# ===== اجرا روی GPU =====
output = model(sample_input)
print(f"Output shape: {output.shape}")
print(f"Output device: {output.device}")
# ===== آموزش روی GPU =====
# (نیاز به انتقال DataLoaderها به GPU دارد)
# for images, labels in train_loader:
# images, labels = images.to(device), labels.to(device)
# outputs = model(images)
# loss = criterion(outputs, labels)
# # ... ادامه آموزش
🔹 مثال جامع: طبقهبندی تصاویر
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
import matplotlib.pyplot as plt
class ImageClassifier:
def __init__(self):
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
self.model = None
self.optimizer = None
self.criterion = nn.CrossEntropyLoss()
self.train_losses = []
self.train_accs = []
self.test_accs = []
def build_model(self):
"""ساخت مدل CNN ساده"""
self.model = nn.Sequential(
nn.Conv2d(1, 32, kernel_size=3, padding=1),
nn.ReLU(),
nn.MaxPool2d(2),
nn.Conv2d(32, 64, kernel_size=3, padding=1),
nn.ReLU(),
nn.MaxPool2d(2),
nn.Flatten(),
nn.Linear(64 * 7 * 7, 128),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(128, 10)
).to(self.device)
self.optimizer = optim.Adam(self.model.parameters(), lr=0.001)
return self.model
def get_data_loaders(self, batch_size=64):
"""بارگذاری داده MNIST"""
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))
])
train_dataset = datasets.MNIST('./data', train=True, download=True, transform=transform)
test_dataset = datasets.MNIST('./data', train=False, download=True, transform=transform)
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)
return train_loader, test_loader
def train(self, train_loader, epochs=5):
"""آموزش مدل"""
self.model.train()
print(f"Training on {self.device}...")
for epoch in range(epochs):
running_loss = 0.0
correct = 0
total = 0
for images, labels in train_loader:
images, labels = images.to(self.device), labels.to(self.device)
self.optimizer.zero_grad()
outputs = self.model(images)
loss = self.criterion(outputs, labels)
loss.backward()
self.optimizer.step()
running_loss += loss.item()
_, predicted = torch.max(outputs, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
epoch_loss = running_loss / len(train_loader)
epoch_acc = 100 * correct / total
self.train_losses.append(epoch_loss)
self.train_accs.append(epoch_acc)
print(f"Epoch [{epoch+1}/{epochs}] - Loss: {epoch_loss:.4f}, Accuracy: {epoch_acc:.2f}%")
return self.model
def evaluate(self, test_loader):
"""ارزیابی مدل"""
self.model.eval()
correct = 0
total = 0
with torch.no_grad():
for images, labels in test_loader:
images, labels = images.to(self.device), labels.to(self.device)
outputs = self.model(images)
_, predicted = torch.max(outputs, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
acc = 100 * correct / total
self.test_accs.append(acc)
print(f"Test Accuracy: {acc:.2f}%")
return acc
def predict(self, image):
"""پیشبینی یک تصویر"""
self.model.eval()
if len(image.shape) == 3:
image = image.unsqueeze(0)
image = image.to(self.device)
with torch.no_grad():
output = self.model(image)
_, predicted = torch.max(output, 1)
return predicted.item()
# ===== استفاده =====
classifier = ImageClassifier()
classifier.build_model()
# بارگذاری داده
train_loader, test_loader = classifier.get_data_loaders()
# آموزش
classifier.train(train_loader, epochs=3)
# ارزیابی
classifier.evaluate(test_loader)
# نمایش نمونه پیشبینی
test_images, test_labels = next(iter(test_loader))
sample_idx = 0
pred = classifier.predict(test_images[sample_idx])
print(f"\nSample prediction: {pred}")
print(f"True label: {test_labels[sample_idx].item()}")
# نمایش نمودارهای آموزش
plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(classifier.train_losses)
plt.title("Training Loss")
plt.xlabel("Epoch")
plt.ylabel("Loss")
plt.subplot(1, 2, 2)
plt.plot(classifier.train_accs, label='Train')
plt.plot(classifier.test_accs, label='Test')
plt.title("Accuracy")
plt.xlabel("Epoch")
plt.ylabel("Accuracy (%)")
plt.legend()
plt.show()
📌 نکات کلیدی
- ✅ Tensor ساختار داده اصلی در PyTorch است که میتواند روی GPU اجرا شود [citation:2][citation:6].
- ✅ Autograd بهصورت خودکار گرادیانها را برای بهروزرسانی وزنها محاسبه میکند [citation:1][citation:6].
- ✅ مدلها با ارثبری از nn.Module ساخته میشوند و تابع
forwardمسیر پیشبینی را مشخص میکند [citation:1][citation:5]. - ✅ DataLoader دادهها را به صورت mini-batch برای آموزش کارآمد آماده میکند [citation:9].
- ✅ optimizer.zero_grad() گرادیانها را قبل از هر مرحله صفر میکند.
- ✅ loss.backward() گرادیانها را محاسبه میکند و optimizer.step() وزنها را بهروز میکند [citation:7].
- ✅ با model.to(device) مدل را به GPU منتقل کنید [citation:2].
- ✅ مدلها را میتوان با torch.save و torch.load ذخیره و بازیابی کرد.
- ✅ PyTorch به دلیل محاسبات داینامیک و رابط کاربری پایتونیک برای تحقیق و توسعه بسیار محبوب است [citation:4][citation:8].