4.2. Çok Katmanlı Algılayıcıların Sıfırdan Uygulanması
Open the notebook in Colab
Open the notebook in Colab
Open the notebook in Colab
Open the notebook in SageMaker Studio Lab

Artık çok katmanlı algılayıcıları (MLP’ler) matematiksel olarak nitelendirdiğimize göre, birini kendimiz uygulamaya çalışalım. Softmax regresyonu (Section 3.6) ile elde ettiğimiz önceki sonuçlarla karşılaştırmak için Fashion-MNIST imge sınıflandırma veri kümesi (Section 3.5) ile çalışmaya devam edeceğiz.

from d2l import mxnet as d2l
from mxnet import gluon, np, npx

npx.set_np()

batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
import torch
from torch import nn
from d2l import torch as d2l

batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
import tensorflow as tf
from d2l import tensorflow as d2l

batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)

4.2.1. Model Parametrelerini İlkleme

Fashion-MNIST’in 10 sınıf içerdiğini ve her imgenin \(28 \times 28 = 784\) gri tonlamalı piksel değerleri ızgarasından oluştuğunu hatırlayın. Yine şimdilik pikseller arasındaki uzamsal yapıyı göz ardı edeceğiz, bu nedenle bunu 784 girdi özniteliği ve 10 sınıf içeren basit bir sınıflandırma veri kümesi olarak düşünebiliriz. Başlarken, bir gizli katman ve 256 gizli birim içeren bir MLP uygulayacağız. Bu miktarların ikisini de hiper parametreler olarak kabul edebileceğimizi unutmayın. Tipik olarak, belleğin donanımda öyle tahsis edildiğinden ve adreslendiğinden hesaplama açısından verimli olma eğiliminde olan 2’nin katlarında katman genişliklerini seçiyoruz.

Yine, parametrelerimizi birkaç tensörle temsil edeceğiz. Her katman için, bir ağırlık matrisini ve bir ek girdi vektörünü izlememiz gerektiğini unutmayın. Her zaman olduğu gibi, bu parametrelere göre kaybın gradyanları için bellek ayırıyoruz.

num_inputs, num_outputs, num_hiddens = 784, 10, 256

W1 = np.random.normal(scale=0.01, size=(num_inputs, num_hiddens))
b1 = np.zeros(num_hiddens)
W2 = np.random.normal(scale=0.01, size=(num_hiddens, num_outputs))
b2 = np.zeros(num_outputs)
params = [W1, b1, W2, b2]

for param in params:
    param.attach_grad()
num_inputs, num_outputs, num_hiddens = 784, 10, 256

W1 = nn.Parameter(torch.randn(
    num_inputs, num_hiddens, requires_grad=True) * 0.01)
b1 = nn.Parameter(torch.zeros(num_hiddens, requires_grad=True))
W2 = nn.Parameter(torch.randn(
    num_hiddens, num_outputs, requires_grad=True) * 0.01)
b2 = nn.Parameter(torch.zeros(num_outputs, requires_grad=True))

params = [W1, b1, W2, b2]
num_inputs, num_outputs, num_hiddens = 784, 10, 256

W1 = tf.Variable(tf.random.normal(
    shape=(num_inputs, num_hiddens), mean=0, stddev=0.01))
b1 = tf.Variable(tf.zeros(num_hiddens))
W2 = tf.Variable(tf.random.normal(
    shape=(num_hiddens, num_outputs), mean=0, stddev=0.01))
b2 = tf.Variable(tf.random.normal([num_outputs], stddev=.01))

params = [W1, b1, W2, b2]

4.2.2. Etkinleştirme Fonksiyonu

Her şeyin nasıl çalıştığını bildiğimizden emin olmak için, ReLU aktivasyonunu yerleşik relu işlevini doğrudan çağırmak yerine maksimum işlevi kullanarak kendimiz uygulayacağız.

def relu(X):
    return np.maximum(X, 0)
def relu(X):
    a = torch.zeros_like(X)
    return torch.max(X, a)
def relu(X):
    return tf.math.maximum(X, 0)

4.2.3. Model

Uzamsal yapıyı göz ardı ettiğimiz için, her iki boyutlu imgeyi num_inputs uzunluğuna sahip düz bir vektör halinde (reshape) yeniden şekillendiriyoruz. Son olarak, modelimizi sadece birkaç satır kodla uyguluyoruz.

