مرا به خاطر بسپار

آموزش پیشرفته PyTorch: یادگیری انتقالی، مدیریت حافظه و بهینه‌سازی مدل‌ها

بازدید: 29 آخرین به‌روزرسانی: 05 مهر 1404

مقدمه

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

یادگیری انتقالی

یادگیری انتقالی (Transfer Learning) روشی است که در آن از یک مدل از پیش آموزش‌دیده (pre-trained) برای حل مسائل جدید استفاده می‌شود. این روش به‌ویژه زمانی مفید است که داده‌های کافی برای آموزش یک مدل از صفر ندارید. مدل‌های از پیش آموزش‌دیده، مانند ResNet یا BERT، روی مجموعه داده‌های عظیم (مانند ImageNet یا Wikipedia) آموزش دیده‌اند و دانش عمومی را در خود ذخیره کرده‌اند.
چرا یادگیری انتقالی مهم است؟
صرفه‌جویی در زمان: آموزش یک مدل از صفر زمان‌بر است؛ یادگیری انتقالی این زمان را کاهش می‌دهد.
نیاز به داده کمتر: با استفاده از دانش قبلی مدل، حتی با داده‌های محدود می‌توانید نتایج خوبی بگیرید.
کاربرد گسترده: از تشخیص تصویر تا پردازش زبان طبیعی، یادگیری انتقالی در همه‌جا کاربرد دارد.
پیاده‌سازی یادگیری انتقالی در PyTorch
بیایید یک مثال عملی برای استفاده از مدل ResNet18 از پیش آموزش‌دیده برای طبقه‌بندی تصاویر سفارشی (مثلاً تشخیص گربه در مقابل سگ) پیاده‌سازی کنیم.
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
from torchvision.models import resnet18, ResNet18_Weights

# تنظیم دستگاه (GPU یا CPU)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# بارگذاری مدل از پیش آموزش‌دیده
model = resnet18(weights=ResNet18_Weights.IMAGENET1K_V1)

# فریز کردن لایه‌های مدل برای جلوگیری از تغییر وزن‌ها
for param in model.parameters():
    param.requires_grad = False

# جایگزینی لایه نهایی برای تطبیق با تعداد کلاس‌های جدید (مثلاً 2 کلاس: گربه و سگ)
num_ftrs = model.fc.in_features
model.fc = nn.Linear(num_ftrs, 2)  # دو کلاس خروجی
model = model.to(device)

# تعریف تابع تبدیل برای پیش‌پردازش تصاویر
transform = transforms.Compose([
    transforms.Resize((224, 224)),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])

#   هستند'train' و 'test'  فرض کنید داده‌ها در پوشه‌های 
train_dataset = torchvision.datasets.ImageFolder('path/to/train', transform=transform)
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=32, shuffle=True)

# تعریف تابع loss و بهینه‌ساز
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.fc.parameters(), lr=0.001)

