Ana içeriğe geç

Orta10 dkB — Görüntü ve CNN

Filtre, stride, padding

Önkoşul:Konvolüsyon işlemi

Kanca

  1. dersteki konvolüsyonda pencere her zaman TEK piksel kayıyor ve dolgu (padding) yoktu. Bu ders, bu iki varsayımı gevşetiyor: pencere kaç piksel kayabilir (stride), ve girdinin kenarına sıfır eklemek (padding) neden faydalı?

Sezgi

Stride, pencerenin her adımda kaç piksel kaydığıdır; padding, girdinin kenarlarına eklenen sıfır çerçevesidir. İkisi de çıkış boyutunu etkiler — ama padding’in ikinci, daha az bilinen bir faydası daha var: kenar piksellerin “adil” temsil edilmesini sağlamak.

Kaydırıcılarla oyna — çıkış boyutu formülünün canlı nasıl değiştiğini izle.

Girdi (7×7)

Çıkış (5×5)

Çıkış boyutu = ⌊(Girdi + 2×Padding − Çekirdek) / Stride⌋ + 1 = ⌊(7 + 2×0 − 3) / 1⌋ + 1 = 5

Mekanizma

Önce stride’ın etkisini görelim:

Stride, çıkış boyutunu nasıl küçültür

# Stride: çekirdeğin her adımda KAÇ piksel kaydığı. stride=1 varsayılan; büyük
# stride, pencereyi daha SEYREK gezdirip çıkışı küçültür.
girdi = torch.arange(1, 26, dtype=torch.float32).reshape(1, 1, 5, 5)
kernel = torch.ones(1, 1, 3, 3)

print("Girdi (5x5):")
print(girdi[0, 0].numpy().astype(int))

print(f"\n{'Stride':<10} {'Çıkış şekli':<14}")
for s in [1, 2, 3]:
    cikis = F.conv2d(girdi, kernel, stride=s)
    print(f"{s:<10} {tuple(cikis.shape[2:])}")

print("\nstride=1: pencere HER pikselde duruyor (3x3 çıkış). stride=3: pencere sadece 1 kez duruyor (1x1 çıkış).")
Girdi (5x5):
[[ 1  2  3  4  5]
 [ 6  7  8  9 10]
 [11 12 13 14 15]
 [16 17 18 19 20]
 [21 22 23 24 25]]

Stride     Çıkış şekli   
1          (3, 3)
2          (2, 2)
3          (1, 1)

stride=1: pencere HER pikselde duruyor (3x3 çıkış). stride=3: pencere sadece 1 kez duruyor (1x1 çıkış).

stride=1’de pencere HER piksel konumunda duruyor (3×3 çıkış); stride=3’te sadece 1 kez duruyor (1×1 çıkış). Şimdi padding:

Padding, çıkış boyutunu nasıl korur

# Padding: girdinin KENARLARINA sıfır ekleyerek, çıkışın küçülmesini yavaşlatmak
# (veya "same" padding ile TAMAMEN önlemek).
print(f"\n{'Padding':<10} {'Çıkış şekli':<14}")
for p in [0, 1]:
    cikis = F.conv2d(girdi, kernel, padding=p)
    print(f"{p:<10} {tuple(cikis.shape[2:])}")

print("\npadding=1 ile 3x3 çekirdek, çıkışı girdiyle AYNI boyutta (5x5) tutuyor -- buna 'same' padding denir.")

Padding    Çıkış şekli   
0          (3, 3)
1          (5, 5)

padding=1 ile 3x3 çekirdek, çıkışı girdiyle AYNI boyutta (5x5) tutuyor -- buna 'same' padding denir.

padding=1 ile 3×3’lük çekirdek, çıkışı girdiyle AYNI boyutta (5×5) tutuyor — “same” padding. Ama padding’in İKİNCİ bir faydası var:

Kenar piksellerin 'görülme' sayısı

# Padding'in daha az bilinen bir faydası: KENAR piksellerin, pencere tarafından
# KAÇ KEZ 'görüldüğünü' sayalım.
def ziyaret_sayaci(girdi_boyut, kernel_boyut, stride, padding):
    padded = girdi_boyut + 2 * padding
    sayac = np.zeros((padded, padded))
    konumlar = []
    k = 0
    while k + kernel_boyut <= padded:
        konumlar.append(k)
        k += stride
    for i in konumlar:
        for j in konumlar:
            sayac[i:i+kernel_boyut, j:j+kernel_boyut] += 1
    return sayac[padding:padding+girdi_boyut, padding:padding+girdi_boyut]

print("\nPadding YOK: her pikselin pencere tarafından kaç kez 'görüldüğü':")
print(ziyaret_sayaci(5, 3, 1, 0).astype(int))
print("\nPadding VAR (padding=1):")
print(ziyaret_sayaci(5, 3, 1, 1).astype(int))
print("\nPadding'siz köşe piksel SADECE 1 kez görülüyor (merkez piksel 9 kez!) -- kenar bilgisi kayboluyor.")
print("Padding, bu dengesizliği azaltıyor -- köşe piksel artık 4 kez görülüyor.")

Padding YOK: her pikselin pencere tarafından kaç kez 'görüldüğü':
[[1 2 3 2 1]
 [2 4 6 4 2]
 [3 6 9 6 3]
 [2 4 6 4 2]
 [1 2 3 2 1]]

