---
title: "Görüde Öz-Denetimli Öğrenme (SSL) ve PPUU"
subtitle: "İki parçalı hafta — konuk hoca Ishan Misra (Facebook AI Research) görüde öz-denetimli öğrenmeyi (SSL) anlatır: etiketli veri pahalıdır, bu yüzden SSL etiketsiz veriden yapay bir pretext (bahane) görevi uydurur — döndürmeyi tahmin et, göreli konum, renklendirme — ve onu çözerken anlamlı temsil öğrenir; pretext görevin kendisi önemsizdir, değerli olan yan ürünü olan temsildir, sonra bu temsil az etiketli downstream görevlere taşınır. Misra'nın PIRL'i bu fikri olgunlaştırır: pretext'i tahmin etmek yerine dönüşüme değişmez temsil öğren (orijinal ile dönüştürülmüş versiyon benzer, rastgele görüntü farklı — contrastive). Ardından Alfredo Canziani (Practicum) PPUU'yu (belirsizlik altında öngörü ve politika öğrenme) gösterir — meşhur kamyon geri sokma problemini: bir emulator (kamyon kinematiğini öğrenen dünya modeli) ve bir controller (onu süren politika) öğrenilir, önce dünya modeli eğitilir, sonra controller bu öğrenilmiş model içinde planlanır ve maliyet emulator zinciri boyunca backprop ile controller'a yayılır."
---
::: {.callout-note title="Bölüm bilgisi"}
- **Konuk Lecture videosu (Ishan Misra):** [YouTube — Self-supervised learning in computer vision](https://www.youtube.com/watch?v=0KeR6i1_56g) (≈115 dk)
- **Canziani'nin Practicum videosu:** [YouTube — Prediction and policy learning under uncertainty (PPUU)](https://www.youtube.com/watch?v=A3klBqEWR-I) (≈60 dk)
- **Edition:** Spring 2020 (NYU-DLSP20)
- **Hocalar:** Ishan Misra (konuk, SSL — FAIR) + Alfredo Canziani (Practicum, PPUU)
- **Kaynak:** [atcold.github.io/NYU-DLSP20](http://atcold.github.io/NYU-DLSP20)
- **Okuma süresi:** ≈25 dk
:::
```{python}
#| echo: false
# ============================================================================
# SETUP — NYU sayısal motor (_engine.py) + NYU Violet+gold viz (_viz.py)
# Bu hücre gizlidir (#| echo: false). Aşağıdaki TÜM figür hücreleri burada
# tanımlanan rotate_image_4way / make_synthetic_image + önceki hafta
# yardımcıları + COL_* + apply_style / draw_pipeline / style_legend /
# CLASS_COLORS isimlerini kullanır.
# _engine.py saf numpy (torch YOK); _viz.py NYU Violet+gold paleti.
# İçerikler VERBATIM gömülüdür.
#
# NOT: matplotlib backend'i AYARLANMAZ (matplotlib.use(...) ÇAĞRILMAZ).
# Quarto kendi inline (figür yakalayan) backend'ini kurar; Agg backend
# inline figür-yakalamayı bozar (plt.show() çıktı üretmez). Standalone
# figür testinde savefig kullanılır.
# ============================================================================
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.patches import (
FancyBboxPatch, FancyArrowPatch, Rectangle, Circle, Ellipse, Polygon, Patch,
)
from matplotlib.lines import Line2D
from matplotlib.colors import ListedColormap, BoundaryNorm, LinearSegmentedColormap
np.random.seed(0)
# ===========================================================================
# _engine.py — saf numpy sayısal yardımcılar (torch YOK)
# ===========================================================================
# ---------------------------------------------------------------------------
# Afin / lineer dönüşümler
# ---------------------------------------------------------------------------
def affine_transform(P, W, b=None):
"""P[N,2] noktalarına y = W x (+ b) afin/lineer dönüşümü uygular (satır-vektör konvansiyonu)."""
P = np.asarray(P, float)
Y = P @ np.asarray(W, float).T
if b is not None:
Y = Y + np.asarray(b, float)
return Y
def unit_grid(n=11, lim=2.0, fine=61):
"""Izgara çizgileri listesi (yatay + dikey). Her çizgi (fine,2) dizisi.
Lineer dönüşüm görsellerinde 'uzayın kumaşı' için."""
t = np.linspace(-lim, lim, n)
f = np.linspace(-lim, lim, fine)
lines = []
for yi in t:
lines.append(np.column_stack([f, np.full_like(f, yi)]))
for xi in t:
lines.append(np.column_stack([np.full_like(f, xi), f]))
return lines
def linear_transforms():
"""Canziani'nin dört temel lineer dönüşümü (Bölüm 8) — 2x2 matrisler."""
th = np.deg2rad(35.0)
R = np.array([[np.cos(th), -np.sin(th)], [np.sin(th), np.cos(th)]]) # rotation (ortonormal)
S = np.array([[1.8, 0.0], [0.0, 0.55]]) # scaling (köşegen)
Sh = np.array([[1.0, 0.85], [0.0, 1.0]]) # shearing
F = np.array([[1.0, 0.0], [0.0, -1.0]]) # reflection (det<0)
return dict(rotation=R, scaling=S, shearing=Sh, reflection=F)
# ---------------------------------------------------------------------------
# SVD geometrisi (Canziani'nin 'patatesi')
# ---------------------------------------------------------------------------
def unit_circle(n=240):
t = np.linspace(0, 2 * np.pi, n)
return np.column_stack([np.cos(t), np.sin(t)])
def svd_demo(W):
"""W = U Σ Vᵀ. Geometrik okuma: rotation(Vᵀ) · scaling(Σ) · rotation(U)."""
U, s, Vt = np.linalg.svd(np.asarray(W, float))
return U, s, Vt
def near_singular_matrix():
"""Bir tekil değeri ≈0 olan matris — bir boyutu 'ezer' (elips çizgiye çöker)."""
th = np.deg2rad(30.0)
R = np.array([[np.cos(th), -np.sin(th)], [np.sin(th), np.cos(th)]])
Sigma = np.diag([1.6, 0.04]) # ikinci tekil değer ≈ 0
return R @ Sigma @ R.T
# ---------------------------------------------------------------------------
# Spiral (manifold germe demosu)
# ---------------------------------------------------------------------------
def make_spiral(n_per=120, k=5, noise=0.18, seed=0):
"""k-kollu spiral (CS231n stili). Her kol bir sınıf; kollar orijinde iç içe → lineer ayrılamaz."""
rng = np.random.default_rng(seed)
X = np.zeros((n_per * k, 2))
y = np.zeros(n_per * k, dtype=int)
for j in range(k):
ix = slice(n_per * j, n_per * (j + 1))
r = np.linspace(0.0, 1.0, n_per)
t = np.linspace(j * 4.0, (j + 1) * 4.0, n_per) + rng.normal(0, 1, n_per) * noise
X[ix] = np.column_stack([r * np.sin(t), r * np.cos(t)])
y[ix] = j
return X, y
def unroll_spiral(X, y, k=5, seed=0):
"""ŞEMATİK 'öğrenilen temsil': her sınıfı kendi yatay bandına taşır → lineer ayrılabilir.
Gerçek bir eğitilmiş ağ DEĞİL; 'ağ manifoldu açar' sezgisinin deterministik görseli."""
rng = np.random.default_rng(seed)
r = np.linalg.norm(X, axis=1)
yb = (y - (k - 1) / 2.0) * 0.55 + rng.normal(0, 0.045, len(y))
return np.column_stack([r * 2.2 - 1.1, yb])
# ---------------------------------------------------------------------------
# İki hilal (make_moons — sklearn YOK, numpy ile elle)
# ---------------------------------------------------------------------------
def make_moons_np(n=400, noise=0.20, seed=0):
"""Doğrusal ayrılamaz iki-hilal veri (sklearn.make_moons eşdeğeri)."""
rng = np.random.default_rng(seed)
n_out = n // 2
n_in = n - n_out
to = np.linspace(0, np.pi, n_out)
ti = np.linspace(0, np.pi, n_in)
outer = np.column_stack([np.cos(to), np.sin(to)])
inner = np.column_stack([1.0 - np.cos(ti), 1.0 - np.sin(ti) - 0.5])
X = np.vstack([outer, inner]) + rng.normal(0, noise, (n, 2))
y = np.array([0] * n_out + [1] * n_in)
return X, y
# ---------------------------------------------------------------------------
# Minik numpy sınıflandırıcılar (lineer vs ReLU MLP) — karar sınırı kontrastı
# ---------------------------------------------------------------------------
def _onehot(y, c):
Y = np.zeros((len(y), c))
Y[np.arange(len(y)), y] = 1.0
return Y
def _softmax(z):
z = z - z.max(axis=1, keepdims=True)
e = np.exp(z)
return e / e.sum(axis=1, keepdims=True)
def logreg_train(X, y, steps=500, lr=1.0, seed=0):
"""Lineer (gizli katmansız) softmax sınıflandırıcı → DÜZ karar sınırı."""
rng = np.random.default_rng(seed)
n, d = X.shape
c = int(y.max() + 1)
W = rng.normal(0, 0.01, (d, c))
b = np.zeros(c)
Y = _onehot(y, c)
for _ in range(steps):
p = _softmax(X @ W + b)
dz = (p - Y) / n
W -= lr * (X.T @ dz)
b -= lr * dz.sum(axis=0)
return dict(W=W, b=b)
def logreg_forward(params, X):
return X @ params["W"] + params["b"]
def mlp_train(X, y, hidden=16, act="relu", steps=600, lr=1.0, seed=0, return_history=False):
"""numpy 2-katmanlı MLP (afine → nonlinearite → afine), softmax + cross-entropy.
ReLU ile EĞRİ karar sınırı (hilalleri/spirali ayırır).
return_history=True → (params, loss_history) döner (eğitim eğrisi figürü için)."""
rng = np.random.default_rng(seed)
n, d = X.shape
c = int(y.max() + 1)
W1 = rng.normal(0, 1, (d, hidden)) * np.sqrt(2.0 / d)
b1 = np.zeros(hidden)
W2 = rng.normal(0, 1, (hidden, c)) * np.sqrt(2.0 / hidden)
b2 = np.zeros(c)
Y = _onehot(y, c)
history = []
for _ in range(steps):
z1 = X @ W1 + b1
a1 = np.maximum(0, z1) if act == "relu" else np.tanh(z1)
p = _softmax(a1 @ W2 + b2)
if return_history:
history.append(float(-np.log(p[np.arange(n), y] + 1e-12).mean()))
dz2 = (p - Y) / n
dW2 = a1.T @ dz2
db2 = dz2.sum(axis=0)
da1 = dz2 @ W2.T
dz1 = da1 * ((z1 > 0) if act == "relu" else (1 - np.tanh(z1) ** 2))
dW1 = X.T @ dz1
db1 = dz1.sum(axis=0)
W1 -= lr * dW1
b1 -= lr * db1
W2 -= lr * dW2
b2 -= lr * db2
params = dict(W1=W1, b1=b1, W2=W2, b2=b2, act=act)
if return_history:
return params, np.array(history)
return params
def mlp_forward(params, X):
z1 = X @ params["W1"] + params["b1"]
a1 = np.maximum(0, z1) if params["act"] == "relu" else np.tanh(z1)
return a1 @ params["W2"] + params["b2"]
def accuracy(forward_fn, params, X, y):
return float((forward_fn(params, X).argmax(axis=1) == y).mean())
def decision_grid(X, pad=0.6, h=0.02):
"""Karar bölgesi için koordinat ızgarası (xx, yy) ve düz nokta listesi."""
x0, x1 = X[:, 0].min() - pad, X[:, 0].max() + pad
y0, y1 = X[:, 1].min() - pad, X[:, 1].max() + pad
xx, yy = np.meshgrid(np.arange(x0, x1, h), np.arange(y0, y1, h))
grid = np.column_stack([xx.ravel(), yy.ravel()])
return xx, yy, grid
# ---------------------------------------------------------------------------
# Enerji manzarası (EBM — çoklu minimum = çoklu geçerli cevap)
# ---------------------------------------------------------------------------
def energy_landscape(xx, yy):
"""F(x,y): birkaç Gauss kuyusu → çoklu yerel minimum. Düşük enerji = uyumlu cevap."""
wells = [(-1.25, -0.65, 1.0, 0.55), (1.15, 0.85, 1.05, 0.6), (0.15, -1.15, 0.8, 0.45)]
F = np.ones_like(xx) * 1.0
for cx, cy, depth, width in wells:
F = F - depth * np.exp(-((xx - cx) ** 2 + (yy - cy) ** 2) / (2 * width))
return F
# ---------------------------------------------------------------------------
# Hafta 2 — gradient descent, SGD, backprop, eğitim
# ---------------------------------------------------------------------------
def loss_surface_2d(xx, yy):
"""2D parametre uzayında bir kayıp yüzeyi (gradient descent 'dağ' görseli için):
eğik, farklı-ölçekli bir vadi (konveks taban) + hafif dalgalanma."""
u = 0.85 * xx + 0.53 * yy # eksenleri döndür (eğik vadi)
v = -0.53 * xx + 0.85 * yy
return 1.0 * u ** 2 + 3.5 * v ** 2 + 0.6 * np.sin(1.5 * xx) * np.cos(1.5 * yy)
def _loss_grad_2d(p):
"""loss_surface_2d gradyanı (merkezi sonlu fark)."""
eps = 1e-4
gx = (loss_surface_2d(p[0] + eps, p[1]) - loss_surface_2d(p[0] - eps, p[1])) / (2 * eps)
gy = (loss_surface_2d(p[0], p[1] + eps) - loss_surface_2d(p[0], p[1] - eps)) / (2 * eps)
return np.array([gx, gy])
def gd_path(theta0, lr=0.08, steps=40):
"""loss_surface_2d üzerinde gradient descent yörüngesi (parametre adımları)."""
p = np.array(theta0, float)
path = [p.copy()]
for _ in range(steps):
p = p - lr * _loss_grad_2d(p)
path.append(p.copy())
return np.array(path)
def sgd_loss_curves(steps=80, seed=0):
"""Üç rejim için kayıp eğrisi (simülasyon): full-batch (gürültüsüz, düz),
mini-batch (orta gürültü), saf SGD (yüksek gürültü). Aynı yumuşak üstel düşüş."""
rng = np.random.default_rng(seed)
t = np.arange(steps)
base = 0.2 + 2.6 * np.exp(-t / 14.0)
full = base.copy()
mini = base + rng.normal(0, 0.10, steps) * np.exp(-t / 45.0)
sgd = base + rng.normal(0, 0.45, steps) * np.exp(-t / 70.0)
return t, np.clip(full, 0, None), np.clip(mini, 0, None), np.clip(sgd, 0, None)
def tanh_deriv(x):
"""tanh'ın türevi: 1 − tanh²(x). Backprop 'twiddling' figürü için."""
return 1.0 - np.tanh(x) ** 2
def ce_loss_curve(p):
"""Doğru sınıf olasılığı p için cross-entropy kaybı: −log p."""
p = np.clip(np.asarray(p, float), 1e-6, 1.0)
return -np.log(p)
def mse_loss_curve(p):
"""Doğru sınıf olasılığı p için (one-hot hedefe) MSE: (1 − p)²."""
return (1.0 - np.asarray(p, float)) ** 2
# ---------------------------------------------------------------------------
# Hafta 3 — convolution / ConvNet / doğal sinyaller
# ---------------------------------------------------------------------------
def conv_output_size(n, k, s=1):
"""Çıktı boyutu: o = ⌊(n − k)/s⌋ + 1."""
return (n - k) // s + 1
def conv1d(x, w):
"""1B cross-correlation (ML 'convolution'): out[i] = Σ_k x[i+k]·w[k].
Örnek: conv1d([1,2,3,4,5],[1,0,-1]) → [-2,-2,-2] (kenar/fark dedektörü)."""
x = np.asarray(x, float)
w = np.asarray(w, float)
n = len(x) - len(w) + 1
return np.array([np.dot(x[i:i + len(w)], w) for i in range(n)])
def conv2d(img, kernel, stride=1):
"""2B valid cross-correlation (ag öznitelik haritası üretir)."""
img = np.asarray(img, float)
k = np.asarray(kernel, float)
kh, kw = k.shape
H, W = img.shape
oh, ow = conv_output_size(H, kh, stride), conv_output_size(W, kw, stride)
out = np.zeros((oh, ow))
for i in range(oh):
for j in range(ow):
patch = img[i * stride:i * stride + kh, j * stride:j * stride + kw]
out[i, j] = np.sum(patch * k)
return out
def make_synthetic_image(n=28, seed=0):
"""Basit gri-tonlu sentetik görüntü: kare + daire (kenar tespiti net görünsün)."""
img = np.zeros((n, n))
img[5:14, 6:15] = 1.0 # dolu kare
yy, xx = np.ogrid[:n, :n]
cy, cx, r = 19, 19, 6
img[(yy - cy) ** 2 + (xx - cx) ** 2 <= r ** 2] = 0.85 # daire
img[20:22, 4:24] = 0.6 # yatay çizgi (yatay kenar için)
return img
def edge_kernels():
"""Klasik 3×3 öznitelik dedektörü kernel'leri."""
return dict(
sobel_x=np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]], float), # dikey kenar
sobel_y=np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]], float), # yatay kenar
blur=np.ones((3, 3)) / 9.0, # bulanıklaştırma
laplace=np.array([[0, 1, 0], [1, -4, 1], [0, 1, 0]], float), # tüm kenarlar
)
def max_pool2d(img, k=2):
"""k×k max pooling (complex cell / invariance)."""
img = np.asarray(img, float)
H, W = img.shape
oh, ow = H // k, W // k
return np.array([[img[i * k:(i + 1) * k, j * k:(j + 1) * k].max() for j in range(ow)]
for i in range(oh)])
def avg_pool2d(img, k=2):
"""k×k average pooling (LeNet5 stili)."""
img = np.asarray(img, float)
H, W = img.shape
oh, ow = H // k, W // k
return np.array([[img[i * k:(i + 1) * k, j * k:(j + 1) * k].mean() for j in range(ow)]
for i in range(oh)])
# ---------------------------------------------------------------------------
# Hafta 4 — convolution cebiri (Toeplitz) + optimizasyon (κ, momentum, Adam)
# ---------------------------------------------------------------------------
def build_toeplitz(kernel, n):
"""1B convolution'ın Toeplitz matrisi: out = T @ x, T[i, i:i+k] = kernel.
conv1d(x, kernel) == build_toeplitz(kernel, len(x)) @ x (çoğu eleman sıfır = seyrek)."""
kernel = np.asarray(kernel, float)
k = len(kernel)
oh = n - k + 1
T = np.zeros((oh, n))
for i in range(oh):
T[i, i:i + k] = kernel
return T
def quad_loss(xx, yy, kappa=20.0):
"""Eğik, koşullanması κ = L/μ olan kuadratik vadi (condition number görseli).
κ büyük → uzun ince vadi → gradient descent zikzak çizer."""
a, b = 0.92, 0.39 # ~25° dönme
u = a * xx + b * yy
v = -b * xx + a * yy
return 0.5 * (1.0 * u ** 2 + kappa * v ** 2) # L=κ, μ=1
def quad_grad(p, kappa=20.0):
"""quad_loss'un analitik gradyanı."""
a, b = 0.92, 0.39
x, y = p
u = a * x + b * y
v = -b * x + a * y
gu, gv = u, kappa * v
return np.array([gu * a + gv * (-b), gu * b + gv * a])
def optimize_quad(method, theta0, lr, steps, kappa=20.0, beta=0.9, beta2=0.999, eps=1e-8):
"""quad_loss üzerinde bir optimizer'ı koştur; yörünge + kayıp geçmişi döner.
method ∈ {'gd','momentum','adam'}. Defazio'nun zikzak/sönümleme/adaptif anlatısı için."""
p = np.array(theta0, float)
path = [p.copy()]
losses = [float(quad_loss(p[0], p[1], kappa))]
m = np.zeros(2)
v = np.zeros(2)
for t in range(1, steps + 1):
g = quad_grad(p, kappa)
if method == "gd":
step = lr * g
elif method == "momentum":
m = beta * m + g # heavy ball
step = lr * m
elif method == "adam":
m = beta * m + (1 - beta) * g
v = beta2 * v + (1 - beta2) * g * g
mh = m / (1 - beta ** t) # bias correction
vh = v / (1 - beta2 ** t)
step = lr * mh / (np.sqrt(vh) + eps)
else:
raise ValueError(method)
p = p - step
path.append(p.copy())
losses.append(float(quad_loss(p[0], p[1], kappa)))
return np.array(path), np.array(losses)
# ---------------------------------------------------------------------------
# Hafta 5 — autograd worked example (Canziani)
# ---------------------------------------------------------------------------
def autograd_worked(X=None):
"""Canziani worked example: X → Y=X−2 → Z=3·Y² → a=mean(Z) (skaler).
İleri değerler + ∂a/∂xᵢ = (1/4)·3·2·(xᵢ−2) = 1.5·(xᵢ−2).
X=[1,2,3,4] için grad = [−1.5, 0, 1.5, 3] (PyTorch X.grad ile birebir)."""
if X is None:
X = np.array([1.0, 2.0, 3.0, 4.0])
X = np.asarray(X, float)
Y = X - 2.0
Z = 3.0 * Y ** 2
a = float(Z.mean())
grad = 1.5 * (X - 2.0)
return dict(X=X, Y=Y, Z=Z, a=a, grad=grad)
def conv_pad_output(n, k, padding=0, stride=1):
"""Padding'li çıktı boyutu: o = ⌊(n + 2·padding − k)/stride⌋ + 1.
padding=(k−1)/2 (k tek) → çıktı boyutu korunur."""
return (n + 2 * padding - k) // stride + 1
# ---------------------------------------------------------------------------
# Hafta 6 — RNN / vanishing gradient / attention
# ---------------------------------------------------------------------------
def vanishing_demo(steps=50, eigenvalues=(0.5, 1.0, 1.5)):
"""Aynı matristen n kez geçen gradient: λⁿ. λ<1 söner (vanishing), λ>1 patlar
(exploding), λ=1 sabit. Backprop-through-time vanishing gradient görseli."""
t = np.arange(steps + 1)
curves = {ev: np.asarray(ev, float) ** t for ev in eigenvalues}
return t, curves
def rnn_forward(X_seq, Wx, Wz, b, z0=None):
"""Basit RNN hücresi: zₜ = tanh(Wₓ·xₜ + W_z·zₜ₋₁ + b).
X_seq [T, d_in] → gizli durumlar Z [T, d_h] (aynı Wₓ,W_z her adımda = paylaşım)."""
X_seq = np.asarray(X_seq, float)
T = len(X_seq)
dh = np.asarray(Wz).shape[0]
z = np.zeros(dh) if z0 is None else np.asarray(z0, float)
Z = []
for t in range(T):
z = np.tanh(np.asarray(Wx) @ X_seq[t] + np.asarray(Wz) @ z + np.asarray(b))
Z.append(z.copy())
return np.array(Z)
def attention_weights(scores):
"""Attention ağırlıkları = softmax(skorlar); toplamı 1 (olasılık dağılımı, 'odak')."""
scores = np.asarray(scores, float)
e = np.exp(scores - scores.max())
return e / e.sum()
# ---------------------------------------------------------------------------
# Hafta 7 — EBM / autoencoder / manifold
# ---------------------------------------------------------------------------
def energy_1d(y, data_points=(-2.0, 0.0, 2.0), width=0.35):
"""1B enerji F(y): veri noktalarında düşük (çukur), aralarda yüksek (tepe).
'İyi enerji şekli' = veride düşük, dışında yüksek (EBM); çoklu minimum = çoklu cevap."""
y = np.asarray(y, float)
F = np.ones_like(y)
for d in data_points:
F = F - np.exp(-(y - d) ** 2 / (2 * width))
return F
def energy_1d_grad(y, data_points=(-2.0, 0.0, 2.0), width=0.35):
"""energy_1d'nin türevi (çıkarım = enerji minimizasyonu, gradient ile arama)."""
y = np.asarray(y, float)
g = np.zeros_like(y)
for d in data_points:
g = g + (y - d) / width * np.exp(-(y - d) ** 2 / (2 * width))
return g
def make_manifold_curve(n=160, noise=0.0, seed=0):
"""2B veri manifoldu: bir eğri (sinüs yayı) üzerinde noktalar (Hafta 1 manifold hipotezi)."""
t = np.linspace(-2.6, 2.6, n)
M = np.column_stack([t, np.sin(1.3 * t)])
if noise:
M = M + np.random.default_rng(seed).normal(0, noise, M.shape)
return M
def project_to_manifold(points, manifold):
"""Her noktayı manifoldun EN YAKIN noktasına çeker (autoencoder reconstruction sezgisi:
off-manifold girdiyi manifolda geri çek → düşük enerji)."""
points = np.asarray(points, float)
proj = np.array([manifold[np.linalg.norm(manifold - p, axis=1).argmin()] for p in points])
return proj
# ---------------------------------------------------------------------------
# Hafta 8 — contrastive / VAE
# ---------------------------------------------------------------------------
def vae_reparam(mu, sigma, n=400, seed=0):
"""Reparameterization trick: z = μ + σ⊙ε, ε~N(0,I). Düzenli (sürekli, dolu)
Gaussian latent örnekleri — VAE'nin üretken latent uzayı."""
mu = np.atleast_1d(np.asarray(mu, float))
sigma = np.atleast_1d(np.asarray(sigma, float))
rng = np.random.default_rng(seed)
eps = rng.normal(0, 1, (n, len(mu)))
return mu + sigma * eps
def ae_latent_clusters(n=400, seed=0):
"""Sıradan AE latent'i: dağınık, boşluklu kümeler (düzensiz uzay — VAE kontrastı)."""
rng = np.random.default_rng(seed)
centers = np.array([[-2.2, 1.8], [2.0, 2.1], [0.3, -2.3], [-1.8, -1.5]])
pts = []
for c in centers:
pts.append(c + rng.normal(0, 0.28, (n // len(centers), 2)))
return np.vstack(pts)
# ---------------------------------------------------------------------------
# Hafta 9 — sparse coding / GAN (EBM)
# ---------------------------------------------------------------------------
def sparse_code_demo(n=24, n_active=5, seed=0):
"""Yoğun (dense) vs seyrek (sparse) code: L1 düzenlileştirme çoğu bileşeni
sıfıra iter — yalnızca birkaç birim aktif kalır (sparse coding)."""
rng = np.random.default_rng(seed)
dense = rng.normal(0, 1, n)
idx = np.argsort(-np.abs(dense)) # en büyük |değer| → aktif kalanlar
sparse = np.zeros(n)
sparse[idx[:n_active]] = dense[idx[:n_active]]
return dense, sparse
def rotate_image_4way(img):
"""0/90/180/270° döndürülmüş 4 versiyon — rotation pretext görevi (Hafta 10 SSL):
ağ 'kaç derece döndürüldü?' sorusunu çözer (4-yönlü sınıflandırma)."""
img = np.asarray(img, float)
return [np.rot90(img, k) for k in range(4)]
def gan_samples(seed=0, n=200):
"""GAN sezgisi: gerçek veri (manifold/halka) vs generator'ın ürettiği sahte örnekler.
İlk başta sahteler dağınık (eğitilmemiş generator), gerçeğe yakınsar."""
rng = np.random.default_rng(seed)
th = rng.uniform(0, 2 * np.pi, n)
real = np.column_stack([np.cos(th), np.sin(th)]) + rng.normal(0, 0.06, (n, 2)) # gerçek = birim halka
fake_early = rng.normal(0, 1.1, (n, 2)) # eğitilmemiş gen (dağınık)
th2 = rng.uniform(0, 2 * np.pi, n)
fake_late = np.column_stack([np.cos(th2), np.sin(th2)]) + rng.normal(0, 0.18, (n, 2)) # eğitilmiş gen (halkaya yakın)
return real, fake_early, fake_late
# ===========================================================================
# _viz.py — NYU Violet + gold matplotlib stil sabitleri ve yardımcıları
# ===========================================================================
COL_VIOLET = "#57068c" # NYU Violet — birincil çizgi/çerçeve/vurgu
COL_VIOLET_D = "#3d0463" # koyu violet — güçlü vurgu / gradyan
COL_VIOLET_M = "#7b2cbf" # orta violet — ikincil
COL_VIOLET_SOFT = "#b56ad6" # soluk violet
COL_GOLD = "#d4a017" # gold accent
COL_GOLD_D = "#a87d0a" # koyu gold
COL_TEXT = "#2a2535" # gövde metni (hafif violet tint)
COL_INK = "#1e1a2e" # en koyu — başlık
COL_BG = "#f4eefa" # açık violet — dolgu/arka plan
COL_GRID = "#cdbbe0" # soluk violet — ızgara/pasif kenar
COL_WHITE = "#ffffff"
# 5-sınıf kategorik palet (spiral 5 kol / moons ilk 2) — violet↔gold ekseni, tema-uyumlu
CLASS_COLORS = ["#57068c", "#7b2cbf", "#b56ad6", "#d4a017", "#a87d0a"]
# Çizgi-grafik tutarlı renkler
LINE_PRIMARY = COL_VIOLET
LINE_ACCENT = COL_GOLD
LINE_SECONDARY = COL_VIOLET_M
def apply_style(ax):
"""Bir eksene tutarlı NYU Violet+gold görünümü uygular."""
ax.set_facecolor(COL_WHITE)
ax.grid(True, alpha=0.25, color=COL_GRID, linewidth=0.8)
for spine in ax.spines.values():
spine.set_color(COL_GRID)
ax.tick_params(colors=COL_TEXT)
ax.title.set_color(COL_TEXT)
ax.xaxis.label.set_color(COL_TEXT)
ax.yaxis.label.set_color(COL_TEXT)
return ax
def draw_pipeline(ax, stages, title=None, y0=0.0):
"""Soldan-sağa kutu+ok boru hattı şeması (örüntü tanıma vs uçtan-uca).
stages : [(label:str, is_learned:bool), ...]
is_learned=True -> öğrenilen modül (violet dolgulu)
is_learned=False -> elle-tasarlanan/sabit (gold kenarlı, açık dolgu)
"""
n = len(stages)
box_w, box_h, gap = 1.7, 1.0, 0.9
step = box_w + gap
ax.set_xlim(-0.3, n * step)
ax.set_ylim(y0 - 1.1, y0 + 1.1)
ax.axis("off")
if title:
ax.set_title(title, color=COL_TEXT, fontsize=12, pad=10)
for i, (lbl, learned) in enumerate(stages):
x = i * step
fc = "#ece0f7" if learned else COL_BG
ec = COL_VIOLET if learned else COL_GOLD_D
lw = 2.4 if learned else 2.0
box = FancyBboxPatch(
(x, y0 - box_h / 2), box_w, box_h,
boxstyle="round,pad=0.02,rounding_size=0.12",
fc=fc, ec=ec, lw=lw, zorder=2,
)
ax.add_patch(box)
ax.text(x + box_w / 2, y0, lbl, ha="center", va="center",
fontsize=9.5, color=COL_TEXT, zorder=3, wrap=True)
if i > 0:
ax.add_patch(FancyArrowPatch(
(x - gap, y0), (x, y0),
arrowstyle="-|>", mutation_scale=16,
color=COL_VIOLET_M, lw=1.9, zorder=1,
))
return ax
def style_legend(ax, **kw):
"""Tema-uyumlu legend."""
leg = ax.legend(frameon=True, framealpha=0.95, edgecolor=COL_GRID, **kw)
if leg is not None:
leg.get_frame().set_facecolor(COL_WHITE)
for t in leg.get_texts():
t.set_color(COL_TEXT)
return leg
```
## Bu Derste Ne Var? {#sec-genel-bakis-d10}
Bu hafta iki parça: **konuk hoca Ishan Misra** (Facebook AI Research) görüde **öz-denetimli öğrenmeyi (SSL)** anlatıyor; **Alfredo Canziani** ise dünya modellerini pratiğe döken **PPUU**'yu (belirsizlik altında öngörü ve politika öğrenme) — meşhur "kamyon geri sokma" problemini — gösteriyor.
::: {.callout-warning title="⚠️ Atıf notu (Hafta 10 sinyatürü)"}
Bu haftanın Lecture'ı **LeCun değil, konuk Ishan Misra** tarafından verilir (transkriptten doğrulandı: "today we have a guest lecturer, Ishan Misra, research scientist at Facebook AI Research"). Quote'lar **— Misra** ile işaretlenir; Practicum quote'ları **— Canziani**.
:::
Misra'nın büyük fikri: etiketli veri pahalıdır; SSL, **etiketsiz** veriden bir **pretext (bahane) görevi** uydurarak temsil öğrenir, sonra bu temsili gerçek (downstream) görevlere taşır. Canziani ise Hafta 9'un dünya modelini somutlaştırır: bir **emulator** (kamyon kinematiğini öğrenen dünya modeli) + bir **controller** (onu süren politika).
Bu haftanın üç ana fikri:
1. **SSL = pretext görev → temsil → transfer.** Etiketsiz veriden yapay bir görev (döndürmeyi tahmin et, renklendirme, parça konumu) uydur; çözerken anlamlı temsil öğren; downstream'e aktar.
2. **Pretext görev kendisi önemsizdir**; amaç onun yan ürünü olan **temsildir** (representation).
3. **PPUU:** dünya modeli (emulator) + politika (controller); önce dünyayı öğren, sonra onun içinde planla — Hafta 9 world model'in pratiği.
```{mermaid}
%%| echo: false
flowchart TB
Hafta["Hafta 10 = iki parça<br/>(Misra: görüde SSL · Canziani: PPUU)"]
subgraph A["(A) Görüde SSL — Misra (konuk)"]
direction TB
Etiketsiz["Etiketsiz büyük veri<br/>(etiket PAHALI)"]
Pretext["Pretext görev<br/>(döndürme / konum / renklendirme)"]
Temsil["Öğrenilen temsil<br/>(YAN ÜRÜN — asıl ödül)"]
Downstream["Downstream görev<br/>(az etiketli, transfer)"]
PIRL["PIRL = dönüşüme DEĞİŞMEZ<br/>(contrastive, Hafta 8)"]
Post["post-2020 (BYOL/VICReg/<br/>MAE/JEPA) — KURSTA YOK"]
Etiketsiz --> Pretext
Pretext --> Temsil
Temsil --> Downstream
Temsil --> PIRL
PIRL --> Post
end
subgraph B["(B) PPUU — Canziani"]
direction TB
Emulator["Emulator = dünya modeli<br/>(sₜ₊₁ = f(sₜ, aₜ))"]
Controller["Controller = politika<br/>(direksiyon)"]
Planla["Önce dünyayı öğren<br/>→ içinde planla (backprop)"]
Emulator --> Controller
Controller --> Planla
end
Hafta --> Etiketsiz
Hafta --> Emulator
```
::: {.callout-tip title="Builder Notu — İki Parça, Tek Çatı: Etiketsiz Gözetim"}
**Geriye (önkoşul kurslar):**
- **SSL = label'sız gözetim** → Hafta 8 contrastive SSL + Hafta 3 invariance (augmentation).
- **Pretext = proxy görev** → Hafta 1 supervised (ama label'ı veriden uydur) + Hafta 2 cross-entropy (rotation = 4-yönlü sınıflandırma).
- **Emulator/controller** → Hafta 9 dünya modeli (latent-variable EBM) + Hafta 6 dizi/öngörü.
**İleriye (production / research):**
- SSL → **post-2020 (BYOL, VICReg, MAE, JEPA — KURSTA YOK)** (Bölüm 5 İleriye Köprü).
- PPUU/world model → model-based RL, planning, LeCun JEPA programı.
**Tek cümleyle:** Öz-denetimli öğrenme, etiketsiz veriden bir pretext görev uydurup onu çözerek anlamlı temsiller öğrenir ve bunları downstream görevlere taşır; PPUU ise bir dünya modeli (emulator) öğrenip onun içinde bir politika (controller) eğiterek planlamayı pratiğe döker.
:::
## (Misra — Konuk) SSL Nedir? Pre-train → Downstream {#sec-ssl-nedir}
Misra önce supervised learning'in sorununu koyuyor: büyük etiketli veri (ImageNet) pahalıdır ve her görev için yeniden toplanamaz. Çözüm **temsil öğrenme (representation learning)**: bir kez iyi bir temsil öğren, sonra onu etiketin az olduğu **downstream (alt) görevlere** taşı.
> "the story for representation learning for computer vision so far has been... a pre-training step [then] use [it] for downstream tasks where you may not have [labels]." — Misra, 1:18
Supervised pre-training (ImageNet etiketleriyle) işe yarar ama yine etiket ister. **Öz-denetimli öğrenme (SSL)** etiketi ortadan kaldırır: gözetim sinyalini **verinin kendisinden** üretir. (NLP'de word2vec bunu yıllardır yapıyor — kelimeyi bağlamından tahmin et.) @fig-ssl-pretrain bu boru hattını gösteriyor: etiketsiz büyük veri bir pretext göreve girer, encoder bir temsil öğrenir, ve bu temsil az etiketli downstream göreve aktarılır — üstteki gözetimli şerit ise her örneğin pahalı insan etiketi gerektiren kıyasıdır.
```{python}
#| label: fig-ssl-pretrain
#| fig-cap: "SSL boru hattı: etiketsiz büyük veri → pretext görev (döndürmeyi tahmin et, 0°/90°/180°/270°) → öğrenilen temsil (encoder) → transfer/dondur → az etiketli downstream görev. Üstte gözetimli (pahalı insan etiketi) kıyası; altta SSL'in gözetim sinyalini doğrudan veriden ürettiği vurgusu."
fig, ax = plt.subplots(figsize=(11.2, 5.4))
ax.set_xlim(0, 100)
ax.set_ylim(0, 56)
ax.axis("off")
ax.set_title("Kendi Kendine Gözetimli Öğrenme (SSL): pre-train → downstream",
fontsize=14, color=COL_INK, fontweight="bold", pad=12)
# ---------------------------------------------------------------------------
# Yardımcı: yuvarlatılmış kutu + ortalanmış metin
# ---------------------------------------------------------------------------
def box(x, y, w, h, fc, ec, lw=2.2, z=2):
ax.add_patch(FancyBboxPatch((x, y), w, h,
boxstyle="round,pad=0.4,rounding_size=1.6",
fc=fc, ec=ec, lw=lw, zorder=z))
def arrow(x0, y0, x1, y1, col=COL_VIOLET_M, lw=2.2, z=4, style="-|>"):
ax.add_patch(FancyArrowPatch((x0, y0), (x1, y1),
arrowstyle=style, mutation_scale=18,
color=col, lw=lw, zorder=z))
# ---------------------------------------------------------------------------
# Üst şerit: gözetimli (supervised) kıyas — pahalı insan etiketi
# ---------------------------------------------------------------------------
box(4, 47, 40, 7, "#fbf3dd", COL_GOLD_D, lw=1.8, z=2)
ax.text(7, 50.5, "Gözetimli (supervised):", ha="left", va="center",
fontsize=10.5, color=COL_GOLD_D, fontweight="bold", zorder=3)
ax.text(24.5, 50.5, "her örnek için PAHALI insan etiketi", ha="left", va="center",
fontsize=10, color=COL_TEXT, zorder=3)
# ---------------------------------------------------------------------------
# 1) Etiketsiz büyük veri — çoklu görsel ikonu
# ---------------------------------------------------------------------------
base = make_synthetic_image(28)
gx0, gy0 = 5.5, 24.0
for r in range(2):
for c in range(2):
ext = [gx0 + c * 7.3 + r * 1.0, gx0 + c * 7.3 + r * 1.0 + 6.6,
gy0 + r * 7.0, gy0 + r * 7.0 + 6.6]
ax.imshow(base, cmap="Purples", extent=ext, zorder=3,
aspect="auto", alpha=0.92)
ax.add_patch(plt.Rectangle((ext[0], ext[2]), 6.6, 6.6,
fill=False, ec=COL_VIOLET, lw=1.2, zorder=4))
ax.text(11.5, 21.5, "ETİKETSİZ büyük veri\n(milyonlarca görsel)",
ha="center", va="top", fontsize=10, color=COL_INK, fontweight="bold")
# ---------------------------------------------------------------------------
# 2) Pretext görev kutusu — rotation (4-yönlü) önizleme
# ---------------------------------------------------------------------------
box(27, 22, 22, 17, "#fbf3dd", COL_GOLD_D, lw=2.2, z=2)
ax.text(38, 37.0, "Pretext görev", ha="center", va="center",
fontsize=10.5, color=COL_GOLD_D, fontweight="bold", zorder=5)
ax.text(38, 34.2, "döndürmeyi tahmin et\n(0° / 90° / 180° / 270°)",
ha="center", va="center", fontsize=8.6, color=COL_TEXT, zorder=5)
rots = rotate_image_4way(base)
labels = ["0°", "90°", "180°", "270°"]
rx0, ry0, sz = 29.0, 23.0, 4.4
for i, (rim, lb) in enumerate(zip(rots, labels)):
ex = [rx0 + i * 4.9, rx0 + i * 4.9 + sz, ry0, ry0 + sz]
ax.imshow(rim, cmap="Purples", extent=ex, zorder=5, aspect="auto")
ax.add_patch(plt.Rectangle((ex[0], ex[2]), sz, sz, fill=False,
ec=COL_VIOLET, lw=1.0, zorder=6))
ax.text(ex[0] + sz / 2, ry0 - 0.9, lb, ha="center", va="top",
fontsize=7.6, color=COL_VIOLET_D, zorder=6)
# ---------------------------------------------------------------------------
# 3) Öğrenilen temsil — encoder (violet kutu)
# ---------------------------------------------------------------------------
box(54, 24, 17, 13, "#ece0f7", COL_VIOLET, lw=2.8, z=2)
ax.text(62.5, 33.0, "ÖĞRENİLEN\nTEMSİL", ha="center", va="center",
fontsize=11, color=COL_VIOLET_D, fontweight="bold", zorder=3)
ax.text(62.5, 27.5, "(encoder)", ha="center", va="center",
fontsize=9, color=COL_VIOLET_M, zorder=3, style="italic")
# ---------------------------------------------------------------------------
# 4) Downstream görev — az etiketli (gold)
# ---------------------------------------------------------------------------
box(80, 24, 16, 13, "#fbf3dd", COL_GOLD_D, lw=2.4, z=2)
ax.text(88, 33.0, "Downstream\ngörev", ha="center", va="center",
fontsize=10.5, color=COL_GOLD_D, fontweight="bold", zorder=3)
ax.text(88, 27.5, "AZ etiketli veri", ha="center", va="center",
fontsize=9, color=COL_TEXT, zorder=3)
# ---------------------------------------------------------------------------
# Oklar — boru hattı akışı
# ---------------------------------------------------------------------------
arrow(20.5, 30.5, 26.5, 30.5) # veri → pretext
arrow(49.5, 30.5, 53.5, 30.5) # pretext → temsil
arrow(71.5, 30.5, 79.5, 30.5, col=COL_GOLD_D) # transfer → downstream
ax.text(75.4, 33.2, "transfer\n/ dondur", ha="center", va="center",
fontsize=8.4, color=COL_GOLD_D, fontweight="bold", zorder=5)
# pre-train / downstream faz etiketleri (alt)
ax.text(27.5, 18.5, "pre-train (gözetimsiz)", ha="center", va="center",
fontsize=9.5, color=COL_VIOLET, fontweight="bold")
ax.text(84, 18.5, "downstream (transfer)", ha="center", va="center",
fontsize=9.5, color=COL_GOLD_D, fontweight="bold")
arrow(5.5, 16.8, 49.5, 16.8, col=COL_VIOLET, lw=1.4, style="-")
arrow(54, 16.8, 96, 16.8, col=COL_GOLD_D, lw=1.4, style="-")
# ---------------------------------------------------------------------------
# Annotation şeridi (alt)
# ---------------------------------------------------------------------------
box(5, 3.5, 91, 8.5, COL_BG, COL_VIOLET, lw=1.6, z=1)
ax.text(50, 7.7,
"SSL gözetim sinyalini VERİDEN üretir (etiketsiz); pre-train → downstream transfer",
ha="center", va="center", fontsize=10.2, color=COL_INK,
fontweight="bold", zorder=3)
plt.tight_layout()
```
::: {.callout-tip title="Builder Notu — Pre-train → Downstream"}
**Geriye (Hafta 8 + 1):** SSL, Hafta 8'in contrastive fikrinin geniş çerçevesi; pre-train→downstream, Hafta 1'in "temsil öğren" temasının pratik hattı. Etiketsiz gözetim = label'ı veriden uydurmak.
**İleriye:** Pre-train → fine-tune paradigması, tüm foundation modellerin (görü ve dil) çalışma biçimidir; SSL onu etiketsiz veriye açar.
:::
## (Misra — Konuk) Pretext Görev: Proxy ile Temsil Öğrenmek {#sec-pretext}
SSL'in kalbi **pretext (bahane) görevidir**: gerçek hedef olmayan, ama çözerken iyi bir temsil öğrenmeni sağlayan yapay bir tahmin görevi.
> "a pretext task is a prediction task that you solve... to learn a representation, and then you finally get to your downstream task where you want to use this representation to perform something meaningful." — Misra, 13:18
Kritik nüans: pretext görevinin kendisi **önemsizdir** (kimse "görüntünün döndürme açısı" gerçekten umursamaz). Önemli olan, onu çözmek için ağın öğrenmek **zorunda kaldığı** temsildir — yan ürün.
> "we are not really interested in predicting the rotations... we are just using this task as a proxy to learn some features." — Misra, 19:11
::: {.callout-tip title="Builder Notu — Pretext = Bahane"}
**Geriye (Hafta 1-2):** Pretext görev = supervised öğrenme (Hafta 1), ama etiket veriden otomatik üretilir; rotation tahmini = 4-yönlü cross-entropy (Hafta 2). "Yan ürün temsil" = Hafta 1 representation learning.
**İleriye:** "Proxy görevle temsil öğren" fikri, LLM'lerin next-token tahmininin (proxy) dev temsiller öğrenmesinin (yan ürün) ta kendisidir.
:::
## (Misra — Konuk) Pretext Örnekleri: Konum, Döndürme, Renklendirme {#sec-pretext-ornek}
Misra yaratıcı pretext görev örnekleri veriyor:
- **Göreli konum (relative position):** bir görüntüden iki yama al, ağa "ikincisi birinciye göre nerede?" diye sor. Bunu çözmek için ağ nesneleri anlamak zorunda kalır. (Nearest-neighbor görselleştirmesi, öğrenilen temsilin **anlamlı/semantik** olduğunu gösterir.)
- **Döndürme tahmini (rotation):** görüntüyü 0/90/180/270° döndür, ağa "kaç derece döndürdüm?" diye sor (4-yönlü sınıflandırma). En popüler pretext görevlerinden — uygulaması çok kolay.
> "you apply a rotation of 0, 90, 180, or 270 degrees... and you ask the network to predict what was the exact rotation applied — a four-way classification problem." — Misra, 18:13
- **Renklendirme (colorization):** gri görüntüden renkli hâlini tahmin et.
Hepsinin ortak mantığı: görevi çözmek "dünyayı anlamayı" gerektirir; bir nesneyi döndürdüğünü bilmek için nesnenin sınırlarını/yapısını kavraman gerekir. Misra'nın PIRL'i (Hafta 3, Hafta 8'de anılan) bu fikri contrastive bir çerçeveye taşır. @fig-pretext-rotation döndürme pretext'ini gerçek bir sentetik görüntü üzerinde gösteriyor: aynı görüntünün 0°/90°/180°/270° versiyonları, ve ağın çözdüğü 4-yönlü sınıflandırma sorusu.
```{python}
#| label: fig-pretext-rotation
#| fig-cap: "Rotation pretext görevi (Hafta 10 görü SSL): aynı sentetik görüntünün 0°/90°/180°/270° döndürülmüş dört versiyonu. Ağ \"kaç derece döndürüldü?\" sorusunu 4-yönlü sınıflandırma olarak çözer. Görevin kendisi önemsizdir; ağ doğru cevabı verebilmek için nesnenin yapısını ve yönelimini anlamak zorunda kalır — yararlı temsil (representation) bu zorunluluğun yan ürünüdür (Misra). Diğer pretext görevleri: göreli konum tahmini ve renklendirme."
img = make_synthetic_image(28)
rots = rotate_image_4way(img)
basliklar = ["0°", "90°", "180°", "270°"]
fig, axes = plt.subplots(1, 4, figsize=(11, 4.2))
fig.suptitle("Rotation Pretext — Görü için Kendinden-Denetimli Öğrenme (SSL)",
fontsize=13, color=COL_INK, fontweight="bold", y=1.04)
for ax, panel, baslik in zip(axes, rots, basliklar):
ax.imshow(panel, cmap="Purples", interpolation="nearest")
ax.set_title(baslik, fontsize=14, color=COL_VIOLET, fontweight="bold", pad=8)
ax.set_xticks([])
ax.set_yticks([])
for spine in ax.spines.values():
spine.set_color(COL_VIOLET)
spine.set_linewidth(2.2)
# Soru etiketi (ağın çözdüğü görev)
fig.text(0.5, 0.90, "Ağ sorar: \"Bu görüntü kaç derece döndürüldü?\" → 4-yönlü sınıflandırma",
ha="center", va="center", fontsize=11, color=COL_GOLD_D, fontweight="bold")
# Açıklayıcı altbaşlık (Misra — temsil yan ürün)
altbaslik = ("Görevin kendisi önemsiz; ağ doğru cevabı vermek için nesnenin yapısını ve "
"yönelimini anlamak ZORUNDA kalır → TEMSİL (representation) yan üründür (Misra).\n"
"Diğer pretext görevleri: göreli konum tahmini, renklendirme (colorization).")
fig.text(0.5, -0.06, altbaslik, ha="center", va="center", fontsize=9.5,
color=COL_TEXT, wrap=True)
plt.tight_layout(rect=[0, 0.0, 1, 0.88])
```
::: {.callout-tip title="Builder Notu — Döndürme = 4-Yönlü"}
**Geriye (Hafta 3 + 8):** Rotation/augmentation = Hafta 3 invariance/stationarity; PIRL = Hafta 8 contrastive (noise contrastive estimation). Pretext = etiketsiz proxy.
**İleriye:** Bu elle-tasarlanan pretext görevler, post-2020'de yerini daha ilkesel yöntemlere bıraktı (Bölüm 5) — ama "veriden gözetim uydur" fikri kaldı.
:::
## (Misra — Konuk) PIRL ve Değişmez Temsil {#sec-pirl}
Erken pretext görevlerin (rotation, jigsaw) bir zaafı vardı: ağ bazen görevi "kestirme" yollarla çözüp anlamsız temsil öğrenebilir. Misra'nın **PIRL** (Pretext-Invariant Representation Learning) yaklaşımı bunu düzeltir: temsilin, pretext dönüşümüne (örn. yamaların karıştırılması) **değişmez (invariant)** olmasını ister — yani orijinal ile dönüştürülmüş versiyonun temsilleri **benzer** olmalı (Hafta 8 pozitif çift), rastgele başka görüntüden **farklı** (negatif çift). PIRL, contrastive amaç (noise contrastive estimation) kullanır.
Bu, Hafta 8'in contrastive SSL'inin görüye uygulanmış, olgun hâlidir: pretext'i "tahmin et" yerine "değişmez ol" olarak kurar. @fig-pirl bu it-çek mantığını gömme uzayında gösteriyor: orijinal ve dönüştürülmüş versiyon yakına çekilir (pozitif), rastgele görüntü uzakta kalır (negatif).
```{python}
#| label: fig-pirl
#| fig-cap: "PIRL (Pretext-Invariant Representation Learning): pretext görevini tahmin etmek yerine dönüşüme değişmez temsil öğren. Solda şema — bir görsel ve ona uygulanan dönüşüm (yama karıştırma) paylaşımlı bir encoder'dan geçer; iki temsil ortak gömme uzayında birbirine yakın çekilir (pozitif çift). Sağda gömme uzayı — orijinal (ankraj) ≈ dönüştürülmüş versiyon (pozitif, kısa violet çizgi), ama rastgele başka bir görsel uzakta kalır (negatif, kesik gold çizgi). İt-çek mantığı: pozitifi çek, negatifi it → contrastive / NCE (Hafta 8)."
fig, (axL, axR) = plt.subplots(1, 2, figsize=(11, 5.0),
gridspec_kw={"width_ratios": [1.05, 1.0]})
# ---------------------------------------------------------------------------
# SOL PANEL — PIRL şeması: görsel → dönüşüm → ortak gömme
# ---------------------------------------------------------------------------
axL.set_xlim(0, 10)
axL.set_ylim(0, 10)
axL.axis("off")
axL.set_title("PIRL: pretext'i TAHMİN ETME → dönüşüme DEĞİŞMEZ ol",
color=COL_INK, fontsize=12, fontweight="bold", pad=10)
# Orijinal görsel ikonu (basit sentetik görüntü)
img = make_synthetic_image(28)
rots = rotate_image_4way(img) # 0/90/180/270° — yama-karıştırma pretext'i
# Orijinal kutu
def img_icon(ax, x, y, w, data, label, ec):
ax.imshow(data, cmap="Purples", extent=[x, x + w, y, y + w],
origin="upper", aspect="auto", zorder=3)
box = FancyBboxPatch((x, y), w, w, boxstyle="round,pad=0.02,rounding_size=0.05",
fc="none", ec=ec, lw=2.4, zorder=4)
ax.add_patch(box)
ax.text(x + w / 2, y - 0.45, label, ha="center", va="top",
fontsize=9.5, color=COL_TEXT, zorder=5)
img_icon(axL, 0.6, 6.3, 2.3, img, "orijinal görsel", COL_VIOLET)
# Dönüşüm uygulanmış (180° döndürülmüş = yama karıştır)
img_icon(axL, 0.6, 1.4, 2.3, rots[2], "dönüştürülmüş\n(yama karıştır)", COL_VIOLET_M)
# Dönüşüm oku (orijinal → dönüştürülmüş)
axL.add_patch(FancyArrowPatch((1.75, 6.1), (1.75, 3.85), arrowstyle="-|>",
mutation_scale=18, color=COL_GOLD_D, lw=2.2, zorder=2))
axL.text(2.05, 4.95, "DÖNÜŞÜM", ha="left", va="center", fontsize=9,
color=COL_GOLD_D, rotation=90, fontweight="bold")
# Encoder (paylaşımlı ağ) → ortak gömme uzayı
def encoder_box(ax, x, y):
b = FancyBboxPatch((x, y), 1.7, 1.0, boxstyle="round,pad=0.02,rounding_size=0.1",
fc="#ece0f7", ec=COL_VIOLET, lw=2.4, zorder=3)
ax.add_patch(b)
ax.text(x + 0.85, y + 0.5, "encoder\n(paylaşımlı)", ha="center", va="center",
fontsize=8.5, color=COL_TEXT, zorder=4)
return x + 1.7, y + 0.5
ex_t, ey_t = encoder_box(axL, 4.0, 6.8)
ex_b, ey_b = encoder_box(axL, 4.0, 1.4)
# Görsellerden encoder'a oklar
axL.add_patch(FancyArrowPatch((2.9, 7.45), (4.0, 7.3), arrowstyle="-|>",
mutation_scale=14, color=COL_VIOLET_M, lw=1.8, zorder=1))
axL.add_patch(FancyArrowPatch((2.9, 2.55), (4.0, 1.9), arrowstyle="-|>",
mutation_scale=14, color=COL_VIOLET_M, lw=1.8, zorder=1))
# Gömme noktaları (ortak uzayda yakın)
emb_top = (8.7, 6.0)
emb_bot = (8.95, 5.0)
axL.add_patch(FancyArrowPatch((ex_t, ey_t), (emb_top[0] - 0.25, emb_top[1] + 0.2),
arrowstyle="-|>", mutation_scale=14, color=COL_VIOLET, lw=1.8, zorder=1))
axL.add_patch(FancyArrowPatch((ex_b, ey_b), (emb_bot[0] - 0.25, emb_bot[1] - 0.2),
arrowstyle="-|>", mutation_scale=14, color=COL_VIOLET, lw=1.8, zorder=1))
# Ortak gömme uzayı çerçevesi
axL.add_patch(FancyBboxPatch((7.3, 3.6), 2.5, 3.6,
boxstyle="round,pad=0.02,rounding_size=0.1",
fc=COL_BG, ec=COL_GRID, lw=1.6, ls="--", zorder=0))
axL.text(8.55, 7.0, "ortak gömme\nuzayı", ha="center", va="center",
fontsize=8.5, color=COL_VIOLET_D, fontweight="bold", zorder=1)
for (px, py), c in [(emb_top, COL_VIOLET), (emb_bot, COL_VIOLET_M)]:
axL.add_patch(Circle((px, py), 0.18, fc=c, ec=COL_WHITE, lw=1.2, zorder=5))
# Yakınlık çizgisi (pozitif çift)
axL.plot([emb_top[0], emb_bot[0]], [emb_top[1], emb_bot[1]],
color=COL_VIOLET, lw=2.6, zorder=4)
axL.text(8.85, 5.5, "YAKIN", ha="left", va="center", fontsize=8.5,
color=COL_VIOLET_D, fontweight="bold", rotation=-60, zorder=6)
# ---------------------------------------------------------------------------
# SAĞ PANEL — gömme uzayında pozitif (yakın) vs negatif (uzak)
# ---------------------------------------------------------------------------
apply_style(axR)
axR.set_title("Gömme uzayı: orijinal ≈ dönüştürülmüş, ≠ rastgele",
color=COL_INK, fontsize=12, fontweight="bold", pad=10)
axR.set_xlim(-1.3, 1.3)
axR.set_ylim(-1.3, 1.3)
axR.set_xlabel("gömme boyutu 1")
axR.set_ylabel("gömme boyutu 2")
axR.set_aspect("equal")
# Ankraj: orijinal görselin gömmesi
anchor = np.array([0.25, 0.30])
# Pozitif: dönüştürülmüş versiyon — ankraja YAKIN
pos = anchor + np.array([0.18, -0.12])
# Negatif: rastgele başka görsel — UZAK
neg = np.array([-0.75, -0.65])
# Pozitif çift kısa çizgi (violet)
axR.plot([anchor[0], pos[0]], [anchor[1], pos[1]], color=COL_VIOLET,
lw=2.8, zorder=2, label="pozitif çift (yakın)")
# Negatif uzun çizgi (gold)
axR.plot([anchor[0], neg[0]], [anchor[1], neg[1]], color=COL_GOLD,
lw=2.2, ls="--", zorder=2, label="negatif (uzak)")
axR.scatter(*anchor, s=240, c=COL_VIOLET, edgecolors=COL_WHITE, lw=1.8,
zorder=4, marker="o")
axR.scatter(*pos, s=200, c=COL_VIOLET_M, edgecolors=COL_WHITE, lw=1.8,
zorder=4, marker="o")
axR.scatter(*neg, s=200, c=COL_GOLD, edgecolors=COL_WHITE, lw=1.8,
zorder=4, marker="s")
axR.annotate("orijinal\n(ankraj)", anchor, textcoords="offset points",
xytext=(8, 14), fontsize=8.5, color=COL_VIOLET_D, fontweight="bold")
axR.annotate("dönüştürülmüş\n(pozitif)", pos, textcoords="offset points",
xytext=(14, -28), fontsize=8.5, color=COL_VIOLET_M)
axR.annotate("rastgele görsel\n(negatif)", neg, textcoords="offset points",
xytext=(-6, -34), fontsize=8.5, color=COL_GOLD_D, fontweight="bold")
style_legend(axR, loc="upper right", fontsize=8.5)
# Alt açıklama bandı
axR.text(0.0, -1.18,
"İt-çek: pozitifi çek, negatifi it → contrastive / NCE (Hafta 8)",
ha="center", va="center", fontsize=8.8, color=COL_TEXT,
style="italic",
bbox=dict(boxstyle="round,pad=0.4", fc=COL_BG, ec=COL_GRID, lw=1.0))
plt.tight_layout()
```
::: {.callout-tip title="Builder Notu — PIRL = Değişmezlik"}
**Geriye (Hafta 8 + 3):** PIRL = contrastive SSL (Hafta 8) + invariance (Hafta 3); pozitif çift = dönüşülmüş versiyon, negatif = başka görüntü. NCE amacı = Hafta 8.
**İleriye:** "Dönüşüme değişmez temsil" fikri, post-2020 SSL'in (SimCLR/BYOL) tam çekirdeğidir (Bölüm 5).
:::
## (İleriye Köprü) SSL'in Post-2020 Evrimi — KURSTA YOK {#sec-post2020}
DLSP20 (Mart 2020), SSL'i **contrastive ve pretext-tabanlı** yöntemlerle (PIRL, MoCo, ClusterFit) anlatır. Bu kurstan **sonra** SSL hızla evrildi — ve aşağıdaki yöntemler bu kursta **YOKTUR** (yalnızca ileriye köprü olarak anılır). @fig-ssl-evolution bu kırılmayı bir zaman çizelgesinde gösteriyor: dikey çizgi Mart 2020'yi (kursun kayıt tarihi) işaretler, solda kursta işlenen yöntemler, sağda post-2020 yöntemleri.
::: {.callout-warning title="⚠️ İleriye Köprü Notu (post-2020 — KURSTA YOK)"}
- **SimCLR** (Şub 2020) — basit, büyük-batch contrastive (kursta MoCo var, SimCLR adıyla geçmez)
- **BYOL** (Haz 2020) — **negatif örneksiz** SSL (Hafta 8'in "çok negatif gerekir" sorununu çözer)
- **Barlow Twins** (2021) — çapraz-korelasyon düzenlileştirme
- **VICReg** (2021) — variance-invariance-covariance (LeCun'un "düşük-enerji hacmini sınırla" ilkesinin somut hâli)
- **MAE** (He ve ark., 2021) — masked autoencoder (DAE'nin ViT'teki hâli)
- **JEPA / I-JEPA / V-JEPA** (LeCun grubu, 2022-2024) — joint embedding predictive architecture; LeCun'un dünya-modeli + non-contrastive programının bugünkü zirvesi
Bunlar kurs içeriğine kurs terimi gibi **eklenmez**; Hafta 7-10'da öğrenilen EBM/SSL temelinin nereye evrildiğini göstermek için kullanılır.
:::
```{python}
#| label: fig-ssl-evolution
#| fig-cap: "Görüde öz-denetimli öğrenmenin (SSL) post-2020 evrimi. Dikey kesikli çizgi kursun kayıt tarihini (Mart 2020, DLSP20) işaretler: solda kursta işlenen contrastive/pretext-tabanlı yöntemler (MoCo, PIRL, ClusterFit), sağda kursta yer almayan post-2020 yöntemler (SimCLR, BYOL, Barlow Twins, VICReg, MAE, JEPA). Non-contrastive (BYOL/VICReg) ve JEPA, Hafta 8-9 fikirlerinin negatif-örnek gerektirmeyen evrimidir — ileriye köprü."
fig, ax = plt.subplots(figsize=(11, 5.4))
ax.axis("off")
# Zaman ekseni (yatay)
t0, t1 = 2018.0, 2023.0
ax.set_xlim(t0 - 0.4, t1 + 0.7)
ax.set_ylim(-3.0, 3.4)
# Yatay zaman ekseni çizgisi
axis_y = 0.0
ax.annotate("", xy=(t1 + 0.55, axis_y), xytext=(t0 - 0.3, axis_y),
arrowprops=dict(arrowstyle="-|>", color=COL_INK, lw=2.0))
ax.text(t1 + 0.6, axis_y - 0.32, "zaman", ha="right", va="top",
fontsize=9, color=COL_TEXT, style="italic")
for yr in range(2018, 2024):
ax.plot([yr, yr], [axis_y - 0.08, axis_y + 0.08], color=COL_INK, lw=1.2)
ax.text(yr, axis_y - 0.30, str(yr), ha="center", va="top",
fontsize=8.5, color=COL_TEXT)
# Dikey ayrım çizgisi — Mart 2020 (DLSP20)
split_x = 2020.2
ax.plot([split_x, split_x], [-2.7, 3.1], color=COL_GOLD_D, lw=2.2,
ls=(0, (5, 3)), zorder=1)
ax.text(split_x, 3.25, "Mart 2020 (DLSP20)", ha="center", va="bottom",
fontsize=9.5, color=COL_GOLD_D, fontweight="bold")
# Başlık etiketleri sol/sağ
ax.text(2018.0, 2.55, "KURSTA VAR", ha="left", va="center",
fontsize=12, color=COL_VIOLET, fontweight="bold")
ax.text(2020.55, 2.55, "POST-2020 — KURSTA YOK", ha="left", va="center",
fontsize=12, color=COL_GOLD_D, fontweight="bold")
# SOL — kursta var (violet dolu kutular): MoCo, PIRL, ClusterFit
left_methods = [("MoCo", 2019.9, 1.5), ("PIRL", 2019.85, 0.55),
("ClusterFit", 2019.95, -0.45)]
for name, mx, my in left_methods:
bx, bw, bh = mx - 0.95, 0.9, 0.62
box = FancyBboxPatch((bx, my - bh / 2), bw, bh,
boxstyle="round,pad=0.02,rounding_size=0.10",
fc="#ece0f7", ec=COL_VIOLET, lw=2.2, zorder=3)
ax.add_patch(box)
ax.text(bx + bw / 2, my, name, ha="center", va="center",
fontsize=9.5, color=COL_VIOLET_D, fontweight="bold", zorder=4)
# SAĞ — post-2020 (gold kesikli kutular): SimCLR, BYOL, Barlow Twins, VICReg, MAE, JEPA
right_methods = [("SimCLR", 2020.6, 1.7), ("BYOL", 2020.7, 0.7),
("Barlow Twins", 2021.2, -0.35), ("VICReg", 2021.9, 1.4),
("MAE", 2021.95, 0.35), ("JEPA", 2022.7, -0.55)]
for name, mx, my in right_methods:
bw, bh = 1.05, 0.6
bx = mx - bw / 2
box = FancyBboxPatch((bx, my - bh / 2), bw, bh,
boxstyle="round,pad=0.02,rounding_size=0.10",
fc=COL_BG, ec=COL_GOLD_D, lw=2.0,
ls=(0, (4, 2)), zorder=3)
ax.add_patch(box)
ax.text(mx, my, name, ha="center", va="center",
fontsize=9.0, color=COL_GOLD_D, fontweight="bold", zorder=4)
# Annotation kutusu (alt)
note = ("Kursta: contrastive / pretext-tabanlı (MoCo, PIRL, rotation görevi).\n"
"Sonrası: non-contrastive (BYOL / VICReg) + JEPA = Hafta 8-9 fikirlerinin\n"
"EVRİMİ — negatif-örnek gerektirmeyen SSL. KURSTA YOK (ileriye köprü).")
ax.text(2020.2, -2.45, note, ha="center", va="center", fontsize=8.6,
color=COL_TEXT,
bbox=dict(boxstyle="round,pad=0.5", fc=COL_WHITE, ec=COL_VIOLET, lw=1.3))
ax.set_title("Görüde Öz-Denetimli Öğrenme (SSL) — Post-2020 Evrimi",
fontsize=13, color=COL_INK, fontweight="bold", pad=14);
```
::: {.callout-tip title="Builder Notu — Post-2020 Evrim"}
**Geriye (Hafta 8-9):** Bu evrim, Hafta 8'in "contrastive'in çok-negatif sorunu" + Hafta 9'un "düşük-enerji hacmini sınırla" ilkesinin doğrudan devamıdır — non-contrastive (BYOL/VICReg) tam bu iki fikri birleştirir.
**İleriye:** JEPA, LeCun'un tüm kurs boyunca tohumladığı fikirlerin (EBM + world model + non-contrastive SSL) bugünkü sentezidir.
:::
## Geçiş: Misra'dan Canziani'ye {#sec-gecis-d10}
Misra etiketsiz veriden temsil öğrenmeyi (SSL) anlattı. Şimdi **Canziani** başka bir "gözetimsiz" problemi gösteriyor: bir sistemin **dünya modelini** ve onu kontrol eden **politikayı** kendi kendine öğrenmesi. Meşhur "kamyon geri sokma" (truck backer-upper) örneğiyle, Hafta 9'un soyut dünya modelini somut, çalışan bir koda döküyor.
## (Canziani) Truck Backer-Upper: Emulator + Controller {#sec-emulator-controller}
Canziani klasik bir öz-öğrenme problemi gösteriyor: bir **römorklu kamyonu** keyfi bir başlangıçtan yükleme rampasına geri sokmak için bir **doğrusal-olmayan kontrolör** öğrenmek (yalnızca geri vites).
> "[we are] trying to design, by self-learning, a nonlinear controller to control the steering of a trailer truck while backing up to a loading dock." — Canziani, 1:53
Durum 6 değişkenle tanımlı (kabin açısı $\theta_{cab}$, römork açısı $\theta_{trailer}$, $X$, $Y$, ve hızlar). İki ağ var:
1. **Emulator:** kamyon-römork **kinematiğini** öğrenir — mevcut durum + eylemden (direksiyon) bir sonraki durumu öngörür. Bu bir **dünya modelidir**:
$$
s_{t+1} = f(s_t, a_t)
$$
2. **Controller:** emulator'ı (yani dünyayı) kontrol eden **politika** — her adımda hangi direksiyonu vereceğini öğrenir.
@fig-emulator-controller bu döngüsel mimariyi gösteriyor: controller durumdan eylem üretir, emulator durum + eylemden bir sonraki durumu öngörür, geri besleme döngüsü kamyonu rampaya geri sokar.
```{python}
#| label: fig-emulator-controller
#| fig-cap: "PPUU mimarisi: controller (politika π) durum sₜ'den eylem aₜ (direksiyon) üretir; emulator (Hafta 9'un dünya modeli) sₜ ve aₜ'den bir sonraki durumu sₜ₊₁=f(sₜ,aₜ) tahmin eder; geri besleme döngüsü kamyon+römorku rampaya geri sokar."
np.random.seed(0)
fig, ax = plt.subplots(figsize=(10.5, 5.4))
ax.set_xlim(0, 10)
ax.set_ylim(0, 6.4)
ax.axis("off")
ax.set_facecolor(COL_WHITE)
ax.set_title("PPUU: Emulator (dünya modeli) + Controller (politika) — kamyonu rampaya geri sok",
color=COL_INK, fontsize=12.5, pad=12, fontweight="bold")
# Düğüm konumları (döngüsel şema)
state_xy = (1.55, 4.55)
ctrl_xy = (5.0, 5.35)
action_xy = (8.55, 4.55)
emu_xy = (5.0, 1.95)
next_xy = (1.55, 1.95)
# Durum ikonu — basit kamyon+römork
def draw_truck(ax, cx, cy, scale=1.0, label_sub="t"):
ax.add_patch(Rectangle((cx - 0.62*scale, cy - 0.12*scale), 0.70*scale, 0.30*scale,
fc=COL_VIOLET_SOFT, ec=COL_VIOLET_D, lw=1.4, zorder=4))
ax.add_patch(Rectangle((cx + 0.12*scale, cy - 0.12*scale), 0.34*scale, 0.34*scale,
fc=COL_VIOLET, ec=COL_VIOLET_D, lw=1.4, zorder=4))
for wx in (cx - 0.45*scale, cx - 0.10*scale, cx + 0.30*scale):
ax.add_patch(Circle((wx, cy - 0.14*scale), 0.07*scale, fc=COL_INK, ec=COL_INK, zorder=5))
ax.text(cx, cy + 0.40*scale, f"durum s$_{label_sub}$", ha="center", va="bottom",
fontsize=10.5, color=COL_VIOLET_D, fontweight="bold", zorder=6)
sb = FancyBboxPatch((state_xy[0]-1.05, state_xy[1]-0.70), 2.10, 1.30,
boxstyle="round,pad=0.02,rounding_size=0.10",
fc=COL_BG, ec=COL_VIOLET, lw=2.0, zorder=2)
ax.add_patch(sb)
draw_truck(ax, state_xy[0], state_xy[1]-0.05, scale=1.0, label_sub="t")
nb = FancyBboxPatch((next_xy[0]-1.05, next_xy[1]-0.70), 2.10, 1.30,
boxstyle="round,pad=0.02,rounding_size=0.10",
fc="#ece0f7", ec=COL_VIOLET, lw=2.0, zorder=2)
ax.add_patch(nb)
draw_truck(ax, next_xy[0], next_xy[1]-0.05, scale=1.0, label_sub="t+1")
ax.text(next_xy[0], next_xy[1]-0.92, "s$_{t+1}$ = f(s$_t$, a$_t$)",
ha="center", va="top", fontsize=10, color=COL_GOLD_D, fontweight="bold")
# CONTROLLER (politika)
cb = FancyBboxPatch((ctrl_xy[0]-1.45, ctrl_xy[1]-0.55), 2.90, 1.10,
boxstyle="round,pad=0.02,rounding_size=0.12",
fc=COL_VIOLET, ec=COL_VIOLET_D, lw=2.6, zorder=3)
ax.add_patch(cb)
ax.text(ctrl_xy[0], ctrl_xy[1]+0.13, "CONTROLLER", ha="center", va="center",
fontsize=12, color=COL_WHITE, fontweight="bold", zorder=4)
ax.text(ctrl_xy[0], ctrl_xy[1]-0.22, "politika π(s$_t$)", ha="center", va="center",
fontsize=9.5, color="#e8d6f7", zorder=4)
# EMULATOR (dünya modeli)
eb = FancyBboxPatch((emu_xy[0]-1.45, emu_xy[1]-0.55), 2.90, 1.10,
boxstyle="round,pad=0.02,rounding_size=0.12",
fc=COL_GOLD, ec=COL_GOLD_D, lw=2.6, zorder=3)
ax.add_patch(eb)
ax.text(emu_xy[0], emu_xy[1]+0.13, "EMULATOR", ha="center", va="center",
fontsize=12, color=COL_INK, fontweight="bold", zorder=4)
ax.text(emu_xy[0], emu_xy[1]-0.22, "dünya modeli s$_{t+1}$=f(s$_t$,a$_t$)", ha="center", va="center",
fontsize=9.0, color="#5a4408", zorder=4)
# Eylem aₜ (direksiyon ikonu)
ax.add_patch(Circle(action_xy, 0.40, fc=COL_BG, ec=COL_VIOLET, lw=2.2, zorder=3))
ax.add_patch(Circle(action_xy, 0.13, fc=COL_VIOLET, ec=COL_VIOLET_D, lw=1.2, zorder=4))
for ang in (90, 210, 330):
a = np.deg2rad(ang)
ax.plot([action_xy[0], action_xy[0]+0.37*np.cos(a)],
[action_xy[1], action_xy[1]+0.37*np.sin(a)], color=COL_VIOLET, lw=2.0, zorder=4)
ax.text(action_xy[0], action_xy[1]+0.62, "eylem a$_t$", ha="center", va="bottom",
fontsize=10.5, color=COL_VIOLET_D, fontweight="bold")
ax.text(action_xy[0], action_xy[1]-0.62, "(direksiyon)", ha="center", va="top",
fontsize=8.5, color=COL_TEXT)
# Oklar (döngü)
def arrow(ax, p0, p1, color, rad=0.0, lw=2.3):
ax.add_patch(FancyArrowPatch(p0, p1, arrowstyle="-|>", mutation_scale=20,
color=color, lw=lw,
connectionstyle=f"arc3,rad={rad}", zorder=2))
arrow(ax, (state_xy[0]+0.85, state_xy[1]+0.45), (ctrl_xy[0]-1.45, ctrl_xy[1]-0.05), COL_VIOLET_M, rad=-0.18)
arrow(ax, (ctrl_xy[0]+1.45, ctrl_xy[1]-0.05), (action_xy[0]-0.05, action_xy[1]+0.50), COL_VIOLET_M, rad=-0.18)
arrow(ax, (action_xy[0]-0.05, action_xy[1]-0.50), (emu_xy[0]+1.45, emu_xy[1]+0.05), COL_GOLD_D, rad=-0.18)
arrow(ax, (state_xy[0], state_xy[1]-0.70), (emu_xy[0]-1.20, emu_xy[1]+0.45), COL_GOLD_D, rad=0.12, lw=1.9)
arrow(ax, (emu_xy[0]-1.45, emu_xy[1]+0.05), (next_xy[0]+0.95, next_xy[1]-0.10), COL_GOLD_D, rad=-0.12)
ax.add_patch(FancyArrowPatch((next_xy[0]-0.55, next_xy[1]+0.70), (state_xy[0]-0.55, state_xy[1]-0.70),
arrowstyle="-|>", mutation_scale=18, color=COL_VIOLET_D, lw=2.0,
ls=(0,(4,2)), connectionstyle="arc3,rad=0.0", zorder=2))
ax.text(state_xy[0]-1.30, (state_xy[1]+next_xy[1])/2, "geri\nbesleme",
ha="right", va="center", fontsize=8.5, color=COL_VIOLET_D, fontstyle="italic")
# Hedef: rampa
ramp_x, ramp_y = 9.0, 1.35
ax.add_patch(plt.Polygon([[ramp_x-0.7, ramp_y], [ramp_x+0.7, ramp_y], [ramp_x+0.7, ramp_y+0.55]],
closed=True, fc=COL_GOLD, ec=COL_GOLD_D, lw=1.6, alpha=0.85, zorder=3))
ax.text(ramp_x, ramp_y-0.18, "HEDEF: rampa", ha="center", va="top",
fontsize=9.5, color=COL_GOLD_D, fontweight="bold")
# Annotation
note = ("emulator = dünya modeli (Hafta 9, s$_{t+1}$=f(s$_t$,a$_t$)); "
"controller = politika (direksiyon);\n"
"amaç: kamyonu rampaya geri sokmak")
ax.text(5.0, 0.30, note, ha="center", va="center", fontsize=9.0, color=COL_TEXT,
bbox=dict(boxstyle="round,pad=0.5", fc=COL_BG, ec=COL_VIOLET, lw=1.4))
plt.show()
```
::: {.callout-tip title="Builder Notu — Emulator = Dünya Modeli"}
**Geriye (Hafta 9 + 6):** Emulator = Hafta 9'un dünya modeli (gelecek durumu öngörür); controller = politika. Durum geçişi $s_{t+1} = f(s_t, a_t)$, Hafta 6 RNN recurrence'ının kontrol hâli.
**İleriye:** Emulator + controller ayrımı, modern **model-based RL**'in (önce dünya modeli öğren, sonra içinde planla) temel kalıbıdır.
:::
## (Canziani) Önce Dünyayı Öğren, Sonra İçinde Planla {#sec-planla}
Canziani eğitimin sırasını veriyor: önce **emulator** eğitilir (kamyonu sürerek toplanan verilerle kinematiği öğrenir — bir sonraki durumu doğru öngörsün). Sonra **controller**, *eğitilmiş emulator üzerinden* eğitilir: controller bir direksiyon önerir, emulator sonucu öngörür, ve "rampaya ne kadar yaklaştık?" maliyeti geriye yayılır (backprop) — controller'ı iyileştirir.
> "we have to train a network to be an emulator of the truck and trailer kinematics... [then a] controller to control the emulator." — Canziani, 15:16
Bu PPUU'nun (prediction and policy learning under uncertainty) çekirdeğidir: gerçek dünyada deneme-yanılma pahalı/tehlikeli olduğundan, **öğrenilmiş bir dünya modeli içinde** planlarsın. Backprop, controller'ı emulator zinciri boyunca eğitir — Hafta 5'in autograd'ı, Hafta 6'nın zaman-zinciri burada birleşir. @fig-ppuu-backprop bu iki aşamayı gösteriyor: önce emulator kinematiği öğrenir, sonra controller öğrenilmiş emulator zinciri içinde planlar ve maliyet gradyanı zincir boyunca geri akar.
```{python}
#| label: fig-ppuu-backprop
#| fig-cap: "PPUU iki aşamalı şeması: önce dünyayı öğren, sonra içinde planla. AŞAMA 1'de emülatör kamyon verisinden kinematiği öğrenir (ŝₜ₊₁'i doğru öngörür); AŞAMA 2'de controller, öğrenilmiş emülatör zinciri içinde planlar — ileri akış (violet) aₜ → sₜ₊₁ → sₜ₊₂ → rampaya uzaklık maliyeti üretir, maliyet gradyanı emülatör zinciri boyunca geri (gold backprop) controller'a akar. Hafta 5 autograd + Hafta 6 BPTT + Hafta 7 EBM köprüleri."
fig, (axA, axB) = plt.subplots(2, 1, figsize=(10.5, 6.6))
fig.suptitle("Önce dünyayı öğren, sonra içinde planla (PPUU)",
fontsize=14, fontweight="bold", color=COL_INK, y=0.985)
def box(ax, x, y, w, h, label, learned=True, fs=9.5):
fc = "#ece0f7" if learned else COL_BG
ec = COL_VIOLET if learned else COL_GOLD_D
lw = 2.4 if learned else 2.0
ax.add_patch(FancyBboxPatch(
(x - w / 2, y - h / 2), w, h,
boxstyle="round,pad=0.02,rounding_size=0.06",
fc=fc, ec=ec, lw=lw, zorder=2))
ax.text(x, y, label, ha="center", va="center",
fontsize=fs, color=COL_TEXT, zorder=3)
def arrow(ax, x0, y0, x1, y1, color=COL_VIOLET_M, lw=1.9, ls="-"):
ax.add_patch(FancyArrowPatch(
(x0, y0), (x1, y1), arrowstyle="-|>", mutation_scale=15,
color=color, lw=lw, linestyle=ls, zorder=1,
connectionstyle="arc3,rad=0.0"))
# AŞAMA 1 — Emülatör eğit: kamyon verisi → emülatör kinematiği öğrenir
axA.set_xlim(0, 12)
axA.set_ylim(-1.3, 1.5)
axA.axis("off")
axA.text(0.15, 1.30, "AŞAMA 1 — Emülatör eğit",
fontsize=11.5, fontweight="bold", color=COL_VIOLET_D)
box(axA, 1.7, 0.0, 2.4, 1.0, "Kamyon\nverisi\n(sₜ, aₜ, sₜ₊₁)", learned=False)
box(axA, 6.0, 0.0, 2.4, 1.0, "EMÜLATÖR\nkinematiği\nöğrenir", learned=True)
box(axA, 10.2, 0.0, 2.6, 1.0, "öngörü ŝₜ₊₁\n≈ gerçek sₜ₊₁", learned=False)
arrow(axA, 3.0, 0.0, 4.75, 0.0)
arrow(axA, 7.25, 0.0, 8.85, 0.0)
axA.text(6.0, -0.95, "denetimli: ŝₜ₊₁'i doğru öngörsün",
ha="center", fontsize=8.5, color=COL_TEXT, style="italic")
# AŞAMA 2 — Controller eğit: zincir + geri-akan maliyet (backprop)
axB.set_xlim(0, 12)
axB.set_ylim(-1.6, 1.7)
axB.axis("off")
axB.text(0.15, 1.50, "AŞAMA 2 — Controller eğit (öğrenilmiş model içinde planla)",
fontsize=11.5, fontweight="bold", color=COL_VIOLET_D)
# İleri zincir: controller → aₜ → emülatör → sₜ₊₁ → ... → maliyet
yc = 0.25
box(axB, 1.5, yc, 2.0, 0.9, "CONTROLLER\n→ aₜ", learned=True, fs=9)
box(axB, 4.4, yc, 2.0, 0.9, "EMÜLATÖR\nsₜ → sₜ₊₁", learned=True, fs=9)
box(axB, 7.3, yc, 2.0, 0.9, "EMÜLATÖR\nsₜ₊₁ → sₜ₊₂", learned=True, fs=9)
box(axB, 10.3, yc, 2.3, 0.9, "MALİYET\nrampaya\nUZAKLIK", learned=False, fs=9)
# ileri oklar (violet)
arrow(axB, 2.5, yc, 3.4, yc)
arrow(axB, 5.4, yc, 6.3, yc)
arrow(axB, 8.3, yc, 9.15, yc)
axB.text(6.4, yc + 0.78, "ileri: aₜ → sₜ₊₁ → sₜ₊₂ → … → rampa",
ha="center", fontsize=8.5, color=COL_VIOLET, style="italic")
# Geri-akan gradient (gold ok) — maliyet emülatör zinciri boyunca controller'a
ygrad = -0.95
for (x0, x1) in [(10.3, 7.3), (7.3, 4.4), (4.4, 1.5)]:
arrow(axB, x0, ygrad, x1, ygrad, color=COL_GOLD, lw=2.6)
# bağlantı çizgileri (kutu altları → gradient hattı)
for xc in [1.5, 4.4, 7.3, 10.3]:
axB.plot([xc, xc], [yc - 0.45, ygrad], color=COL_GOLD_D,
lw=0.9, ls=":", zorder=0)
axB.text(6.0, ygrad - 0.42,
"geri: ∂maliyet emülatör ZİNCİRİ boyunca controller'a akar (backprop)",
ha="center", fontsize=9, color=COL_GOLD_D, fontweight="bold")
# Açıklama notu (alt şerit)
note = ("gerçek dünyada deneme pahalı → ÖĞRENİLMİŞ model içinde planla · "
"controller = emülatör zinciri boyunca backprop "
"(Hafta 5 autograd + Hafta 6 BPTT) · maliyet = Hafta 7 EBM")
fig.text(0.5, 0.015, note, ha="center", fontsize=8.2, color=COL_TEXT,
bbox=dict(boxstyle="round,pad=0.4", fc=COL_BG, ec=COL_GRID, lw=1.0))
plt.tight_layout(rect=[0, 0.05, 1, 0.96])
```
::: {.callout-tip title="Builder Notu — Önce Öğren Sonra Planla"}
**Geriye (Hafta 5-6-9):** Controller eğitimi = emulator zinciri boyunca backprop (Hafta 5 autograd + Hafta 6 BPTT); emulator = dünya modeli (Hafta 9). "Maliyet" = rampaya uzaklık enerjisi (Hafta 7 EBM).
**İleriye:** "Öğrenilmiş model içinde planla" = model-based RL, MPC (model predictive control), ve LeCun'un dünya-modeli programının pratiği.
:::
## Bu Dersin Özeti {#sec-ozet-d10}
1. **SSL (Misra):** etiketli veri pahalı → etiketsiz veriden temsil öğren, downstream'e taşı (pre-train → fine-tune).
2. **Pretext görev:** yapay bir proxy tahmin görevi (göreli konum, döndürme, renklendirme); kendisi önemsiz, **temsil** yan ürünü değerli.
3. **PIRL:** pretext'i "tahmin et" yerine "dönüşüme değişmez ol" olarak kurar (contrastive, Hafta 8).
4. **Post-2020 SSL (KURSTA YOK):** BYOL/VICReg/MAE/JEPA — Hafta 8-9 fikirlerinin evrimi (İleriye Köprü).
5. **PPUU (Canziani):** emulator (dünya modeli, $s_{t+1}=f(s_t,a_t)$) + controller (politika); truck backer-upper.
6. **Önce dünyayı öğren, sonra içinde planla:** controller, eğitilmiş emulator zinciri boyunca backprop ile eğitilir — model-based RL'in kalbi.
::: {.callout-important title="Tek Bir Cümle"}
Öz-denetimli öğrenme, etiketsiz veriden bir pretext görev (döndürme, konum, renklendirme) uydurup çözerek anlamlı temsiller öğrenir ve downstream'e taşır (Misra); PPUU ise bir dünya modeli (emulator) öğrenip onun içinde bir politika (controller) eğiterek planlamayı pratiğe döker (Canziani) — ikisi de etiketsiz/gözetimsiz öğrenmenin, Hafta 7-9'da kurulan EBM/world-model temelinin uygulamalarıdır.
:::
## Kontrol Soruları {#sec-kontrol-d10}
::: {.callout-note collapse="true" title="Soru 1: SSL supervised learning'den nasıl farklıdır? Pretext görev nedir, neden \"önemsiz\"dir?"}
**Cevap:** Supervised learning insan **etiketi** ister (pahalı); SSL gözetim sinyalini **verinin kendisinden** üretir (etiketsiz). Bir **pretext (bahane) görev**, gerçek hedef olmayan ama çözerken iyi bir temsil öğrenmeni sağlayan yapay bir tahmin görevidir (Misra 13:18) — örn. görüntünün döndürme açısını tahmin et. Görevin kendisi **önemsizdir** (kimse döndürme açısını gerçekten umursamaz); değerli olan, onu çözmek için ağın öğrenmek zorunda kaldığı **temsildir** (yan ürün, Misra 19:11). Sonra bu temsil etiketin az olduğu downstream görevlere aktarılır.
:::
::: {.callout-note collapse="true" title="Soru 2: Üç pretext görev örneği ver. \"Döndürme tahmini\" neden anlamlı temsil öğretir?"}
**Cevap:** (1) **Göreli konum:** iki yamanın birbirine göre konumunu tahmin et; (2) **Döndürme:** görüntüyü 0/90/180/270° döndür, açıyı tahmin et (4-yönlü sınıflandırma, Misra 18:13); (3) **Renklendirme:** gri görüntüyü renklendir. Döndürme anlamlı temsil öğretir çünkü bir nesnenin hangi açıyla döndürüldüğünü bilmek için ağın nesnenin **sınırlarını, yapısını, yönelimini** kavraması gerekir — yani "dünyayı anlamak" zorunda kalır. Bu yapısal anlama, downstream görevlere yarayan temsildir.
:::
::: {.callout-note collapse="true" title="Soru 3: Post-2020 SSL yöntemleri (BYOL, VICReg, MAE, JEPA) bu kursta var mı? Hangi kurs fikirlerinin evrimidir?"}
**Cevap:** **Hayır, bu kursta YOK** — DLSP20 Mart 2020'de çekildi, hepsi sonra geldi (yalnızca ileriye köprü olarak anılır). **BYOL** (Haz 2020) Hafta 8'in "contrastive çok negatif ister" sorununu çözer (negatif-örneksiz SSL); **VICReg** (2021) Hafta 9'un "düşük-enerji hacmini sınırla" ilkesinin somut hâli (variance-invariance-covariance); **MAE** (2021) Hafta 8'in DAE'sinin ViT hâli (masked autoencoder); **JEPA** (2022-24, LeCun) EBM + world model + non-contrastive SSL'in sentezi. Yani hepsi Hafta 7-10'da öğrenilen EBM/SSL temelinin doğal devamıdır.
:::
::: {.callout-note collapse="true" title="Soru 4: (Builder) PPUU'da emulator ve controller ne yapar? Controller nasıl eğitilir? Hangi haftalarla bağlantılı?"}
**Cevap:** **Emulator** kamyon-römork kinematiğini öğrenen bir **dünya modelidir**: mevcut durum + eylemden sonraki durumu öngörür:
$$
s_{t+1} = f(s_t, a_t)
$$
**Controller** bir **politikadır**: her adımda hangi direksiyonu vereceğini öğrenir. **Eğitim sırası:** önce emulator eğitilir (kinematiği öğrensin); sonra controller, *eğitilmiş emulator üzerinden* eğitilir — controller direksiyon önerir, emulator sonucu öngörür, "rampaya uzaklık" maliyeti emulator zinciri boyunca **backprop** ile controller'a yayılır (Canziani 15:16). Bağlantılar: emulator = Hafta 9 dünya modeli; zincir-backprop = Hafta 5 autograd + Hafta 6 BPTT; maliyet = Hafta 7 EBM. Bu, model-based RL'in kalbidir.
:::
## Egzersizler {#sec-egzersiz-d10}
**Egzersiz 1 (Pretext görev kur).** CIFAR-10'da etiketleri **yok say**; her görüntüyü rastgele 0/90/180/270° döndür ve açıyı tahmin eden bir ağ eğit (4-yönlü sınıflandırma). Sonra bu ağın özniteliklerini dondurup üstüne küçük bir sınıflandırıcı eğit — etiketsiz pretext'in downstream'e ne kadar yardım ettiğini ölç.
```python
import torch
# Pretext gorevi: ETIKETSIZ goruntuyu dondur, ACIYI tahmin ettir (4-yonlu).
# Donme acisi "bedava etiket" uretir -> oz-denetimli gozetim sinyali.
def make_rotation_batch(images):
# images: [B, C, H, W] -> her ornek icin rastgele 0/90/180/270 dondur
B = images.shape[0]
ks = torch.randint(0, 4, (B,)) # 4 sinif (bedava etiket)
rotated = torch.stack([torch.rot90(images[i], int(ks[i]), dims=[-2, -1])
for i in range(B)])
return rotated, ks # (girdi, otomatik etiket)
imgs = torch.rand(8, 3, 32, 32)
rot, labels = make_rotation_batch(imgs)
print(f"pretext etiketleri (donme sinifi) = {labels.tolist()}")
# Sonra: encoder'i pretext ile egit -> ozellikleri DONDUR ->
# ustune kucuk siniflandirici (downstream) -> etiketsiz on-egitimin katkisi
```
**Egzersiz 2 (Nearest neighbor).** Pretext-eğitilmiş bir ağın öznitelik uzayında, bir sorgu görüntüsüne en yakın komşuları bul. Komşular anlamlı (aynı nesne sınıfı) mı? Bu, temsilin "semantik" olduğunu nasıl gösterir (Misra'nın yöntemi)?
```python
import numpy as np
# Ozellik uzayinda en yakin komsu: temsil "semantik" mi?
# Anlamli temsilde -> en yakin komsular AYNI nesne sinifindan olur.
def nearest_neighbors(query_feat, bank_feats, k=5):
# kosinus benzerligi (normalize edip ic carpim)
q = query_feat / (np.linalg.norm(query_feat) + 1e-9)
B = bank_feats / (np.linalg.norm(bank_feats, axis=1, keepdims=True) + 1e-9)
sims = B @ q
return np.argsort(-sims)[:k] # en benzer k komsu
rng = np.random.default_rng(0)
bank = rng.normal(0, 1, (100, 64)) # 100 goruntunun ozellikleri
query = bank[7] + rng.normal(0, 0.05, 64) # 7'ye yakin bir sorgu
print("en yakin komsular:", nearest_neighbors(query, bank))
# komsular ANLAMLI sinif paylasiyorsa -> temsil semantik (pretext ise yaramis)
```
**Egzersiz 3 (PIRL = invariance).** Bir görüntü ve onun bir dönüşümü (yama karıştırma) için temsillerin **benzer**, rastgele başka bir görüntününkinden **farklı** olmasını isteyen bir contrastive kayıp kur. Bu, Hafta 8 pozitif/negatif çiftiyle nasıl aynıdır?
```python
import torch
import torch.nn.functional as F
# PIRL: orijinal ile DONUSTURULMUS versiyon BENZER (pozitif),
# rastgele baska goruntu FARKLI (negatif) -> contrastive (Hafta 8).
def pirl_loss(z_orig, z_transformed, z_negatives, tau=0.1):
z_orig = F.normalize(z_orig, dim=-1)
z_pos = F.normalize(z_transformed, dim=-1)
z_neg = F.normalize(z_negatives, dim=-1)
pos = (z_orig * z_pos).sum(-1, keepdim=True) / tau # pozitif benzerlik
neg = z_orig @ z_neg.t() / tau # negatif benzerlikler
logits = torch.cat([pos, neg], dim=1) # [pozitif | negatifler]
target = torch.zeros(len(z_orig), dtype=torch.long) # pozitif = indeks 0
return F.cross_entropy(logits, target) # NCE = Hafta 8
z_o = torch.randn(4, 64); z_t = z_o + 0.1 * torch.randn(4, 64) # pozitif ~ orijinal
z_n = torch.randn(16, 64) # rastgele negatifler
print(f"PIRL contrastive kayip = {pirl_loss(z_o, z_t, z_n).item():.3f}")
# pozitifi cek, negatifi it -> Hafta 8 pozitif/negatif cifti ile AYNI mantik
```
**Egzersiz 4 (Post-2020 ayrımı).** Şu yöntemleri "kursta var" / "kursta yok (post-2020)" diye ayır: MoCo, PIRL, BYOL, ClusterFit, VICReg, MAE, JEPA. Her "yok" için hangi kurs fikrinin evrimi olduğunu yaz.
```python
# Kursta VAR (DLSP20, Mart 2020) vs YOK (post-2020 ileriye kopru).
kursta_var = ["MoCo", "PIRL", "ClusterFit"] # contrastive / pretext-tabanli
post_2020 = {
"BYOL": "Hafta 8 'cok negatif gerekir' -> negatif-orneksiz SSL",
"VICReg": "Hafta 9 'dusuk-enerji hacmini sinirla' -> var-inv-cov",
"MAE": "Hafta 8 DAE -> masked autoencoder (ViT)",
"JEPA": "EBM + world model + non-contrastive SSL sentezi (LeCun)",
}
for m in ["MoCo", "PIRL", "BYOL", "ClusterFit", "VICReg", "MAE", "JEPA"]:
if m in kursta_var:
print(f"{m:12s} -> KURSTA VAR")
else:
print(f"{m:12s} -> KURSTA YOK (post-2020): {post_2020[m]}")
# hepsi Hafta 7-10 EBM/SSL temelinin dogal devami (kursta YOK)
```
**Egzersiz 5 (Hafta 11 habercisi — aktivasyon/kayıp + PPUU).** Hafta 11'de LeCun aktivasyon ve kayıp fonksiyonlarını (EBM kayıpları dahil) sistematik anlatacak; Canziani PPUU'yu sürdürecek. (a) Şimdiye kadar gördüğün kayıpları (cross-entropy, MSE, contrastive, reconstruction) "EBM enerjisini şekillendirme" çerçevesinde nasıl gruplarsın? (b) Bir EBM için "marj kaybı (hinge/margin loss)" neden mantıklıdır (pozitif-negatif enerji farkını zorlar)?
```python
import torch
import torch.nn.functional as F
# (a) Kayiplar = "enerjiyi sekillendirme" cercevesinde:
# cross-entropy/MSE -> dogruya DUSUK enerji (push down);
# contrastive -> negatife YUKSEK enerji (push up);
# reconstruction -> manifolda DUSUK enerji (off-manifold yuksek).
# (b) Marj kaybi: E(pozitif) ile E(negatif) arasinda en az 'm' fark ZORLA.
def margin_loss(E_pos, E_neg, m=1.0):
# pozitif enerjisi DUSUK, negatif YUKSEK olsun; aradaki marj >= m
return F.relu(E_pos - E_neg + m).mean()
E_pos = torch.tensor([0.2, 0.1, 0.3]) # gercek -> DUSUK enerji
E_neg = torch.tensor([1.5, 1.8, 1.2]) # sahte -> YUKSEK enerji
print(f"marj kaybi = {margin_loss(E_pos, E_neg).item():.3f}")
# marj zaten saglaniyorsa kayip ~0; aksi halde pozitifi bas, negatifi yukselt
# -> Hafta 7 EBM "veride dusuk, disinda yuksek" sekli (Hafta 11'de sistematik)
```
## Sonraki Ders İçin Hazırlık {#sec-sonraki-d10}
::: {.callout-warning title="Sonraki Hafta — H11: Aktivasyon/Kayıp Fonksiyonları ve Öngörülü Politika (PPUU)"}
**Kayıplar EBM çatısına oturuyor.** Bu hafta görüde SSL'i (pretext görev → temsil → transfer, PIRL = değişmezlik) ve PPUU'yu (emulator + controller, önce dünyayı öğren sonra içinde planla) kapattık. Hafta 11'de **LeCun** aktivasyon ve kayıp fonksiyonlarını (özellikle **EBM kayıpları**) sistematik ele alacak; Canziani PPUU'yu (belirsizlik altında politika) derinleştirecek. Egzersiz 1 (pretext görev) ve Egzersiz 5 (kayıp = enerji şekillendirme) tam bu derse hazırlar.
:::
**Hafta 11: Aktivasyon/Kayıp Fonksiyonları ve Öngörülü Politika (PPUU)** — LeCun (Lecture) + Canziani (Practicum)
Hafta 11'de LeCun aktivasyon ve kayıp fonksiyonlarını (özellikle **EBM kayıpları**) sistematik ele alacak; Canziani PPUU'yu (belirsizlik altında politika) derinleştirecek.
**Hafta 11 öncesi yapılacak:**
- Egzersiz 1 (pretext görev) ve Egzersiz 5 (kayıp = enerji şekillendirme) çöz.
- "Pretext görev = proxy, temsil = yan ürün" ve "emulator = dünya modeli" cümlelerini kendi sözcüklerinle yaz.
- Hafta 7-9 EBM zincirini hatırla — Hafta 11 kayıpları o çerçeveye oturur.
## Anahtar Kavramlar (Cheat Sheet) {#sec-cheat-d10}
| Kavram | Tanım | Hoca / timestamp |
|---|---|---|
| Öz-denetimli öğrenme (SSL) | Etiketsiz veriden gözetim sinyali; pre-train→downstream | Misra 1m18 |
| Pretext görev | Proxy tahmin görevi; temsil öğrenmek için | Misra 13m18 |
| Pretext önemsiz, temsil değerli | Görev bahane; öğrenilen temsil asıl ödül | Misra 19m11 |
| Döndürme pretext'i | 0/90/180/270° tahmin (4-yönlü sınıflandırma) | Misra 18m13 |
| Göreli konum / renklendirme | Yama konumu / gri→renk pretext görevleri | Misra 14m16 / 22m19 |
| PIRL | Pretext-değişmez temsil (contrastive, NCE) | Misra (PIRL) |
| Post-2020 SSL (KURSTA YOK) | BYOL/VICReg/MAE/JEPA — ileriye köprü | İleriye köprü |
| Emulator (dünya modeli) | $s_{t+1} = f(s_t, a_t)$; kinematiği öğrenir | Canziani 15m16 |
| Controller (politika) | Emulator üzerinden eğitilen kontrolör | Canziani 15m33 |
| PPUU | Önce dünyayı öğren, içinde planla (backprop) | Canziani 1m53 |
## ML Builder Bağlantıları {#sec-koprular-d10}
**Geriye köprüler (önkoşul kurslar):**
1. **SSL = etiketsiz gözetim** → Hafta 8 contrastive + Hafta 3 invariance.
2. **Pretext = proxy supervised** → Hafta 1 supervised + Hafta 2 cross-entropy (rotation = 4-yönlü).
3. **PIRL = contrastive invariance** → Hafta 8 (NCE) + Hafta 3.
4. **Emulator = dünya modeli** → Hafta 9 (latent EBM) + Hafta 6 (durum geçişi).
5. **Controller eğitimi = zincir backprop** → Hafta 5 autograd + Hafta 6 BPTT.
**İleriye köprüler (production / research):**
1. **SSL** → **BYOL/VICReg/MAE/JEPA (post-2020, KURSTA YOK)**.
2. **Pre-train → fine-tune** → foundation models (görü + dil).
3. **Pretext (proxy)** → LLM next-token (proxy → temsil).
4. **Emulator + controller** → model-based RL, MPC, JEPA planning.
::: {.callout-important title="Bu dersten tek bir şey alıp gideceksen"}
Öz-denetimli öğrenme, pahalı etiketleri atlayıp **etiketsiz veriden bir pretext görev uydurur** (döndürmeyi, konumu, rengi tahmin et) — görevin kendisi önemsizdir, değerli olan yan ürün **temsildir**; ve PPUU, Hafta 9'un dünya modelini somutlaştırır: önce bir emulator ($s_{t+1}=f(s_t,a_t)$) öğren, sonra onun içinde bir controller (politika) eğit. İkisi de, Hafta 7-9'da kurulan EBM/world-model temelinin uygulamalarıdır — ve bu temelin post-2020 evrimi (BYOL, VICReg, MAE, JEPA) kursta yoktur ama LeCun'un bugünkü programının doğrudan devamıdır.
:::