CodeBlanks Logo Icon CodeBlanks

Meydan okuma 3

CNN ile görüntü modeli kurarsın.

Meydan okuma 3: kendi optimize edicin

PyTorch optimize edicilerinin içinde ne olduğunu kanıtlamanın en iyi yolu birini kendin yazmaktır. torch.optim.Optimizer'dan türeyen bir sınıf, step içinde parametre gruplarını gezer:

class BenimSGD(torch.optim.Optimizer):
    def __init__(self, params, lr):
        super().__init__(params, {"lr": lr})

    @torch.no_grad()
    def step(self):
        for grup in self.param_groups:
            for p in grup["params"]:
                if p.grad is not None:
                    p -= grup["lr"] * p.grad

zero_grad, parametre grupları ve state_dict temel sınıftan hazır gelir.

Uygulama BenimSGD

Karttaki BenimSGD sınıfını yaz. Aynı başlangıçtan iki kopya model oluştur (verildi); birini BenimSGD(lr=0.1), diğerini torch.optim.SGD(lr=0.1) ile 20 adım eğit. Son ağırlıkların aynı olduğunu torch.allclose ile yazdır.

Başlangıç kodu

model.py
import copy
import torch
from torch import nn

torch.manual_seed(0)
X = torch.randn(64, 3)
y = X @ torch.tensor([[1.0], [-2.0], [0.5]])
a = nn.Linear(3, 1)
b = copy.deepcopy(a)

# buraya yaz

Örnek çözüm

model.py
import copy
import torch
from torch import nn

torch.manual_seed(0)
X = torch.randn(64, 3)
y = X @ torch.tensor([[1.0], [-2.0], [0.5]])
a = nn.Linear(3, 1)
b = copy.deepcopy(a)

class BenimSGD(torch.optim.Optimizer):
    def __init__(self, params, lr):
        super().__init__(params, {"lr": lr})

    @torch.no_grad()
    def step(self):
        for grup in self.param_groups:
            for p in grup["params"]:
                if p.grad is not None:
                    p -= grup["lr"] * p.grad

for model, opt in [(a, BenimSGD(a.parameters(), lr=0.1)), (b, torch.optim.SGD(b.parameters(), lr=0.1))]:
    for _ in range(20):
        opt.zero_grad()
        nn.functional.mse_loss(model(X), y).backward()
        opt.step()
print(torch.allclose(a.weight, b.weight))

Beklenen çıktı

True

Uygulama Momentumlu sürüm

BenimMomentum sınıfını yaz: her parametre için self.state[p]["buf"] tamponu tutsun; ilk adımda buf = g.clone(), sonra buf = m·buf + g; güncelleme p -= lr·buf. w = 0'dan (w - 3)² için lr = 0.1, m = 0.9 ile 2 adım at ve w'yi round(..., 3) ile yazdır (beklenen: 1.62).

Başlangıç kodu

model.py
import torch

w = torch.tensor(0.0, requires_grad=True)

# buraya yaz

Örnek çözüm

model.py
import torch

w = torch.tensor(0.0, requires_grad=True)

class BenimMomentum(torch.optim.Optimizer):
    def __init__(self, params, lr, m):
        super().__init__(params, {"lr": lr, "m": m})

    @torch.no_grad()
    def step(self):
        for grup in self.param_groups:
            for p in grup["params"]:
                if p.grad is None:
                    continue
                durum = self.state[p]
                if "buf" not in durum:
                    durum["buf"] = p.grad.clone()
                else:
                    durum["buf"] = grup["m"] * durum["buf"] + p.grad
                p -= grup["lr"] * durum["buf"]

opt = BenimMomentum([w], lr=0.1, m=0.9)
for _ in range(2):
    opt.zero_grad()
    ((w - 3) ** 2).backward()
    opt.step()
print(round(w.item(), 3))

Beklenen çıktı

1.62

Soru ve cevaplar

Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.

1 <code>step</code> neden <code>@torch.no_grad()</code> ile işaretlenir?

  • Zorunlu değildir
  • Güncelleme hesap grafiğine kaydedilmesin diye Doğru cevap
  • Daha hızlı olsun diye
  • Gradyanları sıfırlamak için

Açıklama: Parametreler yerinde değiştirilir; bu bir türev alınacak işlem değildir.

2 Varsayılan ayarları üst sınıfa ver.

Soru
super().__init__(params, ____)
Cevap
super().__init__(params, {"lr": lr})

Açıklama: İkinci argüman varsayılan grup ayarlarının sözlüğüdür.

3 Parçaları eşleştir.

Kavram Anlamı
param_groups Ayarlı parametre grupları
@torch.no_grad() İzlemesiz güncelleme
p.grad is not None Donuk parametreleri atla
self.state[p] Parametre başına durum

İleri seviye bölümündeki tüm dersler