Reverse-mode vs Forward-mode Autodiff: JVP, VJP, Dual Numbers ve LLM'de Hangisi Ne Zaman
Otomatik türevin iki temel modu: forward-mode (Jacobian-vector product, dual numbers) ve reverse-mode (vector-Jacobian product, backprop). Matematiksel karşılaştırma, hesaplama karmaşıklığı, JAX'te jvp/vjp/grad/hessian, LLM'de hangi senaryo hangi modu gerektirir.
Şükrü Yusuf KAYA
55 dakikalık okuma
İleri🔄 Backprop'un kardeşi forward-mode
Her LLM mühendisi backprop'u (reverse-mode) bilir. Ama autodiff'in iki modu olduğunu, ve forward-mode'un da spesifik senaryolarda kullanıldığını çok azı bilir. 55 dakika sonra: JVP ve VJP'in ne demek olduğunu, JAX'in jvp/vjp/grad/hessian/jacfwd/jacrev API'larını, ve neden Hessian-vector products için forward-mode'un kritik olduğunu kavrayacaksın. Bu, advanced ML araştırmacılarının cephaneliği.
Ders Haritası (Detaylı)#
- Sembolik, numerik, otomatik türev karşılaştırması
- Forward-mode: Dual numbers ile sezgi
- Reverse-mode: Backprop'un genel hali
- Jacobian'ın anatomisi: tam matris vs implicit
- JVP (Jacobian-vector product) — forward-mode'un kalbi
- VJP (vector-Jacobian product) — reverse-mode'un kalbi
- Hesaplama karmaşıklığı: hangisi ne zaman ucuz
- JAX API: jvp, vjp, grad, jacfwd, jacrev, hessian
- Hessian-vector products: forward-of-reverse trick
- Higher-order autodiff: 2., 3. türevler
- LLM uygulamaları: Newton method, K-FAC, Fisher info
- Pratik: PyTorch'ta forward-mode ()
torch.func
1. Türev Hesaplama Yöntemleri — Üç Aile#
Bir fonksiyonun türevini hesaplamanın üç yolu var:
a) Sembolik türev (analytic)#
Calculus kurallarını formelle uygula:
, .
d/dx (x²) = 2xd/dx (sin x) = cos xAraçlar: SymPy, Mathematica, Maple.
Avantajlar:
- Tam doğru (yuvarlama yok)
- Formülü tekrar kullanılabilir
Dezavantajlar:
- Expression swell: karmaşık fonksiyonun türevi exponential olarak büyür
- Conditional ve loop'lar ile uyumsuz
- NN'lerde imkansız (milyarlarca operasyon)
b) Numerik türev (finite differences)#
Avantajlar:
- Genel (her fonksiyonda çalışır)
- Implementasyon trivial
Dezavantajlar:
- Truncation error (O(h²))
- Round-off error (h çok küçükse FP precision kaybedilir)
- n parametre için n+1 fonksiyon evaluation → O(n) maliyet
- Genelde gradient check için kullanılır, gerçek hesap için değil
c) Otomatik türev (autodiff)#
İkisinin de güçlü yanlarını birleştir:
- Tam doğru (sembolik gibi, çünkü chain rule'u tam uygular)
- Hesaplanabilir (sembolik expression swell yok)
- Conditional, loop, recursion ile uyumlu
- O(N) maliyet (N = operasyon sayısı)
Autodiff'in iki modu:
- Forward-mode (tangent-mode)
- Reverse-mode (adjoint-mode, backprop'un genel hali)
python
import numpy as npimport sympy as sp # 1. Sembolikx_sym = sp.Symbol('x')f_sym = sp.sin(x_sym) * sp.exp(x_sym)df_sym = sp.diff(f_sym, x_sym)print("Sembolik f'(x):", df_sym)# cos(x)*exp(x) + sin(x)*exp(x)f_at_2 = float(df_sym.subs(x_sym, 2.0))print(f"f'(2) sembolik = {f_at_2:.6f}") # 2. Numerik (finite difference)def f(x): return np.sin(x) * np.exp(x) h = 1e-5df_num = (f(2.0 + h) - f(2.0 - h)) / (2 * h)print(f"f'(2) numerik = {df_num:.6f}") # 3. Otomatik türev (JAX ile)import jaximport jax.numpy as jnp def f_jax(x): return jnp.sin(x) * jnp.exp(x) df_auto = jax.grad(f_jax)(2.0)print(f"f'(2) autodiff = {df_auto:.6f}") # Hepsi aynı değer — ama performans karakteristikleri çok farklıÜç türev metodu yan yana — aynı sonuç, farklı doğa.
2. Forward-mode: Dual Numbers ile Sezgi#
Dual numbers kavramı (Clifford 1873): bir gerçek sayıyı bir infinitesimal ile genişlet.
burada (nilpotent). = primal değer, = tangent (türev) değer.
ε² = 0xẋAritmetik kuralları#
(x + ε ẋ) + (y + ε ẏ) = (x + y) + ε(ẋ + ẏ) (x + ε ẋ) * (y + ε ẏ) = xy + ε(ẋy + xẏ) [çünkü ε² = 0]
Bu çarpım kuralına bak: 'nin katsayısı tam olarak çarpım türevi .
ε(fg)' = f'g + fg'Sezgi#
Her dual number aslında "x'in değeri + x'in türevi"ni birlikte taşıyor. Forward'da operasyonlar yapıldıkça, dual aritmetik otomatik olarak chain rule'u uyguluyor.
(x, ẋ)Örnek#
f(x) = x² + sin(x)f'(2)İlk: x̂ = 2 + ε·1 x̂² = (2 + ε)² = 4 + 4ε + ε² = 4 + 4ε sin(x̂) = sin(2) + ε·cos(2) f(x̂) = (4 + 4ε) + (sin(2) + ε cos(2)) = (4 + sin(2)) + ε(4 + cos(2)) f(2) = 4 + sin(2) ≈ 4.909 f'(2) = 4 + cos(2) ≈ 3.584
Bu kadar. Tek bir forward pass'te hem değer hem türev.
python
import math class Dual: """Dual number for forward-mode autodiff.""" def __init__(self, primal, tangent=0.0): self.p = primal # değer self.t = tangent # türev def __repr__(self): return f"Dual(primal={self.p}, tangent={self.t})" def __add__(self, other): if isinstance(other, Dual): return Dual(self.p + other.p, self.t + other.t) return Dual(self.p + other, self.t) def __mul__(self, other): if isinstance(other, Dual): # (x + ε ẋ)(y + ε ẏ) = xy + ε(ẋy + xẏ) return Dual(self.p * other.p, self.t * other.p + self.p * other.t) return Dual(self.p * other, self.t * other) def __pow__(self, n): # d/dx x^n = n x^(n-1) return Dual(self.p ** n, n * self.p ** (n - 1) * self.t) def __radd__(self, other): return self + other def __rmul__(self, other): return self * other def sin(x): if isinstance(x, Dual): return Dual(math.sin(x.p), math.cos(x.p) * x.t) return math.sin(x) def cos(x): if isinstance(x, Dual): return Dual(math.cos(x.p), -math.sin(x.p) * x.t) return math.cos(x) # Kullanım: x̂ = 2 + ε·1, türevi hesaplax = Dual(2.0, 1.0) # tangent=1 → "x'e göre türev al"y = x ** 2 + sin(x)print(y) # Dual(primal=4.909..., tangent=3.584...)print(f"f(2) = {y.p:.6f}")print(f"f'(2) = {y.t:.6f}") # Doğrulama: f'(x) = 2x + cos(x) → f'(2) = 4 + cos(2) ≈ 3.584print(f"Beklenen: {2*2 + math.cos(2):.6f}")Dual numbers ile forward-mode autodiff — 40 satır.
💡 Dual numbers'ın güzel sırrı
Forward-mode autodiff aslında algebra'da bir trick. ε² = 0 olduğu için, ε katsayısı her zaman türev oluyor. Karmaşık fonksiyonları parçalara ayırıp aritmetik yapmak yeter — chain rule otomatik uygulanıyor. Bu, sembolik türev (formül) ile numerik türev (FD) arasında bir köprü.
3. Reverse-mode: Backprop'un Genel Hali#
Reverse-mode, computational graph'i iki kez geçiyor:
- Forward pass: değerleri hesapla, ara aktiviteleri sakla
- Backward pass: gradient'leri output'tan input'a doğru "geri" yay
Bu Ders 1.3, 1.4'te detaylıca işledik. Ana noktalar:
- Topological sort + reverse traversal
- Her node'da lokal türev (closure)
_backward - Gradient accumulation ()
+=
Forward vs Reverse: Mental model#
Forward: "Bu input'u değiştirseydim, tüm output'lar nasıl değişirdi?"
Reverse: "Bu output'u kabul edip, tüm input'lar nasıl değiştirir?"
LLM eğitimi tek bir output (loss) ve milyarlarca input (parametre) → reverse-mode çok daha verimli.
Image classification 1 loss, milyon parametre → reverse-mode.
Sensitivity analysis (1 input → çok output) → forward-mode.
4. Jacobian'ın Anatomisi#
f: ℝⁿ → ℝᵐTam Jacobian saklamak#
Bir LLM için = milyarlar, = 1 (loss). Jacobian = "gradient vektörü". Pratikte saklanabilir.
nm1 × nBir neural network'ün bir ara katmanı için (örn. hidden states), ve her ikisi de büyük (say milyonlar). Jacobian matrisi terabytes alabilir → asla saklanmaz.
mnm × nÇözüm: Jacobian'ı implicit tut#
Tam Jacobian yerine, sadece Jacobian × vektör (veya vektör × Jacobian) operasyonlarını yapabiliriz. Bu çok daha ucuz.
Forward-mode: (Jacobian-vector product = JVP)
Reverse-mode: (vector-Jacobian product = VJP)
J · vv^T · J5. JVP — Jacobian-Vector Product (Forward-mode'un Kalbi)#
JVP hesaplar: bir input 'ye doğru yöndeki directional derivative.
vSezgi: x'i v yönünde küçük bir adım hareket ettirsem, f kaç değişir?
Pratik#
- Dual numbers: ẋ = v ile primal'i forward'a sürmek = JVP
- m output, n input için 1 JVP = O(N) (N = op count)
- m JVP ile tam Jacobian'ı yeniden kurabilirsin (m kez çağır, m kolon)
Niye forward-mode "Jacobian-vector product"?#
Çünkü forward-mode bir kez çalıştırıldığında her output için bir kolon Jacobian'ı (yani = i. kolon) verir. Yani temel operasyon JVP.
J · e_i6. VJP — Vector-Jacobian Product (Reverse-mode'un Kalbi)#
VJP hesaplar: bir cotangent ile Jacobian'ın sol-çarpımı.
uSezgi: f'in output'una u yönlü bir "sensitivity" verirsen, input'lara karşılık hangi türev?
Pratik#
- Backward pass: gradient'i output'tan input'a doğru aktarır
- LLM loss (m=1, scalar) için →
u = 1(gradient vector)1^T · J = ∇L - n VJP ile tam Jacobian'ı yeniden kurabilirsin (n kez çağır, n satır)
Niye reverse-mode "vector-Jacobian product"?#
Çünkü backward bir kez çalıştırıldığında her input için bir satır Jacobian'ı (yani = i. satır) verir. Temel operasyon VJP.
e_i^T · J7. Hesaplama Karmaşıklığı — Hangisi Ne Zaman Ucuz#
Bir fonksiyon için:
f: ℝⁿ → ℝᵐTam Jacobian fiyatı#
| Yöntem | Maliyet |
|---|---|
| Forward-mode (n kez JVP) | O(n · N) |
| Reverse-mode (m kez VJP) | O(m · N) |
N = operasyon sayısı (forward pass maliyeti).
Kural#
n < m → Forward-mode ucuz m < n → Reverse-mode ucuz
LLM bağlamında#
| Senaryo | n | m | Doğru mod |
|---|---|---|---|
| Loss → parametreler (gradient) | büyük (M-B) | 1 | Reverse ← LLM'in günlük işi |
| 1 input → çok output (sensitivity) | 1 | büyük | Forward |
| Hidden state → input gradient | M | M | Eşit — fonksiyonun yapısına bağlı |
| Hessian (gradient of gradient) | M | M | Karışık (aşağıda) |
Reverse-mode'un memory tradeoff'u#
Forward-mode'da memory: O(1) (sadece dual taşıyorsun).
Reverse-mode'da memory: O(N) — tüm ara aktiviteleri saklamalısın.
Bu yüzden büyük LLM'lerde:
- Reverse-mode ← gradient için zorunlu
- Activation checkpointing ile memory dengelenir
python
# Karşılaştırma: 100-input, 1-output (typical loss)import jaximport jax.numpy as jnpimport time def loss_fn(x): return jnp.sum(jnp.sin(x) ** 2 + x ** 2) n = 100x = jnp.array([0.5] * n) # Reverse-mode (grad): 1 VJP, O(N)grad_rev = jax.grad(loss_fn)t0 = time.perf_counter()g = grad_rev(x)t1 = time.perf_counter()print(f"Reverse-mode (grad): {(t1-t0)*1e6:.1f}μs, grad shape: {g.shape}") # Forward-mode (n kez JVP): O(n·N)def forward_grad(f, x): """Forward-mode ile gradient — n kez JVP.""" grad = jnp.zeros_like(x) for i in range(len(x)): v = jnp.zeros_like(x).at[i].set(1.0) _, jvp_i = jax.jvp(f, (x,), (v,)) grad = grad.at[i].set(jvp_i) return grad t0 = time.perf_counter()g_fwd = forward_grad(loss_fn, x)t1 = time.perf_counter()print(f"Forward-mode (n JVPs): {(t1-t0)*1e6:.1f}μs") # n=100 → forward 100x yavaş# n=10^9 (LLM) → forward imkansız # Tersi senaryo: 1 input, 100 outputdef multi_output(x): return jnp.array([jnp.sin(x * i) for i in range(100)]) # Forward: 1 JVP (1 input)y, jvp_val = jax.jvp(multi_output, (0.5,), (1.0,))print(f"Forward 1 JVP for m=100: instant") # Reverse: 100 kez VJP (her output için)# Çok daha yavaşKarmaşıklık karşılaştırması — hangi mod ne zaman.
8. JAX API — Otomatik Türev Master Kit#
JAX, autodiff'in tam ailesini en temiz API'lerle sunuyor:
Temel#
| Fonksiyon | Ne yapıyor |
|---|---|
jax.grad(f) | Reverse-mode gradient (scalar output için) |
jax.jvp(f, primals, tangents) | Tek bir JVP |
jax.vjp(f, *primals) | VJP fonksiyonu döndürür |
jax.jacfwd(f) | Forward-mode ile tam Jacobian (n JVP) |
jax.jacrev(f) | Reverse-mode ile tam Jacobian (m VJP) |
jax.hessian(f) | Hessian (jacfwd(grad(f)) = forward-of-reverse) |
Higher-level#
| Fonksiyon | Ne yapıyor |
|---|---|
jax.value_and_grad(f) | Hem değer hem gradient (efficient — tek pass) |
jax.vmap(f) | Vectorize (batch axis ekle) |
jax.pmap(f) | Parallel (multi-device) |
Karpathy önerisi#
"Eğer JAX bilseydim, çoğu deep learning projemde PyTorch yerine JAX seçerdim — çünkü autodiff API'si tam ve ortogonal."
python
import jaximport jax.numpy as jnp # Test functiondef f(x): return jnp.sin(x[0]) * jnp.cos(x[1]) + x[2] ** 2 x = jnp.array([1.0, 2.0, 3.0]) # 1. Gradient (reverse-mode)grad = jax.grad(f)print("grad:", grad(x)) # ∇f at x# array([0.4161..., -0.4546..., 6.0]) # 2. Value + Gradient (tek pass)val, gr = jax.value_and_grad(f)(x)print(f"f(x) = {val:.4f}, ∇f(x) = {gr}") # 3. JVP: f(x + ε v) ≈ f(x) + ε · J·vv = jnp.array([1.0, 0.0, 0.0]) # x[0] yönünde tangenty, jvp_val = jax.jvp(f, (x,), (v,))print(f"f(x) = {y:.4f}, JVP·v = {jvp_val:.4f}")# JVP·v = ∂f/∂x[0] = cos(1)·cos(2) ≈ 0.416 # 4. VJP: u^T · Jy, vjp_fn = jax.vjp(f, x)u = 1.0 # scalar output içingrad_via_vjp = vjp_fn(u)print(f"VJP grad: {grad_via_vjp[0]}") # 5. Jacobian (forward vs reverse) — multi-outputdef g(x): return jnp.array([x[0]**2, x[1] * x[2], jnp.sin(x[0])]) J_fwd = jax.jacfwd(g)(x) # 3 input, 3 output → 3x3 JacobianJ_rev = jax.jacrev(g)(x)print("Forward Jacobian:")print(J_fwd)print("Reverse Jacobian:")print(J_rev)print("Aynı mı:", jnp.allclose(J_fwd, J_rev)) # True # 6. HessianH = jax.hessian(f)(x)print("Hessian:")print(H) # 3x3 symmetricJAX'in autodiff API'sinin tam keşfi.
9. Hessian-Vector Products — Forward-of-Reverse Trick#
Modern ML'de tam Hessian asla hesaplanmaz (n × n, milyonlarca). Ama bazı algoritmalar (Newton method, K-FAC, conjugate gradient) Hessian-vector products kullanır:
Klasik yol: forward-over-reverse#
- Reverse-mode ile gradient hesapla:
g = ∇f - Forward-mode ile gradient'in JVP'sini al:
H·v = JVP(g, x, v)
Bu kombinasyon veya + ile yapılır.
jvp(grad(f))jax.jvpjax.gradReverse-over-reverse alternatif#
Aynı şey, ama iki kere reverse: . Daha yavaş ama mümkün.
grad(grad(f))^T · vNiye forward-of-reverse daha iyi?#
Reverse forward'dan daha pahalı memory-wise. Gradient hesabı zaten reverse, sonra üzerine forward ekleyince ekstra memory ihtiyacı yok.
Pratik: Conjugate Gradient#
CG için kullanılır:
H · vv_k+1 = v_k - α · (H · v_k)
Tam H gerek yok, sadece HVP.
python
import jaximport jax.numpy as jnp def f(x): return jnp.sum(x ** 4) + jnp.sum(jnp.sin(x) ** 2) x = jnp.array([1.0, 2.0, 3.0, 4.0])v = jnp.array([1.0, 0.0, 1.0, 0.0]) # bazı yönlerde # Hessian-vector product — forward-of-reversedef hvp(f, x, v): """H(f, x) · v — tam Hessian saklamadan.""" return jax.jvp(jax.grad(f), (x,), (v,))[1] h_v = hvp(f, x, v)print("H·v:", h_v) # Doğrulama: tam Hessian'laH = jax.hessian(f)(x)h_v_direct = H @ vprint("H @ v (direct):", h_v_direct)print("Aynı mı:", jnp.allclose(h_v, h_v_direct)) # Karmaşıklık: HVP O(N), tam Hessian O(N²)# n=1000 için: HVP ~10μs, tam Hessian ~10ms (1000x fark)Hessian-vector product — modern optimization'ın dayanağı.
10. Higher-order Autodiff: 2., 3. Türevler#
JAX'te higher-order trivially: , , ...
grad(grad(f))grad(grad(grad(f)))PyTorch'ta da mümkün ama dikkat: .
backward(create_graph=True)Use case'ler#
- Newton method: 2. derecede optimization —
H⁻¹·∇f - MAML (meta-learning): 2. derecede gradient (gradient'in türevi)
- Physics-informed NN: PDE residual'lerinde 2. derecede türevler
- Sharpness-aware optimization (SAM): gradient'in gradient'i
Pratik uyarı#
Higher-order pahalı. 2. derecede iki kez backward → ~2-3x maliyet, ~2x memory. 3. derecede daha fazla. LLM'de nadir kullanılır (Newton method LLM ölçeğinde pratik değil).
11. LLM'de Forward-mode Uygulamaları#
Forward-mode klasik LLM eğitiminde yer almaz (m=1, n çok büyük → reverse default). Ama edge case'lerde kullanılır:
a) Hessian-vector products#
K-FAC, Shampoo, Newton-CG gibi 2. derece optimizer'lar HVP gerektirir → forward-of-reverse.
b) Fisher Information Matrix vector products#
Natural gradient için . FIM, gradient'in outer product expectation'ı; HVP gibi hesaplanır.
F⁻¹ · ∇Lc) Influence functions#
"Bu test örneğinin tahmininden hangi eğitim örneği en sorumlu?" sorusu için (Koh & Liang 2017): . HVP-based.
-H⁻¹ · ∇ training_loss · ∇ test_lossd) Adversarial training (Lipschitz)#
Robustness analysis'inde Jacobian normları gerekli → forward-mode efficient (input genelde küçük).
e) Diffusion models (score matching)#
∇_x log p(x)f) Physics-informed NN (PINN)#
PDE constraint'leri için input'a göre 2-3 derecede türev — forward-mode genelde tercih edilir.
12. PyTorch'ta Forward-mode — torch.func#
torch.funcPyTorch 2.0 öncesi forward-mode eksikti. Şimdi modülü (eski functorch) JAX-vari API getiriyor:
torch.funcimport torch from torch.func import grad, jvp, vjp, jacfwd, jacrev, hessian, vmap def f(x): return torch.sin(x[0]) * torch.cos(x[1]) + x[2] ** 2 x = torch.tensor([1.0, 2.0, 3.0]) # Reverse-mode gradient g = grad(f)(x) print(g) # Forward-mode Jacobian J = jacfwd(f)(x) print(J)
torch.autograd.functional (eski API)#
torch.autograd.functionalPyTorch 1.x'te benzer ama less ergonomic. Modern PyTorch için öner.
torch.funcpython
import torchfrom torch.func import grad, jvp, vjp, hessian, vmap # Bir mini transformer'ın forward pass'i (toy)def mini_attention(qkv_weights, x): """qkv_weights: (3 * d_model, d_model), x: (seq, d_model)""" d = x.shape[-1] qkv = x @ qkv_weights.T # (seq, 3*d) q, k, v = qkv.chunk(3, dim=-1) scores = q @ k.T / (d ** 0.5) attn = torch.softmax(scores, dim=-1) return (attn @ v).sum() # scalar loss # Test datatorch.manual_seed(0)d_model = 8seq_len = 4W = torch.randn(3 * d_model, d_model, requires_grad=True)x = torch.randn(seq_len, d_model) # Gradient w.r.t. W (reverse-mode — gradient için doğru seçim)grad_W = grad(lambda W: mini_attention(W, x))(W)print(f"grad shape: {grad_W.shape}") # Hessian-vector productv = torch.randn_like(W)hv = jvp(grad(lambda W: mini_attention(W, x)), (W,), (v,))[1]print(f"HVP shape: {hv.shape}") # vmap ile batched gradientbatch_x = torch.randn(16, seq_len, d_model)batched_grad = vmap(lambda x_b: grad(lambda W: mini_attention(W, x_b))(W))(batch_x)print(f"Batched grad shape: {batched_grad.shape}") # (16, 24, 8)torch.func ile JAX-vari autodiff API'lar.
13. Autodiff Implementation Stratejileri (Bonus)#
Gerçek autodiff motorları nasıl implement edilir? 4 strateji:
a) Operator overloading (dinamik graph)#
Class'ın , 'lerini override → her op execute olduğunda graph node yarat.
__add____mul__PyTorch, micrograd, NumPy with dual numbers → bu yaklaşım.
b) Source transformation (statik graph)#
Kodu compile time'da analyze et, türev kodunu otomatik üret. Tensorflow 1.x, JAX (XLA ile), Tapenade (Fortran/C için).
c) Tracing (hybrid)#
Forward'da execute et + graph kaydet, sonra graph'i transform et. JAX bu pattern.
jitd) Just-in-time + caching#
Aynı shape'lerde compiled graph cache'le. Modern , JAX .
torch.compilejitLLM'de hangisi?#
- Eğitim: dynamic graph (PyTorch eager) — debugging için
- Production inference: traced/jitted (veya JAX
torch.compile) — performance içinjit - Hybrid: 2026'nın standardı — decorator ile eager kod hızlanır
torch.compile
14. Mini Egzersizler#
-
Dual numbers ile:
expclass'aDualmetodu ekle.exp. Test et.d/dx eˣ = eˣ -
JVP karmaşıklığı:. Tam Jacobian'ı forward-mode ile kaç JVP'le hesaplarız? Reverse-mode ile kaç VJP?
f: ℝ → ℝ¹⁰⁰ -
HVP doğrulama: Bir 2-diçin,
f(x, y) = x²y + sin(xy)Hessian-vector product'ını forward-of-reverse ile hesapla. Tam Hessian ile karşılaştır.H · v -
Forward vs reverse trade-off:(Jacobian 1000×1000). Hangi mod ucuz? Eğer dataset'in eğitim örneklerinde her noktada gradient norm'unu istersen?
f: ℝ¹⁰⁰⁰ → ℝ¹⁰⁰⁰ -
PyTorchtest: Yukarıdaki
torch.func'da, Q ve K weight'leri arasındaki cross-Hessian hesaplamak istersen, hangi API'yi kullanırsın?mini_attention
Bu Derste Neler Öğrendik?#
✓ Sembolik, numerik, otomatik türev karşılaştırması
✓ Dual numbers ile forward-mode sezgisi (40-satır implementasyon)
✓ Reverse-mode = backprop'un genel hali
✓ JVP (Jacobian-vector product) → forward-mode'un atomu
✓ VJP (vector-Jacobian product) → reverse-mode'un atomu
✓ Karmaşıklık kuralı: n < m → forward, m < n → reverse
✓ JAX API: jvp, vjp, grad, jacfwd, jacrev, hessian
✓ HVP = forward-of-reverse trick — modern optimization'ın dayanağı
✓ Higher-order autodiff: 2., 3. türevler
✓ LLM'de forward-mode kullanım alanları: HVP, FIM·v, influence functions
✓ PyTorch — JAX-vari modern API
torch.funcSıradaki Ders#
2.4 — NumPy ile Tensor Autograd Sıfırdan: Mini-Tinygrad İnşası
1.4'te skaler micrograd yazmıştık. Şimdi tensor-bazlı mini-tinygrad: NumPy üzerinde class'ı, broadcasting-aware backward, view/copy bilinçli gradient akışı, GPU'ya yakın hız. ~400 satırda gerçek autograd.
TensorSık Sorulan Sorular
Popüler ama farklı yerde. Backprop (reverse) deep learning'in günlük ekmeği — 1 scalar loss + milyarlar parametre senaryosunun mükemmel uyumu. Forward-mode niche'ler: (1) **Higher-order derivatives** (HVP, Hessian) — modern optimizer matematiğinin altyapısı. (2) **Physics-informed NN** — PDE constraint'leri için input türevleri. (3) **Sensitivity analysis** — 1 input → çok output sistemler. (4) **Sparse Jacobian** — Jacobian'da çoğu sıfırsa forward verimli. (5) **Hardware-friendly**: forward-mode memory O(1), reverse O(N) — bazı edge devices'da forward tercih.
Yorumlar & Soru-Cevap
(0)Yorum yazmak için giriş yap.
Yorumlar yükleniyor...
İlgili İçerikler
Modül 0: Kurs Çerçevesi ve Atölye Kurulumu
LLM Engineer Kimdir? Junior'dan Staff'a Yapay Zekâ Mühendisliği Kariyer Haritası
Öğrenmeye BaşlaModül 0: Kurs Çerçevesi ve Atölye Kurulumu
Kurs Felsefesi: Neden Bu Yol, Neden Bu Sıra — 8 Aylık Müfredatın İskeleti
Öğrenmeye BaşlaModül 0: Kurs Çerçevesi ve Atölye Kurulumu