Ana içeriğe geç

Orta12 dkB — Görüntü ve CNN

CNN mimarisinin tamamı

Önkoşul:Pooling katmanları

Kanca

25-29. derste CNN’in her PARÇASINI ayrı ayrı gördük: piksel/kanal (25), neden tam bağlı ağ yetmez (26), konvolüsyon (27), stride/padding (28), pooling (29). Bu derste hepsini BİR ARAYA getirip, gerçek bir CNN’in baştan sona nasıl çalıştığını izliyoruz.

Sezgi

Tipik bir CNN, konvolüsyon+ReLU+pooling bloklarını art arda tekrarlayıp, en sonunda tam bağlı bir katmanla sınıflandırma yapar. Her blok, uzamsal boyutu KÜÇÜLTÜRKEN, kanal (özellik) sayısını ARTIRIR — “daha az yer, daha çok anlam” deseni.

Aşağıdaki gezginde, önhesaplanmış GERÇEK aktivasyonlarla (bir “artı” şekli görselinin) katman katman nasıl dönüştüğünü izle.

1 / 8

16×16, 1 kanal -- bir "artı" şekli (25. ders: piksel ızgarası).

Mekanizma

Notebook’ta AYNI ağı, AYNI görseli kullanarak baştan sona kuralım:

Girdi ve ilk konvolüsyon

# 25-29. derste öğrendiğimiz HER PARÇAYI birleştirip GERÇEK bir CNN'in ileri
# geçişini baştan sona izleyelim. Girdi: 16x16'lık bir "artı" şekli.
GIRDI_BOYUT = 16
girdi = torch.zeros(1, 1, GIRDI_BOYUT, GIRDI_BOYUT)
orta = GIRDI_BOYUT // 2
girdi[0, 0, orta-1:orta+1, 3:13] = 1.0  # yatay kol
girdi[0, 0, 3:13, orta-1:orta+1] = 1.0  # dikey kol

# Conv1: 4 elle-tasarlanmış çekirdek (27. dersteki gibi) -- ilk katmanlar genelde
# kenar/doku gibi BASİT örüntüleri öğrenir, biz burada bunu elle taklit ediyoruz.
k_yatay = torch.tensor([[-1., -2, -1], [0, 0, 0], [1, 2, 1]])
k_dikey = torch.tensor([[-1., 0, 1], [-2, 0, 2], [-1, 0, 1]])
k_capraz = torch.tensor([[2., 1, 0], [1, 0, -1], [0, -1, -2]])
k_blur = torch.ones(3, 3) / 9
conv1_kernel = torch.stack([k_yatay, k_dikey, k_capraz, k_blur]).unsqueeze(1)  # (4 filtre, 1 giriş kanalı, 3, 3)

conv1_cikis = F.conv2d(girdi, conv1_kernel, padding=1)  # "same" padding (28. ders)
print(f"Girdi şekli: {tuple(girdi.shape)} -> Conv1 çıkış şekli: {tuple(conv1_cikis.shape)}")
print("4 filtre, 4 farklı özellik haritası üretti -- her biri farklı bir örüntüye duyarlı.")
Girdi şekli: (1, 1, 16, 16) -> Conv1 çıkış şekli: (1, 4, 16, 16)
4 filtre, 4 farklı özellik haritası üretti -- her biri farklı bir örüntüye duyarlı.

ReLU ve ilk pooling

# ReLU (8. ders) negatifleri sıfırlar; MaxPool (29. ders) boyutu yarıya indirir.
relu1_cikis = F.relu(conv1_cikis)
pool1_cikis = F.max_pool2d(relu1_cikis, kernel_size=2, stride=2)

