CodeBlanks Logo Icon CodeBlanks

Meydan okuma 4

Eğitim döngüsü yazarsın.

Meydan okuma 4: dondur, ince ayarla

Son meydan okumada transfer öğrenmenin iki aşamasını uygulayacaksın. "Önceden eğitilmiş" gövdeyi bir yan görevde eğiterek kendin hazırlayacak, sonra yeni bir görev için önce yalnızca başı, ardından tüm ağı küçük oranla eğiteceksin:

# 1. hazırlık: gövde + baş_A, görev A üzerinde
# 2. aşama 1: gövde donuk, baş_B eğitilir
# 3. aşama 2: gövde açık (lr küçük), gövde + baş_B birlikte

Her aşamada eğitilebilir parametre sayısını kontrol etmek, dondurmanın gerçekten uygulandığını doğrular.

Uygulama Hazırlık ve aşama 1

Gövde (Linear(2, 32) → ReLU → Linear(32, 32) → ReLU) ve baş_A = Linear(32, 2) ile görev A'yı (ay verisi) 300 adım eğit. Sonra gövdeyi dondur; görev B (etiketleri ters çevrilmiş ay: 1 - y) için yeni baş_B = Linear(32, 2)'yi 100 adım eğit. Aşama 1'deki eğitilebilir parametre sayısını ve görev B doğruluğunun 0.95'ten büyük olduğunu aynı satırda yazdır.

Başlangıç kodu

model.py
import math
import torch
from torch import nn

torch.manual_seed(0)
def ay(n):
    t = torch.rand(n) * math.pi
    ust = torch.stack([torch.cos(t), torch.sin(t)], 1)
    alt = torch.stack([1 - torch.cos(t), 0.5 - torch.sin(t)], 1)
    X = torch.cat([ust, alt]) + 0.1 * torch.randn(2 * n, 2)
    y = torch.cat([torch.zeros(n), torch.ones(n)]).long()
    return X, y

X, y = ay(200)

# buraya yaz

Örnek çözüm

model.py
import math
import torch
from torch import nn

torch.manual_seed(0)
def ay(n):
    t = torch.rand(n) * math.pi
    ust = torch.stack([torch.cos(t), torch.sin(t)], 1)
    alt = torch.stack([1 - torch.cos(t), 0.5 - torch.sin(t)], 1)
    X = torch.cat([ust, alt]) + 0.1 * torch.randn(2 * n, 2)
    y = torch.cat([torch.zeros(n), torch.ones(n)]).long()
    return X, y

X, y = ay(200)

govde = nn.Sequential(nn.Linear(2, 32), nn.ReLU(), nn.Linear(32, 32), nn.ReLU())
bas_A = nn.Linear(32, 2)
kayip_fn = nn.CrossEntropyLoss()
opt = torch.optim.Adam(list(govde.parameters()) + list(bas_A.parameters()), lr=0.01)
for _ in range(300):
    opt.zero_grad()
    kayip_fn(bas_A(govde(X)), y).backward()
    opt.step()
for p in govde.parameters():
    p.requires_grad = False
bas_B = nn.Linear(32, 2)
model = nn.Sequential(govde, bas_B)
opt = torch.optim.Adam(bas_B.parameters(), lr=0.01)
for _ in range(100):
    opt.zero_grad()
    kayip_fn(model(X), 1 - y).backward()
    opt.step()
egitilebilir = sum(p.numel() for p in model.parameters() if p.requires_grad)
with torch.no_grad():
    print(egitilebilir, (model(X).argmax(1) == 1 - y).float().mean().item() > 0.95)

Beklenen çıktı

66 True

Uygulama Aşama 2: ince ayar

Aşama 1 sonrası (kod hazır) gövdeyi aç ve gövde için lr=1e-4, baş için lr=1e-3 olan parametre gruplarıyla Adam kur. 100 adım ince ayar yap. Eğitilebilir parametre sayısını ve görev B doğruluğunun hâlâ 0.95'ten büyük olduğunu aynı satırda yazdır.

Başlangıç kodu

model.py
import math
import torch
from torch import nn

torch.manual_seed(0)
def ay(n):
    t = torch.rand(n) * math.pi
    ust = torch.stack([torch.cos(t), torch.sin(t)], 1)
    alt = torch.stack([1 - torch.cos(t), 0.5 - torch.sin(t)], 1)
    X = torch.cat([ust, alt]) + 0.1 * torch.randn(2 * n, 2)
    y = torch.cat([torch.zeros(n), torch.ones(n)]).long()
    return X, y

X, y = ay(200)

govde = nn.Sequential(nn.Linear(2, 32), nn.ReLU(), nn.Linear(32, 32), nn.ReLU())
bas_B = nn.Linear(32, 2)
model = nn.Sequential(govde, bas_B)
kayip_fn = nn.CrossEntropyLoss()
opt = torch.optim.Adam(model.parameters(), lr=0.01)
for _ in range(400):
    opt.zero_grad()
    kayip_fn(model(X), 1 - y).backward()
    opt.step()
for p in govde.parameters():
    p.requires_grad = False

# buraya yaz

Örnek çözüm

model.py
import math
import torch
from torch import nn

torch.manual_seed(0)
def ay(n):
    t = torch.rand(n) * math.pi
    ust = torch.stack([torch.cos(t), torch.sin(t)], 1)
    alt = torch.stack([1 - torch.cos(t), 0.5 - torch.sin(t)], 1)
    X = torch.cat([ust, alt]) + 0.1 * torch.randn(2 * n, 2)
    y = torch.cat([torch.zeros(n), torch.ones(n)]).long()
    return X, y

X, y = ay(200)

govde = nn.Sequential(nn.Linear(2, 32), nn.ReLU(), nn.Linear(32, 32), nn.ReLU())
bas_B = nn.Linear(32, 2)
model = nn.Sequential(govde, bas_B)
kayip_fn = nn.CrossEntropyLoss()
opt = torch.optim.Adam(model.parameters(), lr=0.01)
for _ in range(400):
    opt.zero_grad()
    kayip_fn(model(X), 1 - y).backward()
    opt.step()
for p in govde.parameters():
    p.requires_grad = False

for p in govde.parameters():
    p.requires_grad = True
opt = torch.optim.Adam([{"params": govde.parameters(), "lr": 1e-4}, {"params": bas_B.parameters(), "lr": 1e-3}])
for _ in range(100):
    opt.zero_grad()
    kayip_fn(model(X), 1 - y).backward()
    opt.step()
egitilebilir = sum(p.numel() for p in model.parameters() if p.requires_grad)
with torch.no_grad():
    print(egitilebilir, (model(X).argmax(1) == 1 - y).float().mean().item() > 0.95)

Beklenen çıktı

1218 True

Soru ve cevaplar

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

1 Aşama 1'de optimize ediciye hangi parametreler verilmelidir?

  • Yalnızca yeni başın parametreleri Doğru cevap
  • Tüm parametreler
  • Yalnızca gövde
  • Hiçbiri

Açıklama: Gövde donuk olduğu için güncellenmeyecektir; optimize ediciye yalnızca baş verilir.

2 Gövdeyi tekrar eğitilebilir yap.

Soru
for p in govde.parameters():
    p.requires_grad = ____
Cevap
for p in govde.parameters():
    p.requires_grad = True

Açıklama: Aşama 2'de gövde açılır.

3 Aşamaları eşleştir.

Kavram Anlamı
hazırlık Gövde yan görevde öğrenir
aşama 1 Gövde donuk, baş eğitilir
aşama 2 Hepsi, küçük lr
parametre sayımı Dondurma kontrolü

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