Back to posts
PyTorch ile Uçtan Uca Model Geliştirme Rehberi

PyTorch ile Uçtan Uca Model Geliştirme Rehberi

buraxta / April 29, 2025

PyTorch ekosisteminde başarılı bir şekilde ilerlemek için, veri hazırlamadan modeli dağıtmaya kadar uzanan sağlam bir iş akışını anlamak hayati önem taşır. Derin öğrenme projelerindeki en büyük engellerden biri, farklı bileşenleri nasıl düzgün bir şekilde bir araya getireceğinizi bilmemektir. Bu yazıda, sizi bu engellerin üstesinden getirecek ve verimli PyTorch projeleri geliştirmenizi sağlayacak yapılandırılmış bir yaklaşım sunacağım.

Derin öğrenme modelleriyle çalışırken, tekrarlanan bir süreç izleriz: veri toplama ve hazırlama, model oluşturma, eğitim, değerlendirme ve en sonunda dağıtım. Bu süreç, basit doğrusal regresyondan karmaşık sinir ağlarına kadar tüm modeller için aynı kalır. Fark, her bir adımın karmaşıklığında ve özelleştirme seviyesindedir.

PyTorch'un güzelliği, bu sürecin her adımında size esneklik ve kontrol sağlamasıdır. Ancak bu esneklik, başlangıçta biraz zorlayıcı olabilir. "Doğru yolda mıyım?" ya da "Bu işi daha verimli yapmanın bir yolu var mı?" gibi sorular sormak doğaldır. Bu yazı, tam olarak bu endişeleri gidermek için tasarlandı.

İlerleyen bölümlerde, veri yükleme stratejilerinden model kaydetme tekniklerine kadar her şeyi kapsayan eksiksiz bir PyTorch iş akışı sunacağım. Her adımı detaylı örneklerle açıklayacak ve pratik bilgiler sunacağım. Bu yazının sonunda, kendi derin öğrenme projelerinizi yapılandırmak ve yönetmek için sağlam bir çerçeveye sahip olacaksınız.

Önceki "PyTorch Tensörleri A'dan Z'ye Geliştiriciler İçin Temel Kılavuz?" yazımızda tensörler ve temel operasyonlar gibi PyTorch'un temel taşlarını incelemiştik. Şimdi, bu temeller üzerine inşa ederek, gerçek dünya problemlerini çözmek için PyTorch'u nasıl kullanacağımızı keşfedeceğiz. Hadi başlayalım!

1. Veri Hazırlama ve Yükleme

Derin öğrenme projelerine başlamanın ilk adımı veriyi hazırlamaktır. Veri, modelinizin öğreneceği temel malzemedir.

Veriyi eğitim ve test setlerine ayırma

Verinizi eğitim seti ve test seti olarak ayırmak, modelin gerçek dünyada nasıl performans göstereceğini değerlendirmek için çok önemlidir.

import torch
import numpy as np
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split

# Örnek bir regresyon veri seti oluşturalım
X, y = make_regression(n_samples=1000, n_features=3, noise=20, random_state=42)

# Veriyi eğitim ve test setlerine ayıralım (geleneksel yöntem)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# NumPy dizilerini PyTorch tensorlarına dönüştürelim
X_train = torch.from_numpy(X_train).float()
X_test = torch.from_numpy(X_test).float()
y_train = torch.from_numpy(y_train).float().unsqueeze(dim=1)  # Shapei [batch_size, 1] olarak ayarlıyoruz
y_test = torch.from_numpy(y_test).float().unsqueeze(dim=1)

print(f"Eğitim verisinin boyutu: {X_train.shape}")
print(f"Test verisinin boyutu: {X_test.shape}")
print(f"Eğitim etiketlerinin boyutu: {y_train.shape}")
print(f"Test etiketlerinin boyutu: {y_test.shape}")

PyTorch, özellikle büyük veri setleri için kendi Dataset ve DataLoader sınıflarını sunar:

from torch.utils.data import Dataset, DataLoader

