6  1B/2B Convolution ve Otomatik Türev (autograd)

NYU’nun bu haftaki tek sesi: Alfredo Canziani’nin Practicum’u (bu hafta ayrı Lecture yok). İki konu işliyoruz, ikisi de ‘elle anladığımız’ şeyleri PyTorch’ta somutlaştırmak: (1) convolution’ı bir projeksiyon olarak okumak, boyut aritmetiğini (\(o = n - k + 1\), 4-boyutlu 2B kernel) koda dökmek; (2) otomatik türev (autograd) — yani önceki haftalarda elle kurduğumuz backprop’un (zincir kuralı + hesaplama grafiği) PyTorch tarafından requires_grad + .backward() ile otomatik hesaplanması

NotBölüm bilgisi

6.1 Bu Derste Ne Var?

Bu hafta tek hocalı: yalnızca Alfredo Canziani’nin Practicum’u var (bu hafta ayrı bir Lecture yok). İki konu işliyoruz, ikisi de “elle anladığımız” şeyleri PyTorch’ta somutlaştırmak: (1) convolution’ın 1B/2B boyutlarını ve çıktı genişliğini koda dökmek; (2) otomatik türev (autograd) — yani Hafta 2’de LeCun’un elle kurduğu, Hafta 4’te Defazio’nun kullandığı gradient’lerin PyTorch tarafından otomatik hesaplanması.

Canziani’nin köprüsü açık: convolution bir projeksiyondur (sinyalin kernel’e hizası), ve autograd, Hafta 2’nin backprop’unun (zincir kuralı + Jacobian) “düğmeye basınca çalışan” hâlidir. Bu hafta yeni bir teori değil; önceki üç haftanın çalışan koda dönüşmesi.

Bu haftanın üç ana fikri:

  1. Convolution boyutları kuralı: her convolution çıktıyı \((k - 1)\) kadar kısaltır (\(o = n - k + 1\)); 2B kernel topluluğu 4 boyutludur.
  2. autograd = otomatik backprop. requires_grad=True ile PyTorch tüm işlemleri bir hesaplama grafiğinde izler; .backward() gradient’leri zincir kuralıyla hesaplar, .grad’a yazar.
  3. Dinamik grafik (define-by-run): PyTorch grafiği çalışma anında kurar — döngüler, koşullar serbestçe kullanılır.

flowchart TB
    subgraph Conv["(A) Convolution boyut aritmetiği (Canziani)"]
        direction LR
        Proj["Convolution = projeksiyon<br/>(sinyalin kernel'e hizası)"]
        Dim["Boyut cebiri<br/>(1B = 3 boyut · 2B = 4 boyut)"]
        Width["Output width<br/>o = n − k + 1 · padding telafi"]
        Torch["nn.Conv1d / nn.Conv2d<br/>(batch boyutu zorunlu)"]
        Proj --> Dim
        Dim --> Width
        Width --> Torch
    end

    subgraph Auto["(B) Otomatik türev — autograd (Canziani)"]
        direction LR
        Req["requires_grad = True<br/>(işlemleri izle)"]
        Graph["Hesaplama grafiği<br/>(grad_fn = üretici işlem)"]
        Back[".backward()<br/>(zincir kuralı = backprop)"]
        Grad[".grad<br/>(∂a/∂xᵢ sonucu)"]
        Dyn["Dinamik grafik<br/>(define-by-run)"]
        Req --> Graph
        Graph --> Back
        Back --> Grad
        Grad --> Dyn
    end

    Torch -. "convolution katmanını nasıl eğitiriz?" .-> Req

İpucuBuilder Notu — Çalışan Koda Dönüşüm

Geriye (önkoşul kurslar):

  • Convolution = projeksiyon → 18.06 iç çarpım/projeksiyon + Hafta 4 (Toeplitz, satır = kernel).
  • autograd = zincir kuralı → Hafta 2 backprop (Jacobian zinciri) + Calculus Ders 4 + Karpathy micrograd (_backward).
  • Output width \(o = n - k + 1\) → basit sayma; Hafta 3 stride formülünün stride=1 hâli.

İleriye (production / research):

  • autograd → tüm PyTorch eğitiminin motoru (torch.autograd); dinamik grafik, define-by-run paradigması.
  • Convolution boyut yönetimi → padding/stride ile mimari tasarımı, receptive field hesabı.

