Takip et

PyTorch’a Giriş: El Yazısı Rakamları Tanıyan Bir Yapay Sinir Ağı İnşa Etmek

PyTorch’a Giriş: El Yazısı Rakamları Tanıyan Bir Yapay Sinir Ağı İnşa Etmek Giriş Günümüzün hızla dijitalleşen dünyasında, yapay

PyTorch’a Giriş: El Yazısı Rakamları Tanıyan Bir Yapay Sinir Ağı İnşa Etmek

Giriş

Günümüzün hızla dijitalleşen dünyasında, yapay zeka (YZ) ve onun alt dalları olan makine öğrenimi (ML) ve derin öğrenme (DL), hayatımızın birçok alanında devrim niteliğinde değişiklikler yaratmaktadır. Görüntü tanıma, doğal dil işleme, otonom araçlar ve kişiselleştirilmiş öneri sistemleri gibi uygulamalar, derin öğrenmenin gücüyle mümkün hale gelmiştir. Derin öğrenme, insan beyninin çalışma prensiplerinden esinlenerek tasarlanmış yapay sinir ağlarını (YSA) kullanarak karmaşık veri desenlerini öğrenme yeteneğine sahiptir.

Bu alanda geliştirilen birçok güçlü kütüphane arasında PyTorch, esnekliği, Pythonic yapısı ve dinamik hesaplama grafikleri sayesinde araştırmacılar ve geliştiriciler arasında popülerliğini giderek artırmaktadır. Facebook AI tarafından geliştirilen PyTorch, özellikle prototipleme ve araştırmadan üretime geçiş süreçlerinde sunduğu kolaylıklarla öne çıkar.

Bu makalenin amacı, PyTorch’u kullanarak el yazısı rakamlarını tanıyabilen basit bir yapay sinir ağı inşa etme sürecini adım adım açıklamaktır. Bu yolculukta, derin öğrenmenin temel kavramlarını PyTorch’un pratik uygulamalarıyla birleştirerek, okuyucunun hem teorik bilgi edinmesini hem de kendi derin öğrenme modellerini oluşturma becerisi kazanmasını sağlamayı hedefliyoruz. MNIST veri kümesi, derin öğrenme dünyasının “Merhaba Dünya” örneği olarak kabul edilir ve bu alana yeni başlayanlar için mükemmel bir başlangıç noktası sunar. Makale boyunca PyTorch’un temel bileşenlerini, veri hazırlığını, model mimarisini, eğitim sürecini ve model değerlendirmesini detaylı bir şekilde inceleyeceğiz.

PyTorch Nedir?

PyTorch, açık kaynaklı bir makine öğrenimi kütüphanesi olup, özellikle derin öğrenme uygulamaları için tasarlanmıştır. NumPy’ye benzer bir yapıya sahip tensor hesaplamaları sunarken, aynı zamanda GPU hızlandırmasını da destekler. Bu, büyük veri kümeleri ve karmaşık modellerle çalışırken performansı önemli ölçüde artırır. PyTorch’un temel özelliklerini ve bileşenlerini aşağıda inceleyelim:

Tensor’lar: PyTorch’un Temel Yapı Taşı

PyTorch’taki en temel veri yapısı torch.Tensor‘dır. Tensor’lar, çok boyutlu dizilerdir ve NumPy dizilerine benzerler, ancak GPU üzerinde çalışabilme yetenekleri sayesinde derin öğrenme operasyonları için çok daha verimlidirler. Tensor’lar, modelin giriş verilerini, çıktılarını, ağırlıklarını ve gradyanlarını temsil etmek için kullanılır.

Bir tensor oluşturmak oldukça basittir:

import torch

Skaler (0 boyutlu tensor)

x = torch.tensor(42)

Vektör (1 boyutlu tensor)

y = torch.tensor([1, 2, 3])

Matris (2 boyutlu tensor)

z = torch.tensor([[1, 2], [3, 4]])

Boyutları ve veri tipini kontrol etme

print(x.shape, x.dtype) # torch.Size([]) torch.int64 print(y.shape, y.dtype) # torch.Size([3]) torch.int64 print(z.shape, z.dtype) # torch.Size([2, 2]) torch.int64

Tensor’lar farklı veri tiplerini (float, int, bool vb.) destekler ve CPU ile GPU arasında kolayca taşınabilirler (.to('cuda') veya .to('cpu')).

Otomatik Türevleme (Autograd): Geri Yayılımın Kolay Yolu