# Özel bir Dataset sınıfı oluşturalım
class RegressionDataset(Dataset):
    def __init__(self, X, y):
        self.X = torch.from_numpy(X).float()
        self.y = torch.from_numpy(y).float().unsqueeze(dim=1)
        
    def __len__(self):
        return len(self.X)
    
    def __getitem__(self, idx):
        return self.X[idx], self.y[idx]

# Dataset nesnelerini oluşturalım
train_dataset = RegressionDataset(X_train.numpy(), y_train.squeeze().numpy())
test_dataset = RegressionDataset(X_test.numpy(), y_test.squeeze().numpy())

# DataLoader nesnelerini oluşturalım
BATCH_SIZE = 32
train_loader = DataLoader(train_dataset, batch_size=BATCH_SIZE, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=BATCH_SIZE)

# DataLoaderın nasıl çalıştığını görelim
for batch_idx, (data, targets) in enumerate(train_loader):
    print(f"Batch {batch_idx+1}:")
    print(f"  Veri şekli: {data.shape}")
    print(f"  Hedef şekli: {targets.shape}")
    if batch_idx == 2:  # Sadece ilk 3 batchi gösterelim
        break

2. Model Oluşturma

PyTorch model oluşturma temelleri

PyTorch'ta model oluşturmanın en yaygın yolu, nn.Module sınıfını miras alan bir sınıf tanımlamaktır:

import torch.nn as nn

# Basit bir doğrusal regresyon modeli
class LinearRegressionModel(nn.Module):
    def __init__(self, input_features, output_features):
        super().__init__()
        self.linear = nn.Linear(input_features, output_features)
        
    def forward(self, x):
        return self.linear(x)

# 3 girdi özelliği ve 1 çıktıya sahip bir model oluşturalım
model = LinearRegressionModel(input_features=3, output_features=1)
print(model)

PyTorch modelinin içeriğini kontrol etme

Model hakkında detaylı bilgi almak için birkaç yöntem:

# Model parametrelerini göster
print("Model parametreleri:")
for name, param in model.named_parameters():
    print(f"Parametre adı: {name}, Şekli: {param.shape}")

# Modelin parametrelerinin sayısı
def count_parameters(model):
    return sum(p.numel() for p in model.parameters() if p.requires_grad)

print(f"Eğitilebilir parametre sayısı: {count_parameters(model)}")

# Model mimarisini göster
print(model)

Tahmin yapma

Model oluşturulduktan sonra, tahmin yapmak basittir:

# Rastgele bir giriş oluşturalım
x = torch.rand(5, 3)  # 5 örnek, her biri 3 özelliğe sahip

# Modelle tahmin yapalım
with torch.inference_mode():
    y_pred = model(x)

print(f"Girdi şekli: {x.shape}")
print(f"Çıktı şekli: {y_pred.shape}")
print(f"Tahminler: {y_pred}")

3. Modeli Eğitme

PyTorch'ta kayıp fonksiyonu ve optimizasyon algoritması oluşturma

Eğitim için bir kayıp fonksiyonu ve optimizasyon algoritması seçmemiz gerekir:

# Kayıp fonksiyonu - Ortalama Kare Hata (MSE)
loss_fn = nn.MSELoss()

# Optimizasyon algoritması - Adam
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)

PyTorch'ta optimizasyon döngüsü oluşturma

Temel bir eğitim döngüsü şu adımlardan oluşur:

  • Veriyi ileriye doğru geçirme (Forward pass)
  • Kaybı hesaplama
  • Gradyanları sıfırlama
  • Geri yayılım (Backpropagation)
  • Parametreleri güncelleme
# Örnek bir eğitim adımı
def training_step(model, X_batch, y_batch, loss_fn, optimizer):
    # 1. İleriye doğru geçiş
    y_pred = model(X_batch)
    
    # 2. Kaybı hesaplama
    loss = loss_fn(y_pred, y_batch)
    
    # 3. Gradyanları sıfırlama
    optimizer.zero_grad()
    
    # 4. Geri yayılım
    loss.backward()
    
    # 5. Parametreleri güncelleme
    optimizer.step()
    
    return loss.item()

PyTorch eğitim döngüsü

Tam bir eğitim döngüsü şu şekildedir:

def train(model, train_loader, loss_fn, optimizer, epochs=100):
    # Eğitim moduna geç
    model.train()
    train_losses = []
    
    for epoch in range(epochs):
        epoch_loss = 0
        for X_batch, y_batch in train_loader:
            # Eğitim adımını gerçekleştir
            batch_loss = training_step(model, X_batch, y_batch, loss_fn, optimizer)
            epoch_loss += batch_loss
        
        # Epoch başına ortalama kaybı hesapla
        epoch_loss /= len(train_loader)
        train_losses.append(epoch_loss)
        
        # Her 10 epochta ilerlemeyi göster
        if (epoch + 1) % 10 == 0:
            print(f"Epoch {epoch+1}/{epochs}, Kayıp: {epoch_loss:.4f}")
    
    return train_losses

PyTorch test döngüsü

Test döngüsü, eğitim döngüsüne benzer, ancak gradyan hesaplamalarını yapmaz:

def test(model, test_loader, loss_fn):
    # Değerlendirme moduna geç
    model.eval()
    test_loss = 0
    
    # Gradyan hesaplamalarını devre dışı bırak
    with torch.inference_mode():
        for X_batch, y_batch in test_loader:
            # Tahmin yap
            y_pred = model(X_batch)
            
            # Batch kaybını hesapla ve toplam kayba ekle
            batch_loss = loss_fn(y_pred, y_batch).item()
            test_loss += batch_loss
    
    # Ortalama test kaybını hesapla
    test_loss /= len(test_loader)
    
    return test_loss

4. Eğitilmiş bir PyTorch modeli ile tahmin yapma

Model eğitildikten sonra, yeni veriler üzerinde tahmin yapmak oldukça basittir:

def make_predictions(model, data):
    # Değerlendirme moduna geç
    model.eval()
    
    # Gradyan hesaplamalarını devre dışı bırak
    with torch.inference_mode():
        predictions = model(data)
    
    return predictions

# Örnek tahmin yapalım
sample_data = torch.rand(10, 3)  # 10 örnek, her biri 3 özelliğe sahip
predictions = make_predictions(model, sample_data)
print(f"Tahminler: {predictions[:5]}")  # İlk 5 tahmini göster

5. PyTorch modelini kaydetme ve yükleme

PyTorch modelini kaydetme

PyTorch'ta modelleri kaydetmenin iki yolu vardır:

  • Tüm modeli kaydetme
  • Sadece model parametrelerini (state_dict) kaydetme
# Tüm modeli kaydetme
MODEL_PATH = "regression_model.pth"
torch.save(model, MODEL_PATH)
print(f"Tüm model şuraya kaydedildi: {MODEL_PATH}")

# Sadece model durumunu (state_dict) kaydetme (önerilen yöntem)
MODEL_STATE_PATH = "regression_model_state.pth"
torch.save(model.state_dict(), MODEL_STATE_PATH)
print(f"Model durumu şuraya kaydedildi: {MODEL_STATE_PATH}")

Kaydedilmiş bir PyTorch modelini yükleme

# Tüm modeli yükleme
loaded_model = torch.load(MODEL_PATH)
print(f"Yüklenen model: {loaded_model}")

# State dict kullanarak model yükleme (önerilen yöntem)
loaded_state_dict_model = LinearRegressionModel(input_features=3, output_features=1)
loaded_state_dict_model.load_state_dict(torch.load(MODEL_STATE_PATH))
print(f"State dict ile yüklenen model: {loaded_state_dict_model}")

6. Hepsini bir araya getirme

Şimdi, öğrendiğimiz tüm adımları birleştirerek gerçek bir regresyon problemi çözelim.

6.1 Veri

# Gerçek bir regresyon problemi için veri oluşturma
torch.manual_seed(42)
X = torch.rand(1000, 5) * 10  # 5 özelliğe sahip 1000 örnek
y = (X[:, 0] * 2) + (X[:, 1] * 1.5) + (X[:, 2] * 0.5) - (X[:, 3] * 1) + (X[:, 4] * 0.25) + torch.randn(1000) * 2

# Veriyi eğitim ve test setlerine ayırma
train_size = int(0.8 * len(X))
X_train, X_test = X[:train_size], X[train_size:]
y_train, y_test = y[:train_size], y[train_size:]