Tek cümleyle: Bu hafta convolution’ın boyut aritmetiğini ve PyTorch’un otomatik türev motorunu (autograd) öğreniyoruz — yani önceki haftaların elle kurduğu backprop’un, requires_grad + .backward() ile nasıl tek satıra indiğini.

6.2 (Canziani) Convolution = Projeksiyon

Canziani convolution’a Hafta 4’ün diliyle başlıyor: her convolution adımı, sinyalin bir parçasının kernel üzerine projeksiyonudur (normalize edilmemiş bir kosinüs/hiza değeri).

“this is going to be my projection of my input signal onto the kernel… what is the alignment of this part of the signal onto this specific subspace?” — Canziani, 1:20

Yani kernel bir “yön” (alt-uzay) tanımlar; convolution çıktısı, sinyalin o yöne ne kadar hizalı olduğunu ölçer. Çıktı yüksekse, kernel’in aradığı desen o konumda güçlüdür. Bu, Hafta 3’ün “öznitelik dedektörü” ve Hafta 4’ün “satır = kernel, çıktı = iç çarpım” görüşünün aynı fikrin devamıdır. Şekil 6.1 bu projeksiyonu somut bir 2B çizimde gösterir: gold ok kernel’in tanımladığı yönü (aranan desen / alt-uzay eksenini), violet ok sinyal yamasını çizer; kesikli dikme sinyali kernel eksenine indirir ve izdüşüm noktası — sinyalin kernel’e gölgesi — convolution çıktısının ta kendisidir.

Şekil 6.1: Convolution = projeksiyon: tek bir convolution çıktısı, sinyal yamasının kernel yönüne (aranan desene) izdüşümüdür. Gold ok kernel’i ve aradığı alt-uzay eksenini, violet ok sinyal yamasını gösterir; kesikli dikme sinyali kernel eksenine indirir ve izdüşüm noktası (sinyalin kernel’e gölgesi) çıkar. Çıktı = ⟨x, w⟩ iç çarpımı = hiza; hiza yüksekse desen vardır. Hafta 4’teki ‘satır = kernel’ okumasının devamı ve attention Q·K skorunun habercisi.
İpucuBuilder Notu — Projeksiyon = Hiza

Geriye (18.06 + Hafta 4): Projeksiyon = iç çarpım / kosinüs benzerliği (18.06); Hafta 4’ün “kernel = matrisin satırı, çıktı = satır·girdi” görüşü tam olarak bu projeksiyondur.

İleriye: “Kernel = aranan yön” görüşü, attention’daki sorgu-anahtar hizasının (\(Q \cdot K^\top\)) habercisidir (Hafta 6 ve sonrası).

6.3 (Canziani) 1B/2B Convolution ve Çok-Kanallı Kernel’ler

Canziani convolution kernel’lerinin boyut aritmetiğini açıyor. Tek bir kernel küçük bir ağırlık penceresidir; bir katman birden çok kernel tutar ve onları istifleyerek/kaydırarak uygular. Çok-kanallı durumda kernel’in bir kalınlığı (thickness) vardır = girdi kanal sayısı.

  • 1B convolution: sinyal bir boyutlu (örn. ses). \(m\) kernel, her biri (kalınlık × kernel_boyutu). Kernel topluluğu 3 boyutlu bir tensördür: (kernel sayısı × girdi kanalı × kernel boyutu).
  • 2B convolution: sinyal iki boyutlu (görüntü). Kernel topluluğu 4 boyutludur: (kernel sayısı × girdi kanalı × yükseklik × genişlik).

“what is the dimensionality of the collection of kernels used for two-dimensional data? Four.” — Canziani, 26:05

Her kernel girdinin tüm kanallarına bakar (kalınlık = girdi kanalı) ve tek bir öznitelik haritası üretir; kernel sayısı = çıktı kanal sayısı. Bu, Hafta 3’teki “her kernel bir feature map” kuralının boyutsal kesin ifadesidir. Şekil 6.2 iki paneli yan yana koyar: solda 1B kernel topluluğunun 3-eksenli tensörü, sağda 2B’nin 4-eksenli tensörü ve nn.Conv2d(20, 16, (3, 5)).weight.shape = (16, 20, 3, 5) somutlaması.

