Meydan okuma 3
- Makine Öğrenmesi kursu
- İleri seviye
- Ders 77/78
- 8 dk
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.gradzero_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
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
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
import torch
w = torch.tensor(0.0, requires_grad=True)
# buraya yazÖrnek çözüm
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.
super().__init__(params, ____)
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 |