print(f"\nReLU1 sonrası şekil: {tuple(relu1_cikis.shape)} (değişmedi -- ReLU boyutu etkilemez)")
print(f"Pool1 sonrası şekil: {tuple(pool1_cikis.shape)} (16x16 -> 8x8, MaxPool boyutu yarıya indirdi)")
print(f"Negatif değer oranı (ReLU öncesi): {(conv1_cikis < 0).float().mean().item():.2%}")
print(f"Negatif değer oranı (ReLU sonrası): {(relu1_cikis < 0).float().mean().item():.2%}")

ReLU1 sonrası şekil: (1, 4, 16, 16) (değişmedi -- ReLU boyutu etkilemez)
Pool1 sonrası şekil: (1, 4, 8, 8) (16x16 -> 8x8, MaxPool boyutu yarıya indirdi)
Negatif değer oranı (ReLU öncesi): 9.57%
Negatif değer oranı (ReLU sonrası): 0.00%

16×16’lık girdi, Conv1+ReLU1’den sonra HÂLÂ 16×16 (4 kanal) — ama Pool1’den sonra 8×8’e iniyor. Çoğu kişi “her katman boyutu küçültür” sanır. Yanlış, çünkü konvolüsyon (same padding’le) ve ReLU boyutu DEĞİŞTİRMEZ — boyutu küçülten SADECE pooling (ve stride’lı konvolüsyon).

Matematik

Tipik bir CNN bloğunun akışı
GirdiKonvolu¨syonReLUPoolingBir sonraki blog˘a\text{Girdi} \xrightarrow{\text{Konvolüsyon}} \xrightarrow{\text{ReLU}} \xrightarrow{\text{Pooling}} \text{Bir sonraki bloğa}
KatmanBoyuta etkisiKanal sayısına etkisi
Konvolüsyon (same padding)DeğiştirmezARTIRIR (filtre sayısı kadar)
ReLUDeğiştirmezDeğiştirmez
PoolingKÜÇÜLTÜR (genelde yarıya)Değiştirmez

Bu üçü ard arda tekrarlandıkça, ağın “görüş alanı” (receptive field) büyür — son katmanlardaki her nöron, girdinin GİDEREK DAHA GENİŞ bir bölgesinden etkilenir.

Kod

İkinci bloğu ve sınıflandırma adımını tamamlayalım:

İkinci konvolüsyon bloğu

# İkinci konvolüsyon bloğu: 4 kanaldan 8 kanala. Bu katmanın çekirdekleri artık
# elle tasarlanmıyor -- gerçek bir ağda geri yayılımla ÖĞRENİLİR (biz burada
# rastgele başlatılmış haliyle gösteriyoruz -- henüz eğitilmemiş bir ağ gibi).
conv2_kernel = torch.randn(8, 4, 3, 3) * 0.3
conv2_cikis = F.conv2d(pool1_cikis, conv2_kernel, padding=1)
relu2_cikis = F.relu(conv2_cikis)
pool2_cikis = F.max_pool2d(relu2_cikis, kernel_size=2, stride=2)

print(f"\nConv2 çıkış şekli: {tuple(conv2_cikis.shape)} -- 4 kanaldan 8 kanala ÇIKTI")
print(f"Pool2 sonrası şekil: {tuple(pool2_cikis.shape)} -- 8x8 -> 4x4")
print("Her konvolüsyon+pool bloğu, uzamsal boyutu KÜÇÜLTÜP kanal (özellik) sayısını ARTIRIYOR.")
print("Bu, CNN mimarilerinin karakteristik deseni: derinleştikçe 'daha az yer, daha çok anlam'.")

Conv2 çıkış şekli: (1, 8, 8, 8) -- 4 kanaldan 8 kanala ÇIKTI
Pool2 sonrası şekil: (1, 8, 4, 4) -- 8x8 -> 4x4
Her konvolüsyon+pool bloğu, uzamsal boyutu KÜÇÜLTÜP kanal (özellik) sayısını ARTIRIYOR.
Bu, CNN mimarilerinin karakteristik deseni: derinleştikçe 'daha az yer, daha çok anlam'.