Derin öğrenmede, modelin ağırlıklarını optimize etmek için kayıp fonksiyonunun parametrelere göre gradyanlarını (türevlerini) hesaplamamız gerekir. Bu süreç, geri yayılım (backpropagation) olarak bilinir ve manuel olarak yapmak oldukça karmaşık ve hataya açık olabilir. PyTorch’un torch.autograd modülü, bu süreci otomatikleştirir.

Bir tensor üzerinde requires_grad=True olarak ayarlandığında, PyTorch bu tensor üzerinde yapılan tüm operasyonları izlemeye başlar. Bir hesaplama tamamlandığında ve loss.backward() çağrıldığında, PyTorch hesaplama grafiğini geriye doğru izleyerek tüm ilgili tensor’lar için gradyanları otomatik olarak hesaplar ve bunları .grad özniteliğinde saklar.

x = torch.tensor(2.0, requires_grad=True)
y = x2
z = y + 3
loss = z.sum()

loss.backward() # Gradyanları hesapla
print(x.grad) # Çıktı: tensor(4.) (z = x^2 + 3, dz/dx = 2x, x=2 için 4)

Bu mekanizma, model eğitiminde kritik bir rol oynar ve geliştiricilerin gradyan hesaplama karmaşıklığıyla uğraşmak yerine model mimarisine odaklanmasını sağlar.

Modüller (torch.nn): Yapay Sinir Ağlarının Yapı Taşları

torch.nn modülü, yapay sinir ağları oluşturmak için gerekli tüm yapı taşlarını (katmanlar, aktivasyon fonksiyonları, kayıp fonksiyonları vb.) sağlar. Bir derin öğrenme modeli, genellikle nn.Module sınıfından türetilerek tanımlanır. Bu sınıf, modelin katmanlarını tanımlayacağımız __init__ metodunu ve verinin ağ üzerinden nasıl akacağını belirleyeceğimiz forward metodunu içerir.

* Katmanlar: nn.Linear (tam bağlantılı katman), nn.Conv2d (evrişimsel katman), nn.MaxPool2d (maksimum havuzlama katmanı) gibi birçok farklı katman tipi bulunur.
* Aktivasyon Fonksiyonları: nn.ReLU, nn.Sigmoid, nn.Tanh, nn.Softmax gibi non-lineer aktivasyon fonksiyonları, ağın karmaşık ilişkileri öğrenmesini sağlar.
* Kayıp Fonksiyonları: nn.CrossEntropyLoss (sınıflandırma için), nn.MSELoss (regresyon için) gibi kayıp fonksiyonları, modelin tahminleri ile gerçek etiketler arasındaki farkı ölçer.

Optimizatörler (torch.optim): Model Parametrelerini Güncelleme

torch.optim modülü, modelin öğrenme sürecinde ağırlıklarını ve bias’larını güncellemek için kullanılan optimizasyon algoritmalarını içerir. En yaygın optimizatörler arasında optim.SGD (Stokastik Gradyan İnişi), optim.Adam, optim.Adagrad ve optim.RMSprop bulunur. Bir optimizatör, modelin parametrelerini ve bir öğrenme oranını alır. Eğitim döngüsünde, gradyanlar hesaplandıktan sonra optimizer.step() çağrısı ile parametreler güncellenir.

Bu temel bileşenler, PyTorch’u derin öğrenme modelleri oluşturmak için son derece güçlü ve esnek bir araç haline getirir. Şimdi bu bileşenleri kullanarak el yazısı rakamlarını tanıma problemine odaklanalım.

MNIST Veri Kümesi

MNIST (Modified National Institute of Standards and Technology) veri kümesi, derin öğrenme ve görüntü sınıflandırma alanında en yaygın kullanılan veri kümelerinden biridir. Genellikle “derin öğrenmenin Merhaba Dünya’sı” olarak anılır ve yeni algoritmaları test etmek veya derin öğrenmeye başlamak için ideal bir başlangıç noktası sunar.

Veri Kümesinin Yapısı

MNIST, 0’dan 9’a kadar olan el yazısı rakamlarının gri tonlamalı görüntülerinden oluşur.
* Görüntü Boyutu: Her görüntü 28×28 piksel boyutundadır. Bu, toplamda 784 piksel anlamına gelir.
* Piksel Değerleri: Piksel değerleri 0 ile 255 arasında değişir; 0 siyahı, 255 beyazı temsil eder.
* Eğitim Seti: 60.000 görüntü içerir ve modelin öğrenmesi için kullanılır.
* Test Seti: 10.000 görüntü içerir ve modelin eğitilmemiş veriler üzerindeki performansını değerlendirmek için kullanılır.
* Etiketler: Her görüntü, temsil ettiği rakamı (0-9) belirten bir etiketle birlikte gelir.