Şekil 6.2: Kernel boyut cebiri: 1B konvolüsyonda kernel tensörü 3 boyutludur (kernel sayısı × girdi kanalı × boyut), 2B konvolüsyonda 4 boyutludur (kernel sayısı × girdi kanalı × yükseklik × genişlik). Her iki durumda da kernel sayısı çıktı kanalı sayısına, kalınlık ise girdi kanalı sayısına eşittir. PyTorch’ta nn.Conv2d(20, 16, (3, 5)) ağırlık tensörünün şekli (16, 20, 3, 5) olur — yani (çıktı kanalı, girdi kanalı, H, W).
İpucuBuilder Notu — Kernel Boyut Cebiri

Geriye (Hafta 3): “Her kernel girdinin tüm kanallarına bakar, bir harita üretir” — Hafta 3’ün multi-channel kernel açıklamasının boyut-cebiri hâli.

İleriye: Bu boyutları doğru saymak, nn.Conv2d parametre sayımının ve bellek bütçesinin temelidir; mimari tasarımda kanal sayısı en kritik kapasite eksenidir.

6.4 (Canziani) Output Width: Her Convolution Boyut Kaybeder

Convolution’ın temel boyut kuralı: kernel’i kaydırırken kenarlarda yer kalmaz, dolayısıyla çıktı girdiden küçüktür. Stride 1 için, girdi boyutu \(n\) ve kernel boyutu \(k\) ise çıktı:

\[ o = n - k + 1 \]

Yani her convolution boyutu \((k - 1)\) kadar kısaltır. Canziani somut sayar: \(n = 5\), \(k = 2\) → çıktı 4; \(n = 5\), \(k = 3\) → çıktı 3.

“every time you perform a convolution you lose the dimension of the kernel minus one.” — Canziani, 17:17

Bu kayıp istenmiyorsa padding (kenarlara sıfır ekleme) ile telafi edilir — örneğin her kenara \((k-1)/2\) sıfır ekleyerek çıktı boyutu korunur. (Bu, Hafta 3’teki genel stride formülünün — \(\lfloor(n-k)/s\rfloor + 1\) — stride = 1 hâlidir.) Şekil 6.3 üstte kernel kaydırmasıyla \(o = n - k + 1\) kuralını, altta padding’in \(n = 28\), \(k = 5\) için boyutu nasıl koruduğunu somutlaştırır.

Şekil 6.3: Konvolüsyonda çıktı genişliği. ÜST: n=5 girişte kernel kaydırma — k=2 dört konum üretir (çıktı 4), k=3 üç konum (çıktı 3); genel kural o = n − k + 1, conv_output_size(5,2)=4 ve (5,3)=3 ile doğrulanır. ALT: padding telafisi — n=28, k=5 için padding olmadan çıktı 24’e düşer (k−1=4 kayıp); her kenara 2 sıfır eklenince conv_pad_output(28,5,padding=2)=28 ile boyut korunur.
İpucuBuilder Notu — Boyut Kaybı + Padding

Geriye (Hafta 3): Hafta 3’ün stride’lı çıktı formülünün özel hâli (s=1). Boyut kaybı, convolution’ın “kenar etkisi”dir.

İleriye: Derin ağlarda her katmanın boyut kaybı birikir; padding ile boyut korumak veya kasıtlı küçültmek (stride/pooling) mimari tasarımın günlük aritmetiğidir. Receptive field hesabı da bu aritmetiğe dayanır.

6.5 (Canziani) PyTorch’ta Convolution Boyutları

Canziani teoriyi nn.Conv1d / nn.Conv2d ile somutlaştırıyor. Bir convolution katmanı tanımlarken: girdi kanalı, çıktı kanalı (kernel sayısı), kernel boyutu, stride, padding verilir.

import torch
import torch.nn as nn

# 1B: 20 girdi kanali, 16 kernel (cikti kanali), kernel boyutu 3
conv1d = nn.Conv1d(in_channels=20, out_channels=16, kernel_size=3, stride=1)
print(conv1d.weight.shape)   # (16, 20, 3)  -> 3 boyutlu kernel toplulugu
print(conv1d.bias.shape)     # (16,)

# 2B: 20 girdi kanali, 16 kernel, 3x5 kernel, padding ile boyut koru
conv2d = nn.Conv2d(in_channels=20, out_channels=16, kernel_size=(3, 5),
                   stride=1, padding=(1, 2))
