
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.