# آموزش مدل
model.train()
for epoch in range(5):  # 5 epoch برای مثال
    running_loss = 0.0
    for inputs, labels in train_loader:
        inputs, labels = inputs.to(device), labels.to(device)
        optimizer.zero_grad()
        outputs = model(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()
        running_loss += loss.item()
    print(f"Epoch {epoch+1}, Loss: {running_loss/len(train_loader)}")

print("آموزش کامل شد!")
  • نکته عملی: برای مجموعه داده خود، مسیر داده‌ها را در ImageFolder تنظیم کنید. همچنین، می‌توانید لایه‌های بیشتری را unfreeze کنید تا مدل بهتر با داده‌هایتان سازگار شود، اما این کار نیاز به منابع محاسباتی بیشتری دارد.

مدیریت حافظه در PyTorch

آموزش مدل‌های یادگیری عمیق، به‌ویژه در شبکه‌های عمیق یا با داده‌های بزرگ، می‌تواند حافظه پردازنده گرافیکی GPU را به سرعت پر کند. مدیریت صحیح حافظه در PyTorch برای جلوگیری از خطاهای OutOfMemoryError حیاتی است. در سال ۲۰۲۵، با افزایش اندازه مدل‌ها (مانند مدل‌های زبانی بزرگ)، این مهارت بیش از پیش اهمیت دارد.
روش‌های مدیریت حافظه
استفاده از batch size مناسب: کاهش اندازه دسته (batch size) مصرف حافظه را کم می‌کند.
حذف متغیرهای غیرضروری: از del برای آزادسازی متغیرها و torch.no_grad() برای جلوگیری از ذخیره گرادیان‌ها استفاده کنید.
تخلیه بار به CPU: برخی محاسبات را در صورت محدودیت GPU به CPU منتقل کنید.
استفاده از Mixed Precision Training: ترکیب دقت 16 بیتی و 32 بیتی برای کاهش مصرف حافظه و افزایش سرعت سودمند خواهد بود.
پیاده‌سازی Mixed Precision Training
PyTorch با ماژول torch.cuda.amp این فرآیند را ساده کرده است. در زیر یک مثال ارائه شده است:
import torch
import torch.nn as nn
import torch.optim as optim
from torch.cuda.amp import GradScaler, autocast
from torchvision.models import resnet18, ResNet18_Weights

# تنظیم دستگاه
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# بارگذاری مدل
model = resnet18(weights=ResNet18_Weights.IMAGENET1K_V1).to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
scaler = GradScaler()  # برای Mixed Precision

# فرض کنید train_loader از قبل تعریف شده
model.train()
for epoch in range(5):
    running_loss = 0.0
    for inputs, labels in train_loader:
        inputs, labels = inputs.to(device), labels.to(device)
        optimizer.zero_grad()
        
        # استفاده از autocast برای محاسبات با دقت ترکیبی
        with autocast():
            outputs = model(inputs)
            loss = criterion(outputs, labels)
        
        # مقیاس‌بندی گرادیان‌ها برای جلوگیری از underflow
        scaler.scale(loss).backward()
        scaler.step(optimizer)
        scaler.update()
        running_loss += loss.item()
    print(f"Epoch {epoch+1}, Loss: {running_loss/len(train_loader)}")

print("آموزش با Mixed Precision کامل شد!")

نکته: استفاده از torch.cuda.amp می‌تواند تا ۵۰ درصد حافظه GPU را صرفه‌جویی کند و آموزش را سریع‌تر کند. برای مدل‌های بزرگ، این روش ضروری است.

بهینه‌سازی مدل‌ها برای استقرار

وقتی مدل شما آماده شد برای استقرار (Deployment)، باید آن را برای استفاده در محیط‌های واقعی بهینه کنید. این شامل کاهش اندازه مدل، بهبود سرعت استنتاج (inference) و اطمینان از مقیاس‌پذیری است.
روش‌های بهینه‌سازی
Pruning: حذف نورون‌ها یا اتصالات غیرضروری برای سبک‌تر کردن مدل.
TorchScript و ONNX: تبدیل مدل به فرمت‌های قابل حمل برای استقرار در محیط‌های غیر PyTorch.
Quantization: کاهش دقت وزن‌ها (مثلاً از 32 بیت به 8 بیت) برای کاهش اندازه مدل.
پیاده‌سازی Quantization در PyTorch
در این مثال، مدل ResNet18 را به فرمت quantized تبدیل می‌کنیم:
import torch
import torchvision.models as models

# بارگذاری مدل
model = models.resnet18(weights=models.ResNet18_Weights.IMAGENET1K_V1)
model.eval()

# اعمال Quantization پویا
quantized_model = torch.quantization.quantize_dynamic(
    model, {torch.nn.Linear}, dtype=torch.qint8
)

# ذخیره مدل
torch.jit.save(torch.jit.script(quantized_model), "quantized_resnet18.pt")

print("مدل Quantized ذخیره شد!")

مدل Quantized تا ۴ برابر کوچک‌تر و سریع‌تر است، که برای استقرار روی دستگاه‌های موبایل یا Edge ایده‌آل است.

کار با مدل‌های زبانی بزرگ یا LLMs در PyTorch

در سال ۲۰۲۵، مدل‌های زبانی بزرگ مانند Grok یا LLaMA در مرکز توجه هستند. PyTorch با کتابخانه Hugging Face Transformers کار با این مدل‌ها را آسان کرده است. بیایید یک مثال ساده از fine-tuning یک مدل زبانی بیاوریم:

from transformers import AutoModelForSequenceClassification, AutoTokenizer
import torch
from torch.utils.data import DataLoader, Dataset

# تعریف یک دیتاست نمونه
class CustomDataset(Dataset):
    def __init__(self, texts, labels, tokenizer, max_len=128):
        self.texts = texts
        self.labels = labels
        self.tokenizer = tokenizer
        self.max_len = max_len
    
    def __len__(self):
        return len(self.texts)
    
    def __getitem__(self, idx):
        text = self.texts[idx]
        label = self.labels[idx]
        encoding = self.tokenizer(text, return_tensors='pt', max_length=self.max_len, truncation=True, padding='max_length')
        return {
            'input_ids': encoding['input_ids'].flatten(),
            'attention_mask': encoding['attention_mask'].flatten(),
            'labels': torch.tensor(label, dtype=torch.long)
        }

# بارگذاری مدل و توکنایزر
model_name = "bert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSequenceClassification.from_pretrained(model_name, num_labels=2).to('cuda')

# داده‌های نمونه
texts = ["این متن مثبت است", "این متن منفی است"]
labels = [1, 0]
dataset = CustomDataset(texts, labels, tokenizer)
dataloader = DataLoader(dataset, batch_size=2)

# بهینه‌ساز
optimizer = torch.optim.AdamW(model.parameters(), lr=2e-5)

# آموزش
model.train()
for epoch in range(3):
    for batch in dataloader:
        inputs = {k: v.to('cuda') for k, v in batch.items() if k != 'labels'}
        labels = batch['labels'].to('cuda')
        outputs = model(**inputs, labels=labels)
        loss = outputs.loss
        loss.backward()
        optimizer.step()
        optimizer.zero_grad()
        print(f"Epoch {epoch+1}, Loss: {loss.item()}")

print("Fine-tuning کامل شد!")

نکته عملی: برای fine-tuning واقعی، از مجموعه داده‌های بزرگ‌تر (مثلاً از Hugging Face Datasets) استفاده کنید و hyperparameterها را تنظیم کنید.

جمع‌بندی

در این مقاله، شما را با مفاهیم پیشرفته PyTorch مانند یادگیری انتقالی، مدیریت حافظه، بهینه‌سازی مدل و کار با مدل‌های زبانی بزرگ آشنا کردیم. با کدهای عملی ارائه‌شده، می‌توانید این تکنیک‌ها را در پروژه‌های خود پیاده‌سازی کنید. PyTorch به دلیل انعطاف‌پذیری و جامعه قوی، ابزاری بی‌نظیر برای مهندسان یادگیری ماشین در سال ۲۰۲۵ است. حالا که این ابزارها را دارید، یک پروژه جدید شروع کنید – شاید یک مدل تشخیص اشیا یا یک چت‌بات هوشمند! برای ادامه یادگیری، به مستندات رسمی PyTorch یا کتابخانه Hugging Face سر بزنید.

سوالات متداول

  1. چگونه می‌توان یک مدل PyTorch را برای دستگاه‌های Edge بهینه کرد؟
با استفاده از Quantization و Pruning برای کاهش اندازه و افزایش سرعت مدل.
  1. چرا از Adam به عنوان بهینه‌ساز در آموزش مدل‌ها استفاده می‌شود؟
Adam به دلیل سرعت همگرایی بالا و تطبیق‌پذیری با گرادیان‌های متغیر محبوب است.
  1. چرا مدل‌های زبانی بزرگ (LLMs) به منابع محاسباتی زیادی نیاز دارند؟
به دلیل تعداد پارامترهای عظیم (میلیاردها) و محاسبات پیچیده در لایه‌های ترانسفورمر.

منابع

https://simorgh.cloud/
تا چه حد این مطلب برای شما مفید بود؟
بر اساس رای 0 نفر

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

ثبت نظر

نظر دادن