x = torch.randn(1, 20, 64, 224)   # (batch, kanal, yukseklik, genislik)
y = conv2d(x)                     # padding sayesinde 64x224 korunur

Kritik noktalar: kernel ağırlığı 2B convolution’da 4 boyutludur (\(16 \times 20 \times 3 \times 5\)); PyTorch her zaman bir batch boyutu bekler (tek sinyal göndersen bile (1, kanal, …) şeklinde), yoksa hata verir; padding, “her convolution boyut kaybeder” kuralını telafi etmenin yoludur.

İpucuBuilder Notu — Batch-First Tensör

Geriye (Hafta 4): conv1d.weight.shape = (16, 20, 3) tam olarak Hafta 4’ün “kernel = yapılı matris satırı” görüşünün tensör hâli; bias = afin terimi.

İleriye: “Batch boyutu zorunlu” kuralı, tüm PyTorch tensör akışının (batch-first) temelidir; padding/stride/dilation üçlüsü, receptive field ve çözünürlüğü ayarlamanın pratik kollarıdır.

6.6 (Canziani) Otomatik Türev (autograd): requires_grad ve Hesaplama Grafiği

Practicum’un ikinci yarısı autograd. Canziani şakayla başlıyor: 90’larda LSTM gradient’lerini elle türetmek zorundaydılar (sayfalar dolusu); bugün PyTorch bunu otomatik yapar.

Bir tensöre requires_grad=True verirsen, PyTorch o tensör üzerindeki tüm işlemleri bir hesaplama grafiğinde izler, böylece kısmi türevleri hesaplayabilir.

“I’m asking torch: please track all the gradient computations over the tensor, such that we can perform computation of partial derivatives.” — Canziani, 28:53

Her türetilmiş tensörün bir grad_fn’i (grad function) vardır: onu hangi işlemin ürettiğini söyler. Örneğin \(Y = X - 2\) için \(Y\)’nin grad_fn’i bir “SubBackward”dır. Bu, Hafta 2’de LeCun’un “her modülün bir backward’ı var” dediği şeyin ta kendisidir — ve Hafta 6’da göreceğimiz RNN gradient’leri de bu motorla otomatik akar. Şekil 6.4 bu hesaplama grafiğini bir DAG olarak çizer: üstte ileri geçiş (veri \(X \to a\)), altta geri geçiş (.backward() ile gradyan \(a \to X\)), her düğümün altında grad_fn etiketi.

Şekil 6.4: autograd hesaplama grafiği (DAG): X → [−2] → Y → [( )²; ×3] → Z → [mean] → a. Üst violet ok ileri geçişi (veri X→a), alt gold ok geri geçişi (.backward() ile gradyan a→X) gösterir. Her ara düğümün altındaki grad_fn etiketi (SubBackward, MulBackward/PowBackward, MeanBackward) o düğümün yerel geri-yayılım kuralını tutar — yani autograd, Hafta 2’deki Jacobian zincir kuralının otomatikleştirilmiş hâlidir ve grad_fn, micrograd’daki _backward closure’unun PyTorch karşılığıdır. Sonuç: X.grad = ∂a/∂xᵢ = 1.5·(xᵢ−2) = [−1.5, 0, +1.5, +3].
İpucuBuilder Notu — grad_fn = micrograd _backward

Geriye (Hafta 2 + Karpathy): grad_fn, Karpathy’nin micrograd’daki _backward kapanışının PyTorch karşılığıdır; hesaplama grafiği, LeCun’un “modüllerin DAG’ı” (Hafta 2) görüşüdür.

İleriye: torch.autograd, tüm derin öğrenme eğitiminin sessiz motorudur; grad_fn zincirini anlamak, bellek (retain_graph), gradient checkpointing ve hata ayıklamanın anahtarıdır.

6.7 (Canziani) Worked Example: a.backward() ve .grad

Canziani somut bir örnek yürütüyor. \(X = [1, 2, 3, 4]\) (requires_grad=True), sonra:

  • \(Y = X - 2\)
  • \(Z = 3 \cdot Y^2\)
  • \(a = \text{mean}(Z)\) (skaler)

a.backward() çağrısı, \(a\)’nın \(X\)’e göre gradient’ini zincir kuralıyla hesaplar (backprop). Elle:

\[ \frac{\partial a}{\partial x_i} = \frac{1}{4}\cdot 3\cdot 2\,(x_i - 2) = \frac{3}{2}(x_i - 2) \]