# PyTorch dataset ve dataloader oluşturma
train_dataset = torch.utils.data.TensorDataset(X_train, y_train.unsqueeze(1))
test_dataset = torch.utils.data.TensorDataset(X_test, y_test.unsqueeze(1))

train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=32, shuffle=True)
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=32)

6.2 PyTorch doğrusal model oluşturma

# Doğrusal regresyon modeli tanımlama
class MultivariateLinearRegression(nn.Module):
    def __init__(self, input_features):
        super().__init__()
        self.linear = nn.Linear(input_features, 1)
    
    def forward(self, x):
        return self.linear(x)

# Modeli oluşturma
model = MultivariateLinearRegression(input_features=5)
print(f"Model mimarisi: {model}")

# Eğitim için kayıp fonksiyonu ve optimizasyon algoritması
loss_fn = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

6.3 Eğitim

# Modeli eğitme
epochs = 100
train_losses = []
test_losses = []

for epoch in range(epochs):
    # Eğitim modu
    model.train()
    train_loss = 0
    
    for X_batch, y_batch in train_loader:
        # İleriye doğru geçiş
        y_pred = model(X_batch)
        
        # Kaybı hesaplama
        loss = loss_fn(y_pred, y_batch)
        
        # Gradyanları sıfırlama
        optimizer.zero_grad()
        
        # Geri yayılım ve optimizasyon
        loss.backward()
        optimizer.step()
        
        train_loss += loss.item()
    
    # Epoch başına ortalama eğitim kaybı
    train_loss /= len(train_loader)
    train_losses.append(train_loss)
    
    # Test modunda değerlendirme
    model.eval()
    test_loss = 0
    
    with torch.inference_mode():
        for X_batch, y_batch in test_loader:
            y_pred = model(X_batch)
            test_loss += loss_fn(y_pred, y_batch).item()
    
    # Ortalama test kaybı
    test_loss /= len(test_loader)
    test_losses.append(test_loss)
    
    # Her 10 epochta ilerlemeyi göster
    if (epoch + 1) % 10 == 0:
        print(f"Epoch {epoch+1}/{epochs}, Eğitim Kaybı: {train_loss:.4f}, Test Kaybı: {test_loss:.4f}")

# Eğitim sonuçlarını görselleştirme (matplotlib ile)
import matplotlib.pyplot as plt

plt.figure(figsize=(10, 6))
plt.plot(train_losses, label="Eğitim Kaybı")
plt.plot(test_losses, label="Test Kaybı")
plt.xlabel("Epoch")
plt.ylabel("MSE Kaybı")
plt.title("Eğitim ve Test Kayıpları")
plt.legend()
plt.show()

6.4 Tahmin yapma

# Test veri seti üzerinde tahminler yapma
model.eval()
with torch.inference_mode():
    test_predictions = model(X_test)

# Gerçek değerler ve tahminleri karşılaştırma
plt.figure(figsize=(12, 6))
plt.scatter(y_test.numpy(), test_predictions.squeeze().numpy(), alpha=0.5)
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], "--r")
plt.xlabel("Gerçek Değerler")
plt.ylabel("Tahmin Edilen Değerler")
plt.title("Gerçek vs Tahmin Edilen Değerler")
plt.show()

# Modelin ağırlıklarına bakalım
print("Model ağırlıkları:")
for name, param in model.named_parameters():
    if "weight" in name:
        print(f"{name}: {param.data.numpy().flatten()}")

6.5 Model kaydetme ve yükleme

# Modeli kaydetme
MODEL_PATH = "multivariate_regression_model.pth"
torch.save(model.state_dict(), MODEL_PATH)
print(f"Model başarıyla kaydedildi: {MODEL_PATH}")

# Modeli yükleme ve doğrulama
loaded_model = MultivariateLinearRegression(input_features=5)
loaded_model.load_state_dict(torch.load(MODEL_PATH))
loaded_model.eval()

# Yüklenen modelle tahmin yapma
with torch.inference_mode():
    loaded_model_preds = loaded_model(X_test)