Padding VAR (padding=1):
[[4 6 6 6 4]
 [6 9 9 9 6]
 [6 9 9 9 6]
 [6 9 9 9 6]
 [4 6 6 6 4]]

Padding'siz köşe piksel SADECE 1 kez görülüyor (merkez piksel 9 kez!) -- kenar bilgisi kayboluyor.
Padding, bu dengesizliği azaltıyor -- köşe piksel artık 4 kez görülüyor.

Padding olmadan köşe piksel pencere tarafından SADECE 1 kez görülüyor — merkez piksel ise 9 kez! Çoğu kişi “padding sadece boyutu korumak için” sanır. Eksik, çünkü padding aynı zamanda kenar bilgisinin, konvolüsyon tarafından merkez kadar “ciddiye alınmasını” sağlıyor.

Matematik

Çıkış boyutu formülü
O=W+2PKS+1O = \left\lfloor \frac{W + 2P - K}{S} \right\rfloor + 1
SembolAnlamı
WWGirdi boyutu (genişlik veya yükseklik)
KKÇekirdek (kernel) boyutu
PPPadding — her kenara eklenen piksel sayısı
SSStride — pencerenin her adımda kaç piksel kaydığı
OOÇıkış boyutu

S=1S=1 ve P=(K1)/2P = (K-1)/2 (tek sayılı KK için) seçilirse, O=WO=W olur — “same” padding. P=0P=0 ise “valid” padding denir (sadece geçerli, tam örtüşen konumlar).

Kod

Solda padding olmadan, sağda padding ile her pikselin pencere tarafından kaç kez görüldüğünü gösteren iki ısı haritası; padding olmadan köşeler çok daha az görülüyor.
Padding olmadan (sol), köşe pikseller merkeze göre çok daha az kez 'görülüyor'. Padding (sağ), bu dengesizliği azaltıyor.

Nerede işe yarar

Stride ve padding, CNN mimarisinin (30. ders) her katmanında ayarlanan iki temel hiperparametredir:

  • stride=1, padding=“same” en yaygın varsayılandır — özellik haritası boyutunu korur, bilgi kaybını en aza indirir.
  • stride=2, boyut küçültmek için (pooling’e alternatif olarak, 29. ders) kullanılabilir — hesaplama maliyetini azaltır.
  • PyTorch’ta nn.Conv2d(..., stride=1, padding=1) gibi parametrelerle doğrudan ayarlanır.

Bu 3 hatayı yaparsın:

  1. Padding’i sadece “boyutu korumak için” kullanmak, kenar bilgisi kaybı sorununu göz ardı etmek.
  2. Stride ve pooling’i (29. ders) karıştırmak — ikisi de boyutu küçültür ama FARKLI mekanizmalarla.
  3. Çıkış boyutu formülünü ezbere bilmeden, deneme-yanılmayla mimari tasarlamaya çalışmak — büyük ağlarda bu hataya çok vakit kaybettirir.

Kendini test et

1. Notebook'ta padding olmadan köşe pikselin pencere tarafından sadece 1 kez, merkez pikselin 9 kez görülmesinin sonucu nedir?
  1. Hiçbir pratik etkisi yoktur
  2. Kenar bölgelerindeki bilgi, konvolüsyon tarafından merkeze göre çok daha az "dikkate alınır" -- bu bir bilgi kaybı riski taşır (doğru cevap)
  3. Köşe pikseller her zaman sıfır olur
  4. Bu sadece bir görselleştirme hatasıdır

Neden: Bir pikselin kaç kez pencere içine girdiği, o pikselin çıkış özelliklerine ne kadar katkı sağladığını belirler; köşe pikseller çok daha az kez görüldüğü için kenar bilgisi orantısız şekilde az temsil edilir.

2. Çıkış boyutu formülünde (⌊(W+2P-K)/S⌋+1) stride (S) büyütüldüğünde ne olur?
  1. Çıkış boyutu büyür
  2. Çıkış boyutu küçülür -- pencere daha SEYREK konumlarda durur (doğru cevap)
  3. Hiçbir etkisi olmaz
  4. Formül geçersiz hale gelir

Neden: S, formülde bölen konumundadır -- büyüdükçe (W+2P-K)/S küçülür, bu da pencerenin daha az konumda durup daha küçük bir çıkış ürettiği anlamına gelir.

3. "Same" padding ne anlama gelir?
  1. Padding hiç kullanılmaz
  2. Padding, çıkış boyutunun girdi boyutuyla AYNI kalmasını sağlayacak şekilde seçilir (doğru cevap)
  3. Her katmanda aynı çekirdek kullanılır
  4. Stride her zaman 1 olmalıdır

Neden: "Same" padding, S=1 iken P'yi (K-1)/2 olacak şekilde seçerek çıkış boyutunun (O) girdi boyutuyla (W) tam olarak eşit kalmasını sağlar.

Özet

Özet

  • Stride, pencerenin her adımda kaç piksel kaydığıdır -- büyüdükçe çıkış küçülür.
  • Padding, girdinin kenarlarına sıfır ekler -- çıkış boyutunu korumak (same padding) için kullanılır.
  • Padding'in ikinci faydası: kenar piksellerin, merkez pikseller kadar "görülmesini" sağlamak.
  • Çıkış boyutu formülü O = ⌊(W+2P-K)/S⌋+1, mimari tasarlarken hayati bir araçtır.
  • stride=1 + same padding, en yaygın varsayılan konfigürasyondur.
Sonraki adım: Pooling katmanları →