MNIST’i Yükleme ve Ön İşleme

PyTorch’un torchvision kütüphanesi, popüler veri kümelerine (MNIST, CIFAR10 vb.) erişimi ve görüntü dönüşümlerini kolaylaştırır. MNIST veri kümesini yüklemek ve derin öğrenme modeline uygun hale getirmek için aşağıdaki adımları izleriz:

1. Dönüşümler (Transforms): Görüntüleri PyTorch tensor’larına dönüştürmek ve normalleştirmek gerekir. Normalizasyon, piksel değerlerini belirli bir aralığa (genellikle 0-1 veya -1-1) ölçekleyerek modelin daha iyi öğrenmesine yardımcı olur. MNIST için genellikle [0, 1] aralığına ölçekleme ve ardından ortalama 0, standart sapma 1 olacak şekilde standartlaştırma yapılır.
2. Veri Kümeleri (Datasets): torchvision.datasets.MNIST sınıfı, veri kümesini indirir ve yükler.
3. Veri Yükleyiciler (DataLoaders): torch.utils.data.DataLoader, veri kümesini küçük gruplara (batch’ler) ayırarak modelin eğitim sürecini daha verimli hale getirir. Ayrıca verileri karıştırma (shuffling) ve çoklu işlem (multi-processing) ile yükleme gibi özellikler sunar.

import torch
from torchvision import datasets, transforms
from torch.utils.data import DataLoader

Cihaz ayarı (GPU varsa 'cuda', yoksa 'cpu')

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

Veri ön işleme dönüşümleri

ToTensor(): PIL Image veya NumPy dizisini [0, 1] aralığında bir Tensor'a dönüştürür.

Normalize(): Tensor'ı belirli bir ortalama ve standart sapma ile standartlaştırır.

MNIST için ortalama ve std değerleri önceden hesaplanmıştır.

transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,)) # MNIST'in ortalama ve std değerleri ])

Eğitim ve test veri kümelerini indirme ve yükleme

train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform) test_dataset = datasets.MNIST(root='./data', train=False, download=True, transform=transform)

Veri yükleyicileri oluşturma

batch_size = 64 train_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True) test_loader = DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False)

Bir örnek batch'i inceleyelim

images, labels = next(iter(train_loader)) print(f"Batch boyutu: {images.shape}") # torch.Size([64, 1, 28, 28]) (batch_size, kanal, yükseklik, genişlik) print(f"Etiketler: {labels.shape}") # torch.Size([64])

Burada images.shape çıktısı [64, 1, 28, 28] şeklindedir. Bu, 64 görüntülük bir batch, her görüntü 1 kanal (gri tonlamalı) ve 28×28 piksel boyutunda demektir.

Yapay Sinir Ağı Mimarisi

El yazısı rakamlarını tanımak için kullanacağımız yapay sinir ağı, temel bir Çok Katmanlı Algılayıcı (Multi-Layer Perceptron – MLP) veya diğer adıyla Tam Bağlantılı Ağ (Fully Connected Network) olacaktır. Bu tür bir ağ, derin öğrenmeye başlamak için iyi bir temel sağlar.

Temel Kavramlar

* Giriş Katmanı: Modelin girdi verisini aldığı katmandır. MNIST için 28×28=784 pikselden oluşan düzleştirilmiş görüntü vektörleri bu katmana girer.
* Gizli Katmanlar: Giriş ve çıkış katmanları arasında yer alan katmanlardır. Bu katmanlarda, ağın karmaşık desenleri ve ilişkileri öğrenmesini sağlayan hesaplamalar yapılır. Her gizli katman, bir dizi nöron içerir.
* Çıkış Katmanı: Modelin nihai tahminlerini ürettiği katmandır. MNIST gibi 10 farklı rakamı sınıflandırma probleminde, bu katman 10 nöron içerir (her rakam için bir tane).
* Nöronlar: Bir yapay sinir ağının temel işlem birimidir. Gelen girdileri alır, ağırlıklarla çarpar, bias ekler ve bir aktivasyon fonksiyonundan geçirerek bir çıktı üretir.
* Ağırlıklar (Weights) ve Bias’lar: Ağın öğrenilebilir parametreleridir. Ağırlıklar, girdilerin önemini belirlerken, bias’lar bir nöronun aktivasyon eşiğini ayarlar.
* Aktivasyon Fonksiyonları: Bir nöronun çıktısını doğrusal olmayan hale getiren fonksiyonlardır. Bu non-lineerlik, ağın daha karmaşık fonksiyonları modellemesini sağlar. ReLU (Rectified Linear Unit) ve Sigmoid en yaygın kullanılanlardandır. Sınıflandırma problemlerinde çıkış katmanında genellikle Softmax kullanılır.