\(X = [1, 2, 3, 4]\) için bu \([-1.5, 0, 1.5, 3]\) verir — ve X.grad tam bunu içerir.

“backpropagation is how you compute the gradients; how do we train the networks — with gradients. Keep them separate!” — Canziani, 32:04

Canziani’nin uyarısı kritik: backprop = gradient hesaplama, eğitim = gradient kullanma — ikisini karıştırma. (Bir teknik not: PyTorch .grad’ı girdiyle aynı şekilde tutar; teorik Jacobian/gradient transpoze farkını pratiklik için göz ardı eder.) Şekil 6.5 bu örneği gerçek değerlerle çizer: solda ileri geçiş (\(X \to Y \to Z\), \(a = 4.5\)), sağda elle türetilen X.grad ve autograd’ın birebir aynı \([-1.5, 0, 1.5, 3]\) sonucu.

Şekil 6.5: Autograd worked example (Canziani, Bölüm 6): X=[1,2,3,4] üzerinde ileri geçiş Y=X−2 → Z=3·Y² → a=mean(Z)=4.5 ve geri yayılımla elde edilen X.grad=[−1.5, 0, 1.5, 3]. Sol panel ileri geçiş değerlerini (violet), sağ panel ∂a/∂xᵢ gradyanlarını (gold) gösterir. Gradyan elle ∂a/∂xᵢ = 1.5·(xᵢ−2) zincir kuralıyla türetilir; PyTorch autograd aynı zincir kuralını otomatik yürütür (backprop) ve birebir aynı sonucu verir.
İpucuBuilder Notu — backprop ≠ Eğitim

Geriye (Hafta 2 + 4): a.backward() = Hafta 2’nin Jacobian zinciri; “backprop ≠ eğitim” ayrımı, Hafta 4’te Defazio’nun da vurguladığı şeydir (Canziani “Aaron’un dün dediği gibi” der — Hafta 4 Defazio dersine atıf).

İleriye: .backward() + optimizer (step()) = Hafta 2’nin dört satırlık eğitim döngüsü; .grad’ın şekli ve birikimi (zero_grad) günlük hata kaynaklarıdır.

6.8 (Canziani) Dinamik Hesaplama Grafiği (Define-by-Run)

Canziani PyTorch’un ayırt edici özelliğini gösteriyor: grafik statik değil, dinamiktir. Bir örnek: \(X\)’i, normu 1000’i aşana kadar bir while döngüsünde ikiye katla. Kaç iterasyon döneceği rastgele başlangıca bağlıdır — yani hesaplama grafiği çalışma anında, koda göre kurulur (define-by-run).

Bu, normal Python kontrol akışını (döngü, koşul) modelin içinde serbestçe kullanabilmen demektir; autograd yine de doğru gradient’i hesaplar çünkü grafiği sen çalıştırdıkça örer. Şekil 6.6 üç farklı rastgele başlangıç için döngünün farklı sayıda iterasyon döndüğünü ve böylece farklı uzunlukta grafik zincirleri doğduğunu gösterir.

Şekil 6.6: Dinamik grafik (define-by-run): hesap grafiği çalışma anında, kodun akışına göre kurulur. while X.norm() < 1000: X = X * 2 döngüsü üç farklı rastgele başlangıç için (‖X‖ = 332.6, 37.9, 4.2) farklı sayıda iterasyonda 1000 eşiğini aşar — sırasıyla 2, 5 ve 8 kez ikiye katlama — ve bu yüzden farklı uzunlukta (3, 6, 9 düğümlü) grafik zincirleri doğar. Her kutu o adımdaki ‖X‖ değerini, her ok ×2 işlemini, gold kutu eşiği aşan son düğümü gösterir. Python döngü/koşulun model içinde serbestçe çalışabilmesi tam da değişken-uzunluklu hesaba (Hafta 6 RNN) kapı açar; statik grafikte (define-then-run) bu mümkün değildir.
İpucuBuilder Notu — Define-by-Run

Geriye (Hafta 2): Hafta 2’de LeCun “döngü varsa grafik üretimi karmaşıklaşır” demişti; PyTorch’un dinamik grafiği bunu doğal çözer — her ileri geçişte grafiği yeniden kurar.