# İki model arasındaki farkı kontrol etme
print(f"Orijinal ve yüklenen model tahminleri arasındaki fark: {torch.sum(torch.abs(test_predictions - loaded_model_preds))}")

PyTorch iş akışının tüm önemli bileşenlerini inceledik - veri hazırlamadan model kaydetmeye kadar. Bu yazıda sunulan yapı, basit regresyon problemlerinden karmaşık derin öğrenme uygulamalarına kadar herhangi bir PyTorch projesinin temelini oluşturur. İşte öğrendiklerimizin kısa bir özeti:

  • Veri, her derin öğrenme projesinin temelidir. PyTorch'un Dataset ve DataLoader sınıfları, veri manipülasyonu ve batch işleme için esnek araçlar sağlar. Verinizi doğru bir şekilde eğitim ve test setlerine ayırmak, modelinizin genelleme yeteneğini değerlendirmek için kritik öneme sahiptir.

  • Model oluşturma, nn.Module sınıfını miras alan özel sınıflar tanımlayarak kolayca gerçekleştirilebilir. forward() metodunu tanımlayarak modelin davranışını belirlersiniz, ve PyTorch otomatik olarak geri yayılım için gerekli hesaplamaları yönetir.

  • Eğitim süreci, ileriye doğru geçiş, kayıp hesaplama, gradyanları sıfırlama, geri yayılım ve parametre güncelleme adımlarını içerir. Bu temel döngü, neredeyse tüm derin öğrenme modellerinde aynıdır ve PyTorch ile bu adımları açık ve anlaşılır bir şekilde uygulayabilirsiniz.

  • Modelinizi eğittikten sonra, tahminler yapmak için torch.inference_mode() ile değerlendirme moduna geçebilirsiniz. Bu mod, gradyan hesaplamalarını devre dışı bırakarak çıkarım işlemlerini hızlandırır ve bellek kullanımını optimize eder.

  • Model kaydetme ve yükleme, PyTorch'ta son derece basittir. Tüm modeli veya sadece durum sözlüğünü (state dictionary) kaydedebilirsiniz. İkinci yaklaşım daha esnektir ve farklı model mimarilerine geçiş yaparken parametre transferine olanak tanır.

Bu temel prensipleri kavramak, derin öğrenme dünyasında başarılı olmanız için gerekli temelinizi oluşturur. PyTorch'un güzelliği, bu temel yapı taşlarını alıp onları ihtiyaçlarınıza göre özelleştirebilmenizdir. Resim sınıflandırmadan doğal dil işlemeye, nesne tespitinden üretici modellere kadar - tüm bu karmaşık uygulamalar, bu yazıda öğrendiğiniz temel iş akışı üzerine inşa edilir.

Unutmayın ki derin öğrenme, deneme-yanılma ve sürekli iyileştirme gerektirir. İlk modeliniz mükemmel olmayabilir, ve bu normaldir. Performansı artırmak için hiperparametreleri ayarlamak, mimariyi değiştirmek veya veri ön işleme stratejinizi geliştirmek gerekebilir. PyTorch'un esnek doğası, bu deneysel yaklaşıma mükemmel bir şekilde uyum sağlar.

Sonraki yazılarımızda, bu temel iş akışını daha karmaşık model mimarileri, özel kayıp fonksiyonları, gelişmiş optimizasyon teknikleri ve daha fazlasıyla genişleteceğiz. Şimdilik, bu yazıdaki örnekleri deneyimleyin, kendi küçük projelerinizle denemeler yapın ve PyTorch'un sunduğu olasılıkları keşfedin.

PyTorch dünyasında yolculuğunuz, bu temel iş akışını anlamakla başlar. Bu bilgilerle donanmış olarak, artık daha karmaşık derin öğrenme uygulamalarına güvenle geçiş yapabilirsiniz. Kodlamaya devam edin, deneyimleyin ve öğrenmeye devam edin!

Bir sonraki yazımızda görüşmek üzere!


Not: Bu yazı, önceki "PyTorch Tensörleri A'dan Z'ye Geliştiriciler İçin Temel Kılavuz?" yazısının devamı niteliğindedir. PyTorch'un temel kavramlarını anlamak için ilk yazıyı da okumanızı öneririm.