Modelin PyTorch’ta Tanımlanması

PyTorch’ta bir yapay sinir ağı, nn.Module sınıfından türetilerek oluşturulur. Bu sınıfı miras alan her modelin iki ana metodu olmalıdır:

1. __init__(self): Bu metodda, ağın katmanları (lineer katmanlar, evrişimsel katmanlar vb.) ve diğer modüller tanımlanır.
2. forward(self, x): Bu metodda, girdi x‘in ağ üzerinden nasıl geçirileceği, yani katmanların ve aktivasyon fonksiyonlarının sırası tanımlanır. Bu metod, model çağrıldığında otomatik olarak çalışır.

MNIST için basit bir MLP modeli tanımlayalım. Görüntüler 28×28=784 piksel olduğundan, giriş katmanımız 784 nöron alacaktır. Çıkış katmanımız ise 10 farklı rakam sınıfı olduğu için 10 nöronlu olacaktır. Arada bir veya iki gizli katman kullanabiliriz.

import torch.nn as nn
import torch.nn.functional as F

Yapay Sinir Ağı modelimizi tanımlıyoruz

class NeuralNetwork(nn.Module): def __init__(self): super(NeuralNetwork, self).__init__() # Giriş katmanı (784 piksel) -> Gizli katman 1 (128 nöron) self.fc1 = nn.Linear(28 * 28, 128) # Gizli katman 1 (128 nöron) -> Gizli katman 2 (64 nöron) self.fc2 = nn.Linear(128, 64) # Gizli katman 2 (64 nöron) -> Çıkış katmanı (10 nöron - 0'dan 9'a kadar rakamlar) self.fc3 = nn.Linear(64, 10) def forward(self, x): # Görüntüleri düzleştirme (flatten) # Giriş boyutu: [batch_size, 1, 28, 28] -> [batch_size, 784] x = x.view(-1, 28 * 28) # -1, batch boyutunun otomatik olarak belirlenmesini sağlar # Gizli katman 1 ve ReLU aktivasyonu x = F.relu(self.fc1(x)) # Gizli katman 2 ve ReLU aktivasyonu x = F.relu(self.fc2(x)) # Çıkış katmanı (aktivasyon fonksiyonu yok, CrossEntropyLoss içinde Softmax uygulanır) x = self.fc3(x) return x

Modeli oluştur ve cihaza taşı

model = NeuralNetwork().to(device) print(model)

Yukarıdaki modelde, F.relu fonksiyonel API’den çağrılır. Alternatif olarak, nn.ReLU() modülünü de __init__ içinde tanımlayıp forward içinde çağırabilirdik. nn.Linear katmanları, giriş ve çıkış boyutlarını otomatik olarak yönetir. x.view(-1, 28 * 28) işlemi, 28×28 boyutundaki 2 boyutlu görüntü verisini 784 boyutlu 1 boyutlu bir vektöre dönüştürerek tam bağlantılı katmanlara uygun hale getirir.

Eğitim Süreci

Bir yapay sinir ağının eğitimi, modelin veri kümesindeki desenleri öğrenerek tahmin yeteneğini geliştirmesi sürecidir. Bu süreç, bir dizi temel adımdan oluşur: kayıp fonksiyonunun belirlenmesi, optimizatörün seçilmesi ve eğitim döngüsünün çalıştırılması.

Kayıp Fonksiyonu (Loss Function)

Kayıp fonksiyonu (veya maliyet fonksiyonu), modelin tahminleri ile gerçek etiketler arasındaki farkı ölçer. Bu fark ne kadar küçükse, modelin performansı o kadar iyidir. Sınıflandırma problemleri için yaygın olarak kullanılan kayıp fonksiyonu nn.CrossEntropyLoss‘tur. Bu fonksiyon, Softmax aktivasyonunu ve Negatif Log Olabilirlik Kaybını (Negative Log Likelihood Loss) birleştirir, bu da onu çok sınıflı sınıflandırma görevleri için oldukça uygun hale getirir. Modelin çıkış katmanında Softmax uygulamadan doğrudan bu kayıp fonksiyonunu kullanabiliriz, çünkü nn.CrossEntropyLoss bunu dahili olarak halleder.