Düzleştirme, tam bağlı katman, softmax

# Son adım: uzamsal haritayı DÜZLEŞTİRİP (flatten) tam bağlı bir katmana ver --
# 26. derste sorguladığımız o "tam bağlı ağ" burada, ama artık HAM piksellere değil,
# CNN'in çıkardığı YÜKSEK SEVİYELİ özelliklere uygulanıyor.
duzlestir = pool2_cikis.flatten()
fc_agirlik = torch.randn(10, duzlestir.shape[0]) * 0.1
fc_bias = torch.randn(10) * 0.1
fc_cikis = fc_agirlik @ duzlestir + fc_bias
softmax_cikis = F.softmax(fc_cikis, dim=0)

print(f"\nDüzleştirilmiş vektör boyutu: {duzlestir.shape[0]} (4×4×8)")
print(f"FC çıkış (10 'sınıf' için ham logit): {[f'{v:.2f}' for v in fc_cikis.tolist()]}")
print(f"Softmax sonrası olasılıklar: {[f'{v:.3f}' for v in softmax_cikis.tolist()]}")
print(f"En yüksek olasılıklı sınıf: {softmax_cikis.argmax().item()} (olasılık={softmax_cikis.max().item():.3f})")
print("\nBu 'sınıf' rastgele başlatılmış (eğitilmemiş) ağırlıklarla üretildi -- gerçek bir sınıflandırma değil,")
print("sadece 27-30. derste gördüğümüz TÜM parçaların (konv, ReLU, pool, FC, softmax) nasıl ZİNCİRLENDİĞİNİ gösteriyor.")

Düzleştirilmiş vektör boyutu: 128 (4×4×8)
FC çıkış (10 'sınıf' için ham logit): ['-0.41', '-4.89', '2.74', '-2.64', '-2.08', '-2.80', '1.72', '0.71', '-2.50', '-6.39']
Softmax sonrası olasılıklar: ['0.027', '0.000', '0.643', '0.003', '0.005', '0.003', '0.231', '0.084', '0.003', '0.000']
En yüksek olasılıklı sınıf: 2 (olasılık=0.643)

Bu 'sınıf' rastgele başlatılmış (eğitilmemiş) ağırlıklarla üretildi -- gerçek bir sınıflandırma değil,
sadece 27-30. derste gördüğümüz TÜM parçaların (konv, ReLU, pool, FC, softmax) nasıl ZİNCİRLENDİĞİNİ gösteriyor.

Son adımda, 4×4×8’lik uzamsal harita düzleştirilip (26. dersteki “tam bağlı ağ” fikri BURADA geri dönüyor — ama artık ham piksellere değil, CNN’in çıkardığı YÜKSEK SEVİYELİ özelliklere uygulanıyor) 10 “sınıf” üzerinde bir softmax (9. ders) dağılımı üretiliyor.

Girdi görseli, iki konvolüsyon+ReLU filtre örneği, iki pooling kanalı örneği ve softmax çıktısını gösteren altı panelli bir şekil.
Bir CNN'in baştan sona yolculuğu: girdi -> konvolüsyon+ReLU -> pooling -> (tekrar) -> düzleştirme -> softmax.

Nerede işe yarar

Bu “konv+ReLU+pool bloklarını tekrarla, sonunda FC+softmax” deseni, neredeyse TÜM klasik CNN mimarilerinin (31. ders) iskeletidir:

  • Erken bloklar (girdiye yakın) BASİT örüntüleri (kenar, doku) yakalar — notebook’taki elle tasarladığımız Conv1 filtreleri gibi.
  • Derin bloklar (çıktıya yakın) KARMAŞIK, SOYUT örüntüleri (şekil, nesne parçası) yakalar — gerçek ağlarda bu, eğitimle kendiliğinden ortaya çıkar.
  • Bu derste kullandığımız ağırlıklar RASTGELE (eğitilmemiş) — softmax çıktısı anlamlı bir sınıflandırma değil, sadece MİMARİNİN nasıl aktığını gösteriyor.

