Loading
Loading
PyTorch هي المكتبة الأكثر استخداماً في أبحاث Deep Learning. إنها مرنة، بديهية، وتدعم GPU. معظم نماذج AI الحديثة تُبنى بها.
| | PyTorch | TensorFlow | |-|---------|-----------| | الاستخدام | أبحاث + تطوير | إنتاج + تطوير | | API | Pythonic وبسيط | أكثر تعقيداً | | Debugging | سهل (standard Python) | أصعب | | المجتمع | أكبر في الأبحاث | أكبر في الإنتاج | | النماذج الجاهزة | Hugging Face 🏆 | TF Hub |
Tensor هو مصفوفة متعددة الأبعاد — مثل NumPy لكن مع دعم GPU والـ Autograd.
import torch
x = torch.tensor([1.0, 2.0, 3.0]) # 1D tensor
M = torch.randn(3, 4) # 2D tensor (matrix)
C = torch.zeros(2, 3, 4) # 3D tensor
PyTorch يتتبع كل العمليات تلقائياً ويحسب التدرجات:
x = torch.tensor(3.0, requires_grad=True)
y = x ** 2 + 2 * x + 1 # y = 10
y.backward() # يحسب dy/dx
print(x.grad) # 2x + 2 = 8
هذا هو Backpropagation — تلقائياً!
import torch.nn as nn
class MyNet(nn.Module):
def __init__(self):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(784, 256),
nn.ReLU(),
nn.Dropout(0.3),
nn.Linear(256, 10),
)
def forward(self, x):
return self.layers(x)
model = MyNet()
print(sum(p.numel() for p in model.parameters()), "معامل")
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
criterion = nn.CrossEntropyLoss()
for epoch in range(10):
for X_batch, y_batch in dataloader:
optimizer.zero_grad() # 1. صفّر التدرجات
output = model(X_batch) # 2. Forward Pass
loss = criterion(output, y_batch) # 3. الخطأ
loss.backward() # 4. Backward Pass
optimizer.step() # 5. تحديث الأوزان
device = "cuda" if torch.cuda.is_available() else "cpu"
model = model.to(device)
# كل البيانات على نفس الـ device
X_batch = X_batch.to(device)
y_batch = y_batch.to(device)
from torch.utils.data import Dataset, DataLoader
class MyDataset(Dataset):
def __init__(self, X, y):
self.X = torch.FloatTensor(X)
self.y = torch.LongTensor(y)
def __len__(self):
return len(self.y)
def __getitem__(self, idx):
return self.X[idx], self.y[idx]
loader = DataLoader(MyDataset(X, y), batch_size=32, shuffle=True)
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import Dataset, DataLoader, random_split
import numpy as np
print("=" * 55)
print("PyTorch: بناء شبكة عصبية كاملة")
print("=" * 55)
print(f"\nPyTorch version: {torch.__version__}")
print(f"GPU متاح: {torch.cuda.is_available()}")
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Device: {device}")
# ─────────────────────────────────────────
# 1. Dataset مخصص
# ─────────────────────────────────────────
class CirclesDataset(Dataset):
"""بيانات دوائر — تصنيف غير خطي"""
def __init__(self, n_samples: int = 1000, noise: float = 0.1):
torch.manual_seed(42)
# دائرة داخلية
r1 = torch.randn(n_samples // 2, 2) * 0.5
# دائرة خارجية
angles = torch.rand(n_samples // 2) * 2 * 3.14159
r2 = torch.stack([torch.cos(angles) * 2, torch.sin(angles) * 2], dim=1)
r2 += torch.randn_like(r2) * noise
self.X = torch.vstack([r1, r2]).float()
self.y = torch.cat([torch.zeros(n_samples // 2),
torch.ones(n_samples // 2)]).long()
def __len__(self): return len(self.y)
def __getitem__(self, i): return self.X[i], self.y[i]
dataset = CirclesDataset(n_samples=1000)
train_set, val_set = random_split(dataset, [800, 200])
train_loader = DataLoader(train_set, batch_size=32, shuffle=True)
val_loader = DataLoader(val_set, batch_size=64)
print(f"\n1. Dataset جاهز: {len(train_set)} train / {len(val_set)} val")
# ─────────────────────────────────────────
# 2. بناء الشبكة
# ─────────────────────────────────────────
class DeepClassifier(nn.Module):
def __init__(self, input_dim: int = 2, hidden_dim: int = 64, num_classes: int = 2):
super().__init__()
self.net = nn.Sequential(
nn.Linear(input_dim, hidden_dim),
nn.BatchNorm1d(hidden_dim),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(hidden_dim, hidden_dim),
nn.BatchNorm1d(hidden_dim),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(hidden_dim, hidden_dim // 2),
nn.ReLU(),
nn.Linear(hidden_dim // 2, num_classes),
)
def forward(self, x: torch.Tensor) -> torch.Tensor:
return self.net(x)
model = DeepClassifier().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.AdamW(model.parameters(), lr=0.01, weight_decay=1e-4)
scheduler = optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=20)
total_params = sum(p.numel() for p in model.parameters())
print(f"2. النموذج: {total_params:,} معامل")
# ─────────────────────────────────────────
# 3. حلقة التدريب
# ─────────────────────────────────────────
def train_epoch(model, loader, optimizer, criterion):
model.train()
total_loss, correct, total = 0, 0, 0
for X, y in loader:
X, y = X.to(device), y.to(device)
optimizer.zero_grad()
out = model(X)
loss = criterion(out, y)
loss.backward()
optimizer.step()
total_loss += loss.item() * len(y)
correct += (out.argmax(1) == y).sum().item()
total += len(y)
return total_loss / total, correct / total
def eval_epoch(model, loader, criterion):
model.eval()
total_loss, correct, total = 0, 0, 0
with torch.no_grad():
for X, y in loader:
X, y = X.to(device), y.to(device)
out = model(X)
total_loss += criterion(out, y).item() * len(y)
correct += (out.argmax(1) == y).sum().item()
total += len(y)
return total_loss / total, correct / total
print("\n3. التدريب:")
print(f" {'Epoch':6s} | {'Train Loss':10s} | {'Train Acc':9s} | {'Val Acc':8s} | LR")
print(" " + "-" * 55)
best_val_acc = 0
for epoch in range(1, 21):
tr_loss, tr_acc = train_epoch(model, train_loader, optimizer, criterion)
vl_loss, vl_acc = eval_epoch(model, val_loader, criterion)
scheduler.step()
lr = optimizer.param_groups[0]["lr"]
if vl_acc > best_val_acc:
best_val_acc = vl_acc
torch.save(model.state_dict(), "best_model.pt")
if epoch % 5 == 0 or epoch == 1:
print(f" {epoch:6d} | {tr_loss:10.4f} | {tr_acc:9.1%} | {vl_acc:8.1%} | {lr:.5f}")
print(f"\n أفضل Val Accuracy: {best_val_acc:.1%}")