criterion = nn.CrossEntropyLoss()

Optimizatör (Optimizer)

Optimizatör, kayıp fonksiyonunu minimize etmek için modelin öğrenilebilir parametrelerini (ağırlıklar ve bias’lar) nasıl güncelleyeceğini belirleyen algoritmadır. En popüler optimizatörlerden bazıları SGD (Stokastik Gradyan İnişi), Adam ve RMSprop’tur. Adam optimizatörü, genellikle iyi bir başlangıç noktasıdır çünkü dinamik öğrenme oranı ayarlaması yapar ve çoğu durumda SGD’den daha hızlı yakınsar.

Optimizatör, modelin parametrelerini (model.parameters()) ve bir öğrenme oranını (learning rate – lr) alır. Öğrenme oranı, her güncellemede parametrelerin ne kadar değiştirileceğini kontrol eden kritik bir hiperparametredir.

learning_rate = 0.001
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)

Eğitim Döngüsü (Training Loop)

Eğitim döngüsü, modelin veri kümesi üzerinde birden fazla kez (epoch) eğitildiği süreçtir. Her epoch, tüm eğitim veri kümesinin modelden bir kez geçirilmesi anlamına gelir. Her epoch içinde, veri kümesi küçük batch’lere ayrılır ve her batch için aşağıdaki adımlar uygulanır:

1. Gradyanları Sıfırlama (optimizer.zero_grad()): PyTorch, gradyanları varsayılan olarak biriktirir. Her yeni batch için önceki batch’ten kalan gradyanların temizlenmesi gerekir, aksi takdirde yanlış güncellemeler yapılır.
2. İleri Yayılım (Forward Pass): Giriş verisi (görüntüler) modele beslenir ve model tahminler (outputs) üretir.
3. Kayıp Hesaplama (Loss Calculation): Modelin tahminleri ile gerçek etiketler (labels) arasındaki fark, kayıp fonksiyonu kullanılarak hesaplanır.
4. Geri Yayılım (Backward Pass): Hesaplanan kayıp, ağ boyunca geriye doğru yayılır ve her öğrenilebilir parametre için gradyanlar (.grad) hesaplanır. Bu işlem loss.backward() ile yapılır.
5. Parametreleri Güncelleme (optimizer.step()): Optimizatör, hesaplanan gradyanları kullanarak modelin ağırlıklarını ve bias’larını günceller.

num_epochs = 5 # Eğitim epoch sayısı

for epoch in range(num_epochs):
    for i, (images, labels) in enumerate(train_loader):
        # Veriyi cihaza taşı
        images = images.to(device)
        labels = labels.to(device)

        # İleri yayılım
        outputs = model(images)
        loss = criterion(outputs, labels)

        # Geri yayılım ve optimizasyon
        optimizer.zero_grad() # Gradyanları sıfırla
        loss.backward()       # Geri yayılım
        optimizer.step()      # Parametreleri güncelle

        if (i+1) % 100 == 0:
            print(f'Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{len(train_loader)}], Loss: {loss.item():.4f}')

Bu döngü, modelin her epoch’ta tüm eğitim verisi üzerinde öğrenmesini ve parametrelerini iyileştirmesini sağlar. loss.item() kullanılarak kayıp değeri Python skalerine dönüştürülür ve yazdırılır.

Modelin Değerlendirilmesi

Model eğitildikten sonra, ne kadar iyi performans gösterdiğini değerlendirmemiz gerekir. Bu değerlendirme, modelin eğitim sırasında görmediği test veri kümesi üzerinde yapılır. Bu, modelin genelleme yeteneğini ölçmek için kritik öneme sahiptir.

Değerlendirme süreci, eğitim döngüsüne benzer ancak birkaç önemli farkla:
1. Gradyan Hesaplamasını Devre Dışı Bırakma: Test aşamasında modelin parametrelerini güncellememiz gerekmediği için gradyan hesaplamasına ihtiyacımız yoktur. torch.no_grad() bağlam yöneticisi kullanılarak bu işlem devre dışı bırakılır, bu da bellek kullanımını azaltır ve hesaplamaları hızlandırır.
2. Doğruluk (Accuracy) Metriği: Sınıflandırma problemlerinde en yaygın değerlendirme metriği doğruluktur (accuracy). Bu, doğru tahmin edilen örneklerin toplam örnek sayısına oranıdır.