def net(X):
    X = X.reshape((-1, num_inputs))
    H = relu(np.dot(X, W1) + b1)
    return np.dot(H, W2) + b2
def net(X):
    X = X.reshape((-1, num_inputs))
    H = relu(X@W1 + b1)  # Burada '@' matris carpimini temsil eder
    return (H@W2 + b2)
def net(X):
    X = tf.reshape(X, (-1, num_inputs))
    H = relu(tf.matmul(X, W1) + b1)
    return tf.matmul(H, W2) + b2

4.2.4. Kayıp İşlevi

Sayısal kararlılığı sağlamak için ve softmaks işlevini zaten sıfırdan uygularken (Section 3.6), softmaks ve çapraz entropi kaybını hesaplamak için yüksek seviyeli API’lerden birleşik işlevi kullanıyoruz. Bu karmaşıklıkla ilgili önceki tartışmamızı Section 3.7.2 içinden hatırlayın. İlgili okuru, uygulama ayrıntıları hakkındaki bilgilerini derinleştirmek için kayıp işlevi kaynak kodunu incelemeye teşvik ediyoruz.

loss = gluon.loss.SoftmaxCrossEntropyLoss()
loss = nn.CrossEntropyLoss(reduction='none')
def loss(y_hat, y):
    return tf.losses.sparse_categorical_crossentropy(
        y, y_hat, from_logits=True)

4.2.5. Eğitim

Neyse ki, MLP’ler için eğitim döngüsü softmax bağlanımıyla tamamen aynıdır. Tekrar d2l paketini kullanarak, train_ch3 fonksiyonunu çağırıyoruz (bkz. Section 3.6), dönem sayısını 10 ve öğrenme oranını 0.1 olarak ayarlıyoruz.

num_epochs, lr = 10, 0.1
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs,
              lambda batch_size: d2l.sgd(params, lr, batch_size))
../_images/output_mlp-scratch_106d07_63_0.svg
num_epochs, lr = 10, 0.1
updater = torch.optim.SGD(params, lr=lr)
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, updater)
../_images/output_mlp-scratch_106d07_66_0.svg
num_epochs, lr = 10, 0.1
updater = d2l.Updater([W1, W2, b1, b2], lr)
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, updater)
../_images/output_mlp-scratch_106d07_69_0.svg

Öğrenilen modeli değerlendirmek için onu bazı test verisine uyguluyoruz.

d2l.predict_ch3(net, test_iter)
../_images/output_mlp-scratch_106d07_75_0.svg
d2l.predict_ch3(net, test_iter)
../_images/output_mlp-scratch_106d07_78_0.svg
d2l.predict_ch3(net, test_iter)
../_images/output_mlp-scratch_106d07_81_0.svg

4.2.6. Özet

  • Manuel olarak yapıldığında bile basit bir MLP uygulamanın kolay olduğunu gördük.

  • Bununla birlikte, çok sayıda katmanla, MLP’leri sıfırdan uygulamak yine de karmaşık olabilir (örneğin, modelimizin parametrelerini adlandırmak ve takip etmek).

4.2.7. Alıştırmalar

  1. Hiper parametre num_hiddens değerini değiştirin ve bu hiper parametrenin sonuçlarınızı nasıl etkilediğini görün. Diğerlerini sabit tutarak bu hiper parametrenin en iyi değerini belirleyiniz.

  2. Sonuçları nasıl etkilediğini görmek için ek bir gizli katman eklemeyi deneyiniz.

  3. Öğrenme oranını değiştirmek sonuçlarınızı nasıl değiştirir? Model mimarisini ve diğer hiper parametreleri (dönem sayısı dahil) sabitlersek, hangi öğrenme oranı size en iyi sonuçları verir?

  4. Tüm hiper parametreleri (öğrenme oranı, dönem sayısı, gizli katman sayısı, katman başına gizli birim sayısı) birlikte optimize ederek elde edebileceğiniz en iyi sonuç nedir?

  5. Birden fazla hiper parametre ile uğraşmanın neden çok daha zor olduğunu açıklayınız.

  6. Birden fazla hiper parametre üzerinde bir arama yapılandırmak için düşünebileceğiniz en akıllı strateji nedir?