İleriye: Define-by-run, PyTorch’u araştırmada esnek kılan şeydir (RNN’ler, değişken-uzunluk diziler — Hafta 6); buna karşılık statik grafikler (eski TensorFlow, torch.compile/torch.jit) hız/optimizasyon için grafiği önceden dondurur.

6.9 Bu Dersin Özeti

  1. Convolution = projeksiyon: sinyalin kernel’e (aranan yöne) hizası.
  2. Boyut aritmetiği: 1B kernel topluluğu 3 boyutlu, 2B 4 boyutlu (kernel sayısı × girdi kanalı × [yükseklik ×] genişlik); kernel sayısı = çıktı kanalı.
  3. Output width: \(o = n - k + 1\) (stride 1); her convolution \((k-1)\) boyut kaybeder; padding telafi eder.
  4. PyTorch: nn.Conv1d/2d(in, out, kernel_size, stride, padding); batch boyutu zorunlu.
  5. autograd: requires_grad=True ile işlemler hesaplama grafiğinde izlenir; grad_fn üretici işlemi tutar.
  6. .backward() = backprop: gradient’i zincir kuralıyla hesaplar, .grad’a yazar. backprop ≠ eğitim.
  7. Dinamik grafik (define-by-run): grafik çalışma anında kurulur; döngü/koşul serbest.
ÖnemliTek Bir Cümle

Bu hafta convolution’ın boyut aritmetiğini (\(o = n - k + 1\), 4-boyutlu 2B kernel) ve PyTorch’un autograd motorunu öğrendik — requires_grad + .backward(), Hafta 2’de LeCun’un elle kurduğu Jacobian zincirini tek satıra indirir, ve dinamik grafik sayesinde bunu döngü/koşul içeren her kodda yapar.

6.10 Kontrol Soruları

Cevap: Çıktı boyutu:

\[ o = n - k + 1 = 28 - 5 + 1 = 24 \]

Genel kural: her convolution çıktıyı \((k - 1)\) kadar kısaltır (Canziani 17:17). Boyutu korumak için padding eklersin — her kenara \((k-1)/2 = 2\) sıfır eklersen çıktı yine 28 olur. (Bu, Hafta 3’ün \(\lfloor(n-k)/s\rfloor+1\) formülünün s=1 hâlidir.)

Cevap: 4 boyutlu (Canziani 26:05): (kernel sayısı × girdi kanalı × yükseklik × genişlik). Kernel sayısı = çıktı kanal sayısı; girdi kanalı = kernel’in “kalınlığı” (her kernel girdinin tüm kanallarına bakar); yükseklik × genişlik = uzamsal pencere. PyTorch’ta nn.Conv2d(20, 16, (3,5)).weight.shape = (16, 20, 3, 5). Ayrıca PyTorch her zaman bir batch boyutu bekler (girdi: batch × kanal × H × W).

Cevap: requires_grad=True, PyTorch’a o tensör üzerindeki tüm işlemleri bir hesaplama grafiğinde izlemesini söyler, böylece kısmi türevler hesaplanabilir (Canziani 28:53). grad_fn, türetilmiş bir tensörü hangi işlemin ürettiğini tutar (örn. \(Y = X - 2\) için SubBackward) — Karpathy micrograd’ın _backward’ının karşılığı. .backward() = backprop = gradient’leri hesaplama (zincir kuralı, .grad’a yazar); eğitim = bu gradient’leri kullanıp parametreyi güncelleme (optimizer.step). Canziani: “ikisini karıştırma” (32:04).

Cevap: \(a = (1/4)\sum 3(x_i - 2)^2\). Zincir kuralı:

\[ \frac{\partial a}{\partial x_i} = \frac{1}{4}\cdot 3\cdot 2\,(x_i - 2) = \frac{3}{2}(x_i - 2) \]

\(X = [1,2,3,4]\) için: $[1.5(-1), 1.5, 1.5, 1.5] = $ [−1.5, 0, 1.5, 3]. X.grad tam bunu içerir — autograd, elle yaptığımız zincir kuralını otomatik yürütür. (PyTorch .grad’ı girdiyle aynı şekilde tutar.)

6.11 Egzersizler

Egzersiz 1 (Boyut aritmetiği). Bir 32×32 görüntüye art arda üç nn.Conv2d(kernel_size=3, padding=0) uygula. Her katmandan sonra uzamsal boyut ne olur? padding=1 ile tekrar dene — fark nedir? Formül \(o = n - k + 1\) ile önceden tahmin et.