# Modeli değerlendirme moduna al

Dropout ve Batch Normalization gibi katmanların davranışını test moduna göre ayarlar

model.eval() with torch.no_grad(): # Gradyan hesaplamasını devre dışı bırak correct = 0 total = 0 for images, labels in test_loader: images = images.to(device) labels = labels.to(device) outputs = model(images) _, predicted = torch.max(outputs.data, 1) # En yüksek olasılığa sahip sınıfı bul total += labels.size(0) correct += (predicted == labels).sum().item() print(f'Test veri kümesinde modelin doğruluğu: {100 * correct / total:.2f}%')

Eğitimi bitirdikten sonra modeli tekrar eğitim moduna alabiliriz

model.train()

torch.max(outputs.data, 1) fonksiyonu, modelin her bir görüntü için ürettiği 10 olasılık değerinden (logit) en yüksek olanın indeksini (yani tahmin edilen sınıfı) bulur. _ değişkeni, maksimum değeri tutarken, predicted değişkeni maksimum değerin indeksini tutar. (predicted == labels).sum().item() ise doğru tahmin edilen örneklerin sayısını verir.

Pratik Uygulama Kodu

Şimdiye kadar ele aldığımız tüm adımları bir araya getirerek, PyTorch ile el yazısı rakamlarını tanıyan bir yapay sinir ağı oluşturan eksiksiz bir Python kodu örneğini sunalım.

import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import datasets, transforms
from torch.utils.data import DataLoader

1. Cihaz Ayarı

GPU (cuda) varsa kullan, yoksa CPU kullan

device = torch.device("cuda" if torch.cuda.is_available() else "cpu") print(f"Kullanılan cihaz: {device}")

2. Hiperparametreler

num_epochs = 10 # Eğitim döngüsü sayısı batch_size = 128 # Her bir eğitim adımında kullanılacak örnek sayısı learning_rate = 0.001 # Optimizatörün öğrenme oranı

3. Veri Ön İşleme ve Yükleme

MNIST için dönüşümler: Tensor'a çevir ve normalleştir

transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,)) # MNIST'in ortalama ve std değerleri ])

Eğitim ve test veri kümelerini indirme ve yükleme

train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform) test_dataset = datasets.MNIST(root='./data', train=False, download=True, transform=transform)

Veri yükleyicileri oluşturma

train_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True) test_loader = DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False)

4. Yapay Sinir Ağı Modelinin Tanımlanması

class NeuralNetwork(nn.Module): def __init__(self): super(NeuralNetwork, self).__init__() # Giriş katmanı (784 piksel) -> Gizli katman 1 (256 nöron) self.fc1 = nn.Linear(28 * 28, 256) # Gizli katman 1 (256 nöron) -> Gizli katman 2 (128 nöron) self.fc2 = nn.Linear(256, 128) # Gizli katman 2 (128 nöron) -> Gizli katman 3 (64 nöron) self.fc3 = nn.Linear(128, 64) # Gizli katman 3 (64 nöron) -> Çıkış katmanı (10 nöron) self.fc4 = nn.Linear(64, 10) # Dropout katmanı, aşırı öğrenmeyi (overfitting) azaltmak için kullanılır self.dropout = nn.Dropout(0.2) # %20 ihtimalle nöronları kapat def forward(self, x): # Görüntüleri düzleştirme: [batch_size, 1, 28, 28] -> [batch_size, 784] x = x.view(-1, 28 * 28) # Katmanlar ve aktivasyon fonksiyonları x = F.relu(self.fc1(x)) x = self.dropout(x) # Dropout uygulama x = F.relu(self.fc2(x)) x = self.dropout(x) x = F.relu(self.fc3(x)) x = self.dropout(x) x = self.fc4(x) # Çıkış katmanı, CrossEntropyLoss içinde Softmax uygulanacak return x

Modeli oluştur ve cihaza taşı

model = NeuralNetwork().to(device) print("\nModel Mimarisi:") print(model)

5. Kayıp Fonksiyonu ve Optimizatör

criterion = nn.CrossEntropyLoss() # Sınıflandırma için uygun kayıp fonksiyonu optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate) # Adam optimizatörü

6. Model Eğitimi

