- Bir nöronun ve tam bağlantılı bir katmanın matematiksel modelini yazmak
- ReLU, sigmoid, tanh ve softmax'ı hesaplamak ve nerede kullanıldıklarını bilmek
nn.Modulevenn.Sequentialile bir ağ kurmak ve parametrelerini saymak
Elle yazılmış bir rakamı tanımak istiyoruz: görüntü 28 × 28 = 784 pikseldir, cevap ise 0'dan 9'a on rakamdan biridir. Hangi fonksiyon 784 sayıyı on olasılığa çevirebilir? Sinir ağı bu fonksiyonu birçok basit parçadan kurar: doğrusal dönüşümler ve aralarında doğrusal olmayan “bükülmeler”. Adı beyinden esinlenmiştir ama aslında parametreleri gradyan inişiyle seçilen matematiksel bir fonksiyondur; tıpkı önceki derslerde gördüğümüz gibi.
Yapay nöron
- xgirdi vektörü (n öznitelik)
- wağırlıklar; her girdinin önemi
- bsapma (bias); aktivasyon eşiğini kaydırır
- φaktivasyon fonksiyonu (ReLU, sigmoid…)
- anöronun çıktısı (aktivasyon)
Bir nöron girdilerinin ağırlıklı toplamını hesaplar, sapmayı ekler ve sonucu bir aktivasyon fonksiyonundan geçirir. Aşağıdaki örnekte z = 0,4 · 0,5 + 0,3 · (−1) + (−0,2) · 2 + 0,1 = −0,4 olur: sigmoid bunu 0,4013'e, ReLU ise 0'a çevirir.
import torch
x = torch.tensor([0.5, -1.0, 2.0])
w = torch.tensor([0.4, 0.3, -0.2])
b = torch.tensor(0.1)
z = w @ x + b
print(round(z.item(), 4))
print(round(torch.sigmoid(z).item(), 4), torch.relu(z).item())-0.4 0.4013 0.0
Aktivasyon fonksiyonları
Aktivasyonlar olmasaydı, kaç katman eklersek ekleyelim ağ doğrusal kalırdı. İspatı kısadır: iki katman art arda uygulanınca W₂(W₁x + b₁) + b₂ = (W₂W₁)x + (W₂b₁ + b₂) elde edilir; bu, W = W₂W₁ matrisli ve b = W₂b₁ + b₂ sapmalı tek bir doğrusal katmandır. Doğrusal olmayan φ katmanları “büker” ve ağın karmaşık, eğri sınırları tanımlamasını sağlar.
- ReLUnegatif değerleri sıfırlar; türevi z > 0 için 1, z < 0 için 0
- σsigmoid: değerler (0; 1) aralığında, olasılık olarak yorumlanır
- tanhhiperbolik tanjant: değerler (−1; 1) aralığında, sıfıra göre simetrik
- zK sınıf için ham puanlar (logitler)
- softmax(z)ᵢi sınıfının olasılığı; hepsi pozitiftir ve toplamı 1'dir
Softmax, çok sınıflı sınıflandırmada son katmanın logitlerini bir olasılık dağılımına çevirir.
| Fonksiyon | Değer aralığı | Nerede kullanılır |
|---|---|---|
| ReLU | [0; ∞) | gizli katmanlarda varsayılan seçim: basit, hızlı, gradyan kaybolmaz |
| Sigmoid | (0; 1) | ikili sınıflandırmada çıktı, “kapılar” (LSTM) |
| tanh | (−1; 1) | yinelemeli ağlar, sıfır merkezli çıktı gerektiğinde |
| softmax | (0; 1), toplamı 1 | çok sınıflı sınıflandırmada son katman |
ReLU'nun bir zayıf yönü vardır: bir nöronun girdisi tüm örnekler için negatifse gradyanı hep sıfırdır ve nöron bir daha öğrenmez (“ölü ReLU”). LeakyReLU negatif tarafta küçük bir eğim bırakarak (örneğin 0,01z) buna karşı koyar. Transformerlarda ise ReLU'nun pürüzsüz bir türü olan GELU yaygın olarak kullanılır. PyTorch'ta hepsi hazırdır: nn.LeakyReLU(), nn.GELU(), nn.Tanh(), nn.Sigmoid().
import torch
z = torch.tensor([-2.0, 0.0, 1.0, 3.0])
print(torch.relu(z))
print(torch.sigmoid(z).round(decimals=4))
print(torch.tanh(z).round(decimals=4))
p = torch.softmax(z, dim=0)
print(p.round(decimals=4), round(p.sum().item(), 4))tensor([0., 0., 1., 3.]) tensor([0.1192, 0.5000, 0.7311, 0.9526]) tensor([-0.9640, 0.0000, 0.7616, 0.9951]) tensor([0.0057, 0.0418, 0.1135, 0.8390]) 1.0
Bir ağ üç sınıf için z = (2; 1; 0) logitlerini verdi. Olasılıkları bul.
Çözümü gösterÇözümü gizle
p ≈ (7,389 / 11,107; 2,718 / 11,107; 1 / 11,107) ≈ (0,665; 0,245; 0,090).
Logitler yalnızca 1 farklı ama olasılıklar yaklaşık e ≈ 2,72 kat farklı: softmax en büyük puanı “güçlendirir”.
import torch
print(torch.softmax(torch.tensor([2.0, 1.0, 0.0]), dim=0).round(decimals=3))tensor([0.6650, 0.2450, 0.0900])
Katmanlar: nn.Linear
Birkaç nöron aynı girdiye baktığında ağırlık vektörleri tek bir W matrisinin satırları olur ve katmanın tüm çıktıları tek bir matris çarpımıyla hesaplanır. Yığın hâlinde gelen girdiler (N, nin), çıktılar ise (N, nout) şeklindedir.
- Xgirdi yığını, şekil (N, nin)
- Wağırlıklar, şekil (nout, nin);
layer.weight - bsapmalar, şekil (nout,);
layer.bias - Yçıktılar, şekil (N, nout)
Her çıktı nöronunun nin ağırlığı ve bir sapması vardır; bu yüzden tam bağlantılı bir katmanda (nin + 1) · nout parametre bulunur.
import torch
from torch import nn
torch.manual_seed(42)
layer = nn.Linear(in_features=3, out_features=2)
print(layer.weight.shape, layer.bias.shape)
x = torch.randn(4, 3)
print(layer(x).shape)
print(sum(p.numel() for p in layer.parameters()))torch.Size([2, 3]) torch.Size([2]) torch.Size([4, 2]) 8
Ağırlıklar küçük rastgele değerlerle başlatılır: nn.Linear onları varsayılan olarak (−1/√nin; 1/√nin) aralığından düzgün dağılımla seçer. Rastgelelik önemlidir; tüm ağırlıklar eşit olsaydı katmandaki her nöron aynı gradyanı alır ve aynı şeyi öğrenirdi (simetri sorunu).
nn.Module ve nn.Sequential ile ağ
PyTorch'ta her model nn.Module'ün bir alt sınıfıdır. Katmanlar __init__ içinde oluşturulur, parametreleri otomatik olarak kaydedilir; forward metodu ise girdiden çıktıya hesaplamayı tanımlar. Modeli model(x) şeklinde çağırırız, PyTorch forward'u kendisi çalıştırır.
import torch
from torch import nn
class MLP(nn.Module):
def __init__(self, n_in, n_hidden, n_out):
super().__init__()
self.fc1 = nn.Linear(n_in, n_hidden)
self.fc2 = nn.Linear(n_hidden, n_out)
def forward(self, x):
h = torch.relu(self.fc1(x))
return self.fc2(h)
torch.manual_seed(42)
model = MLP(784, 128, 10)
print(model)
x = torch.randn(32, 784)
print(model(x).shape)
print(sum(p.numel() for p in model.parameters()))MLP( (fc1): Linear(in_features=784, out_features=128, bias=True) (fc2): Linear(in_features=128, out_features=10, bias=True) ) torch.Size([32, 10]) 101770
model.parameters()— tüm eğitilebilir parametreler; onları optimizasyon aracına veririz.model.to(device)— tüm parametreleri tek çağrıyla CPU'dan GPU'ya (ya da tersine) taşır.model.train()vemodel.eval()— eğitim ve değerlendirme modları (Dropout ve BatchNorm katmanları için önemlidir).model.state_dict()— parametrelerin sözlüğü; bir sonraki derste modeli dosyaya kaydetmek için kullanacağız.
Tam bağlantılı katmanlardan ve aralarındaki aktivasyonlardan oluşan ağa çok katmanlı algılayıcı denir. Son katmanının normalleştirilmemiş çıktıları, yani logitler, herhangi bir gerçek sayı olabilir. Tahmin için en büyük logitin indeksi (logits.argmax(dim=1)), olasılıklar için ise torch.softmax(logits, dim=1) kullanılır.
Mimari nasıl seçilir? Tablo verisi için genellikle 32–256 nöronlu 1–3 gizli katman yeterlidir; küçük bir modelle başla, doğrulama kaybı izin verdikçe büyüt. Görüntüler için ise tam bağlantılı katmanlar çok pahalıdır: 224 × 224 renkli bir görüntüden 1000 nöronluk bir katmana geçmek bile 150 milyondan fazla parametre ister. Bu sorunu evrişimli ağlar çözer.
Katmanlar yalnızca art arda diziliyorsa sınıf yazmaya gerek yoktur: nn.Sequential onları sırayla uygular. Aktivasyon burada bir nn.ReLU() katmanı olarak yazılır. named_parameters() her parametrenin adını ve şeklini gösterir; hata ayıklamada çok işe yarar:
import torch
from torch import nn
model = nn.Sequential(
nn.Linear(784, 128), nn.ReLU(),
nn.Linear(128, 64), nn.ReLU(),
nn.Linear(64, 10),
)
for name, p in model.named_parameters():
print(name, tuple(p.shape))
print(sum(p.numel() for p in model.parameters()))0.weight (128, 784) 0.bias (128,) 2.weight (64, 128) 2.bias (64,) 4.weight (10, 64) 4.bias (10,) 109386
Sequential içindeki sırasıdır; 1 ve 3 numaralı ReLU katmanlarının parametresi yoktur.784 → 128 → 64 → 10 ağında kaç parametre vardır? float32'de ne kadar bellek kaplarlar?
Çözümü gösterÇözümü gizle
2. katman: (128 + 1) · 64 = 8.256.
3. katman: (64 + 1) · 10 = 650.
Toplam: 109.386; kodun çıktısıyla aynı.
Bellek: 109.386 · 4 bayt ≈ 0,44 MB. Parametrelerin %92'si ilk katmanda: büyük girdiler pahalıdır.
2 → 2 → 1 ağı: W₁ = [[1; −1]; [0,5; 0,5]], b₁ = (0; −1), gizli katmanda ReLU, W₂ = [[2; −3]], b₂ = 1. x = (1; 2) için çıktıyı bul.
Çözümü gösterÇözümü gizle
ReLU: h = (0; 0,5); birinci nöron “söndü”.
y = 2 · 0 + (−3) · 0,5 + 1 = −0,5.
Dikkat: bu x için birinci nöronun çıktıya hiçbir etkisi yoktur; bu yüzden geri geçişte ağırlıklarının gradyanı da sıfır olur. ReLU gradyanı yalnızca etkin nöronlardan geçirir.
import torch
x = torch.tensor([1.0, 2.0])
W1 = torch.tensor([[1.0, -1.0], [0.5, 0.5]])
b1 = torch.tensor([0.0, -1.0])
W2 = torch.tensor([[2.0, -3.0]])
b2 = torch.tensor([1.0])
h = torch.relu(W1 @ x + b1)
y = W2 @ h + b2
print(h, y)tensor([0.0000, 0.5000]) tensor([-0.5000])
Önemli noktalar
- Bir nöron z = w · x + b'yi, ardından a = φ(z) aktivasyonunu hesaplar; katman bunu matris biçiminde yapar: Y = X · Wᵀ + b.
- Aktivasyonsuz çok katmanlı bir ağ tek bir doğrusal katmana eşittir; gizli katmanlarda genellikle ReLU kullanılır.
- Softmax logitleri toplamı 1 olan olasılıklara çevirir;
nn.CrossEntropyLoss'a ise ham logitler verilir. - Model
nn.Module'den türer: katmanlar__init__içinde, hesaplamaforwardiçinde; basit bir zincir içinnn.Sequentialyeterlidir. - Tam bağlantılı bir katmanda (nin + 1) · nout parametre vardır;
nn.Linear(n_in, n_out).weight'in şekli (nout, nin)'dir.
Kendini test et
10 soru. Her doğru cevap XP kazandırır.
nn.Linear(10, 5) katmanında kaç parametre vardır?