import torch
import torch.nn as nn

x = torch.randn(1, 3, 32, 32)               # (batch, kanal, H, W)
net_nopad = nn.Sequential(
    nn.Conv2d(3, 8, 3), nn.Conv2d(8, 8, 3), nn.Conv2d(8, 8, 3))
net_pad = nn.Sequential(
    nn.Conv2d(3, 8, 3, padding=1),
    nn.Conv2d(8, 8, 3, padding=1),
    nn.Conv2d(8, 8, 3, padding=1))
print(net_nopad(x).shape)                   # 32 -> 30 -> 28 -> 26
print(net_pad(x).shape)                     # padding=1 -> 32 korunur

Egzersiz 2 (Kernel şekli). nn.Conv2d(3, 64, kernel_size=7) katmanının .weight.shape ve .bias.shape’ini önce tahmin et, sonra yazdırıp doğrula. Toplam parametre sayısını hesapla.

import torch
import torch.nn as nn

conv = nn.Conv2d(3, 64, kernel_size=7)
print(conv.weight.shape)                    # (64, 3, 7, 7)
print(conv.bias.shape)                      # (64,)
params = 64 * 3 * 7 * 7 + 64                 # ağırlık + bias
print(params)                               # 9472

Egzersiz 3 (autograd worked example). X = torch.tensor([1.,2.,3.,4.], requires_grad=True) ile Y=X−2, Z=3*Y**2, a=Z.mean(); a.backward() çağır ve X.grad’ı yazdır. [−1.5, 0, 1.5, 3] çıktığını ve elle türevle eştiğini doğrula.

import torch
X = torch.tensor([1., 2., 3., 4.], requires_grad=True)
Y = X - 2
Z = 3 * Y ** 2
a = Z.mean()
a.backward()
print(X.grad)                               # tensor([-1.5000, 0.0000, 1.5000, 3.0000])
# elle: da/dxi = (1/4)*3*2*(xi-2) = 1.5*(xi-2)

Egzersiz 4 (grad_fn zinciri). Yukarıdaki Y, Z, a tensörlerinin .grad_fn’lerini yazdır. Hangi işlemleri görüyorsun (Sub, Mul, Mean)? Bu zincirin Hafta 2’nin Jacobian zinciriyle ilişkisini açıkla.

import torch
X = torch.tensor([1., 2., 3., 4.], requires_grad=True)
Y = X - 2;  Z = 3 * Y ** 2;  a = Z.mean()
print(Y.grad_fn)                            # <SubBackward0>
print(Z.grad_fn)                            # <MulBackward0>
print(a.grad_fn)                            # <MeanBackward0>
# her grad_fn = o işlemin yerel Jacobian'i (Hafta 2 zincir kurali halkasi)

Egzersiz 5 (Hafta 6 habercisi — diziler). Şimdiye kadar girdiler sabit boyutluydu (görüntü, vektör). Bir cümle ise değişken uzunlukta bir dizidir (“film iyiydi” 2 kelime, “film başından sonuna kadar harikaydı” 5 kelime). (a) Sabit-girdili bir ağa değişken uzunlukta diziyi nasıl verirsin — naif bir fikir öner ve neden yetersiz olduğunu açıkla. (b) Dinamik hesaplama grafiği (Bölüm 7), değişken-uzunluk dizileri işlemek için neden uygundur? Bu, Hafta 6’da RNN ve attention’a geçişi motive eder.

# (a) naif fikir: tum cumleleri sabit L uzunluga pad/truncate et
#     -> kisa cumlede bos token israfi, uzun cumlede bilgi kaybi
# (b) dinamik grafik: her cumle icin grafik o cumlenin uzunluguna gore
#     calisma aninda kurulur -> degisken-uzunluk dogal (Hafta 6 RNN/attention)
sentences = [["film", "iyiydi"],
             ["film", "basindan", "sonuna", "kadar", "harikaydi"]]
for s in sentences:
    print(len(s))                           # 2, 5 -> farkli uzunluk

6.12 Sonraki Ders İçin Hazırlık

UyarıSonraki Hafta — H6: Diziler — RNN, LSTM ve Attention