print("\nEğitim Başladı...") total_steps = len(train_loader) for epoch in range(num_epochs): for i, (images, labels) in enumerate(train_loader): # Veriyi cihaza taşı images = images.to(device) labels = labels.to(device) # İleri yayılım (Forward pass) outputs = model(images) loss = criterion(outputs, labels) # Geri yayılım (Backward pass) ve optimizasyon optimizer.zero_grad() # Önceki gradyanları sıfırla loss.backward() # Gradyanları hesapla optimizer.step() # Parametreleri güncelle if (i+1) % 100 == 0: print(f'Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{total_steps}], Loss: {loss.item():.4f}') print("Eğitim Tamamlandı.")

7. Modelin Değerlendirilmesi

print("\nModel Değerlendirme Başladı...") model.eval() # Modeli değerlendirme moduna al (dropout'ı devre dışı bırakır) with torch.no_grad(): # Gradyan hesaplamasını devre dışı bırak correct = 0 total = 0 for images, labels in test_loader: images = images.to(device) labels = labels.to(device) outputs = model(images) _, predicted = torch.max(outputs.data, 1) # En yüksek olasılığa sahip sınıfı bul total += labels.size(0) correct += (predicted == labels).sum().item() print(f'Test veri kümesindeki doğruluk: {100 * correct / total:.2f}%') print("Model Değerlendirme Tamamlandı.")

İsteğe bağlı: Modelin kaydedilmesi

torch.save(model.state_dict(), 'mnist_mlp_model.pth')

print("Model kaydedildi: mnist_mlp_model.pth")

Bu kod bloğu, PyTorch’un tüm temel bileşenlerini kullanarak MNIST veri kümesi üzerinde bir yapay sinir ağı eğitir ve değerlendirir. nn.Dropout katmanı, aşırı öğrenmeyi (overfitting) azaltmaya yardımcı olan önemli bir düzenlileştirme tekniğidir. Eğitim sırasında rastgele nöronları devre dışı bırakarak ağın belirli özelliklere aşırı bağımlı olmasını engeller.

İleri Seviye Konular ve Sonraki Adımlar

PyTorch ile el yazısı rakamlarını tanıma projesi, derin öğrenmeye sağlam bir giriş noktası sunar. Ancak bu sadece başlangıçtır. Derin öğrenme dünyasında keşfedilecek çok daha fazla konu ve uygulanacak teknik bulunmaktadır.

Evrişimsel Sinir Ağları (Convolutional Neural Networks – CNNs)

MNIST gibi görüntü verileriyle çalışırken, Evrişimsel Sinir Ağları (CNN’ler), Tam Bağlantılı Ağlardan (MLP’ler) genellikle daha üstün performans gösterir. CNN’ler, görüntülerin mekansal hiyerarşik özelliklerini (kenarlar, dokular, nesne parçaları) otomatik olarak öğrenmek üzere tasarlanmıştır. nn.Conv2d, nn.MaxPool2d gibi katmanlar kullanarak çok daha karmaşık ve başarılı görüntü tanıma modelleri oluşturabilirsiniz. MNIST üzerinde bir CNN uygulamak, modelin doğruluğunu önemli ölçüde artıracaktır.

Veri Artırma (Data Augmentation)

Derin öğrenme modelleri, büyük miktarda eğitim verisine ihtiyaç duyar. Veri artırma, mevcut eğitim verilerinden yeni, sentetik örnekler üreterek veri kümesinin boyutunu yapay olarak artırma tekniğidir. Görüntü verileri için döndürme, çevirme, ölçekleme, kırpma, parlaklık/kontrast ayarları gibi dönüşümler uygulanabilir. Bu, modelin farklı varyasyonlara karşı daha sağlam olmasını sağlar ve aşırı öğrenmeyi azaltmaya yardımcı olur. torchvision.transforms modülü, bu tür veri artırma işlemlerini kolayca uygulamanızı sağlar.

Hiperparametre Ayarı (Hyperparameter Tuning)

learning_rate, batch_size, gizli katman sayısı, nöron sayısı, optimizatör tipi gibi modelin eğitimini etkileyen parametrelere hiperparametre denir. Bu hiperparametrelerin doğru değerlerini bulmak, modelin performansını büyük ölçüde etkileyebilir. Izgara araması (Grid Search), rastgele arama (Random Search) veya Bayesian optimizasyon gibi teknikler kullanılarak en iyi hiperparametre kombinasyonu bulunmaya çalışılır.

Model Kaydetme ve Yükleme