Bu 3 hatayı yaparsın:

  1. Her katmanın boyutu küçülttüğünü sanmak — sadece pooling (veya stride>1 konvolüsyon) boyutu küçültür.
  2. Kanal sayısı ile uzamsal boyutu karıştırmak — derinleştikçe biri artar, diğeri azalır.
  3. CNN’in “sihirli” olduğunu düşünmek — aslında sadece 25-29. derste gördüğümüz basit işlemlerin (konvolüsyon, ReLU, pooling, FC, softmax) sıralı bir zinciri.

Kendini test et

1. Notebook'ta Conv1+ReLU1'den sonra görüntü hâlâ 16×16 iken, Pool1'den sonra neden 8×8'e indi?
  1. Conv1 ve ReLU1 hatalıydı
  2. Konvolüsyon (same padding'le) ve ReLU boyutu DEĞİŞTİRMEZ -- boyutu küçülten katman SADECE pooling (doğru cevap)
  3. Her katman otomatik olarak boyutu yarıya indirir
  4. Girdi boyutu yanlış hesaplandı

Neden: Same padding'li konvolüsyon çıkış boyutunu girdiyle aynı tutar (28. ders); ReLU sadece değerleri değiştirir, şekli değil (8. ders); boyutu küçülten tek işlem MaxPool'dur (29. ders).

2. CNN derinleştikçe (girdiden çıktıya doğru ilerledikçe) uzamsal boyut ve kanal sayısı nasıl değişir?
  1. İkisi de artar
  2. Uzamsal boyut genelde KÜÇÜLÜR, kanal (özellik) sayısı genelde ARTAR -- "daha az yer, daha çok anlam" (doğru cevap)
  3. İkisi de sabit kalır
  4. Uzamsal boyut artar, kanal sayısı azalır

Neden: Notebook'ta girdi 16×16×1'den başlayıp Pool2 sonrası 4×4×8'e ulaştı -- uzamsal boyut küçülürken (16->8->4) kanal sayısı büyüdü (1->4->8), bu klasik CNN deseni.

3. Bu dersteki CNN'in softmax çıktısının rastgele (eğitilmemiş) ağırlıklarla üretilmiş olması ne anlama gelir?
  1. Softmax formülü yanlış uygulandı
  2. Çıktı, gerçek bir sınıflandırma DEĞİLDİR -- amaç, mimarinin katmanlarının nasıl ZİNCİRLENDİĞİNİ göstermektir; gerçek bir ağ bu ağırlıkları eğitimle öğrenir (doğru cevap)
  3. Model zaten mükemmel eğitilmiş
  4. Rastgele ağırlıklar hiçbir çıktı üretemez

Neden: Bu dersin amacı bir sınıflandırıcı EĞİTMEK değil, CNN mimarisinin BİLEŞENLERİNİN (konv, ReLU, pool, FC, softmax) nasıl bir araya geldiğini göstermektir -- gerçek bir uygulamada bu ağırlıklar veri üzerinde eğitilir.

Özet

Özet

  • Tipik bir CNN, konvolüsyon+ReLU+pooling bloklarını tekrarlayıp sonunda tam bağlı katman+softmax ile biter.
  • Konvolüsyon (same padding) ve ReLU boyutu değiştirmez; pooling boyutu küçültür.
  • Derinleştikçe uzamsal boyut küçülür, kanal (özellik) sayısı artar.
  • Erken katmanlar basit örüntüleri (kenar, doku), derin katmanlar soyut örüntüleri yakalar.
  • Bu mimari iskelet, 31. derste göreceğimiz TÜM klasik CNN mimarilerinin (LeNet, ResNet) temelidir.
Sonraki adım: Klasik mimariler (LeNet → ResNet) →