Sabit boyuttan değişken uzunluğa. Bu haftaya kadar sabit boyutlu girdilerle (görüntü, vektör) çalıştık. Hafta 6’da değişken uzunlukta dizilere (metin, ses, zaman serisi) geçiyoruz: LeCun RNN ve attention’ı, Canziani PyTorch’ta dizi eğitimini gösterecek. Bu haftanın dinamik hesaplama grafiği (define-by-run) tam da bu değişken-uzunluk dünyasının altyapısıdır — Egzersiz 3-4 (autograd) ve Egzersiz 5 (dizi problemi) tam bu derse hazırlar.

Hafta 6: Diziler — RNN, LSTM ve Attention — LeCun (Lecture) + Canziani (Practicum)

Bu haftaya kadar sabit boyutlu girdilerle (görüntü, vektör) çalıştık. Hafta 6’da değişken uzunlukta dizilere (metin, ses, zaman serisi) geçiyoruz: LeCun RNN ve attention’ı, Canziani PyTorch’ta dizi eğitimini gösterecek. Dinamik hesaplama grafiği (bu hafta) tam da bu değişken-uzunluk dünyasının altyapısıdır.

Hafta 6 öncesi yapılacak:

  • Egzersiz 3-4 (autograd) ve Egzersiz 5 (dizi problemi sezgisi) çöz.
  • “autograd = otomatik backprop (zincir kuralı + hesaplama grafiği)” cümlesini kendi sözcüklerinle yaz.
  • Hafta 2-4-5 üçlüsünü bağla: backprop’u elle kurduk (2), kullandık (4), otomatikleştirdik (5).

6.13 Anahtar Kavramlar (Cheat Sheet)

Kavram Tanım Hoca / timestamp
Convolution = projeksiyon Sinyalin kernel’e (aranan yöne) hizası Canziani 1m20
1B kernel topluluğu 3 boyutlu: kernel sayısı × girdi kanalı × boyut Canziani 12m37
2B kernel topluluğu 4 boyutlu: kernel × kanal × yükseklik × genişlik Canziani 26m05
Output width \(o = n - k + 1\); her conv \((k-1)\) kaybeder Canziani 17m17
Padding Kenara sıfır ekleyip boyut koruma Canziani 25m20
Batch boyutu zorunlu PyTorch girdisi batch × kanal × uzamsal Canziani 26m50
requires_grad İşlemleri hesaplama grafiğinde izle Canziani 28m53
grad_fn Tensörü üreten işlem (örn. SubBackward) Canziani 29m22
.backward() Backprop = gradient hesapla; .grad’a yaz Canziani 32m04
backprop ≠ eğitim Backprop gradient hesaplar; eğitim onu kullanır Canziani 32m16
Dinamik grafik Define-by-run; grafik çalışma anında kurulur Canziani 37m43

6.14 ML Builder Bağlantıları

Geriye köprüler (önkoşul kurslar):

  1. Convolution = projeksiyon → 18.06 iç çarpım + Hafta 4 (satır = kernel).
  2. autograd = zincir kuralı → Hafta 2 backprop (Jacobian) + Calculus Ders 4 + Karpathy _backward.
  3. grad_fn = modül backward → Hafta 2 “her modülün bir backward’ı var”.
  4. Output width → Hafta 3 stride formülü (s=1).
  5. backprop ≠ eğitim → Hafta 4 Defazio (aynı uyarı).

İleriye köprüler (production / research):

  1. autograd → torch.autograd, retain_graph, gradient checkpointing.
  2. Dinamik grafik → RNN/değişken-uzunluk (Hafta 6); torch.compile (statik optimizasyon).
  3. Convolution boyut yönetimi → padding/stride/dilation, receptive field hesabı.
  4. Batch-first tensör → tüm PyTorch veri hattı.
ÖnemliBu dersten tek bir şey alıp gideceksen

PyTorch’un autograd’ı sihir değildir — requires_grad=True tüm işlemleri bir hesaplama grafiğinde izler, .backward() ise Hafta 2’de LeCun’un elle kurduğu zincir kuralını (Jacobian zinciri) otomatik yürütüp .grad’a yazar; convolution boyutları ise basit bir aritmetiktir (\(o = n - k + 1\)). Backprop’u önce elle anladık (Hafta 2), sonra kullandık (Hafta 4), şimdi de PyTorch’a otomatik yaptırıyoruz — ve dinamik grafik, bunu döngü/koşul içeren her kodda mümkün kılarak bizi değişken-uzunluk dizilere (Hafta 6) hazırlıyor.