Eğitilmiş bir modeli yeniden kullanmak veya dağıtmak için kaydetmek ve daha sonra yüklemek önemlidir. PyTorch’ta modelin durum sözlüğünü (model.state_dict()) kaydetmek ve yüklemek en yaygın yöntemdir.

# Modeli kaydetme
torch.save(model.state_dict(), 'model_weights.pth')

Modeli yükleme

Önce model mimarisini oluşturmanız gerekir

loaded_model = NeuralNetwork().to(device) loaded_model.load_state_dict(torch.load('model_weights.pth')) loaded_model.eval() # Değerlendirme için

Transfer Öğrenme (Transfer Learning)

Transfer öğrenme, bir problem üzerinde eğitilmiş bir modelin öğrenilmiş özelliklerini başka bir benzer problemde kullanma tekniğidir. Özellikle veri kümeniz küçükse veya modelinizi sıfırdan eğitmek çok maliyetliyse faydalıdır. Örneğin, ImageNet gibi büyük bir veri kümesi üzerinde eğitilmiş önceden eğitilmiş bir CNN modelini alıp, son katmanlarını kendi özel sınıflandırma görevinize uyarlayabilirsiniz. PyTorch’un torchvision.models modülü, birçok önceden eğitilmiş model sunar.

Gerçek Dünya Uygulamaları

PyTorch ile öğrendiğiniz bu temel prensipler, çok daha karmaşık gerçek dünya problemlerine uygulanabilir. Örneğin:
* Görüntü Tanıma: Daha büyük ve karmaşık veri kümeleri (CIFAR-10, ImageNet) üzerinde nesne tanıma, görüntü sınıflandırma.
* Doğal Dil İşleme (NLP): Metin sınıflandırma, duygu analizi, makine çevirisi, metin üretimi.
* Ses İşleme: Konuşma tanıma, ses sınıflandırma.
* Zaman Serisi Analizi: Finansal tahminler, sensör verisi analizi.

Bu konular, derin öğrenme yolculuğunuzda bir sonraki adımlarınızı şekillendirecek ve sizi daha ileri seviye projelere taşıyacaktır.

Sonuç

Bu makalede, PyTorch kütüphanesini kullanarak el yazısı rakamlarını tanıyabilen basit ama etkili bir yapay sinir ağı inşa etme sürecini detaylı bir şekilde inceledik. PyTorch’un temel yapı taşları olan Tensor’ları, otomatik türevleme mekanizması Autograd’ı, nn.Module tabanlı model tanımını ve eğitim sürecinin ana bileşenlerini (kayıp fonksiyonu, optimizatör, eğitim döngüsü) öğrendik. Ayrıca, MNIST veri kümesinin nasıl yüklendiğini ve ön işlendiğini, modelin nasıl eğitildiğini ve test veri kümesi üzerinde performansının nasıl değerlendirildiğini pratik bir kod örneğiyle gösterdik.

PyTorch, sunduğu esneklik, Pythonic arayüz ve dinamik hesaplama grafikleri sayesinde derin öğrenme araştırmacıları ve geliştiricileri için güçlü bir araçtır. Bu makaledeki örnek, derin öğrenmeye başlamak için sağlam bir temel sağlamaktadır. Elde ettiğimiz yüksek doğruluk oranları, basit bir çok katmanlı algılayıcının bile iyi hazırlanmış veriler üzerinde ne kadar etkili olabileceğini göstermektedir.

Derin öğrenme alanı sürekli gelişmekte olup, bu makalede öğrendikleriniz, daha karmaşık problemler ve daha gelişmiş ağ mimarileri için bir başlangıç noktasıdır. Evrişimsel Sinir Ağları, veri artırma, hiperparametre ayarı ve transfer öğrenme gibi konuları keşfetmek, derin öğrenme becerilerinizi bir sonraki seviyeye taşıyacaktır. Unutmayın, pratik yapmak ve farklı projeler üzerinde çalışmak, derin öğrenme ustası olmanın anahtarıdır. PyTorch ile bu heyecan verici dünyaya adım attınız; şimdi sıra, kendi yaratıcı projelerinizi hayata geçirmekte!

Yorumlar
İçeriği beğendiniz mi? Bir tartışma başlatın veya görüşlerinizi paylaşın.
Yorum Yaz

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Gönder

E-posta Bülteni
Yazılım Topluluğuna Katılın
En son güncellemeleri, yaratıcı ipuçlarını ve özel kaynakları doğrudan e-posta kutunuza alın. Tasarım ve inovasyonun geleceğini birlikte keşfedelim.
Mobil sürümden çık