🐍 کتابخانه مرجع پایتون

🔥 مبانی 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()

📌 نکات کلیدی

← قبلی: مبانی TensorFlow → بعدی: NLP با NLTK ↑ بازگشت به فهرست پیشرفته