Machine Learning Academy · Oppitunti

Koulutussilmukka: häviö, optimoija ja epookit

Oppijat kirjoittavat PyTorch-koulutussilmukan: zero_grad, forward, CrossEntropyLossin laskeminen, backward ja optimizer.step sekä seuraavat häviötä ja tarkkuutta epookkien aikana.

Oppitunti 4/413 vaihetta

Koulutussilmukka: häviö, optimoija ja epookit on ilmainen Machine Learning Academy-oppitunti CoddyKitissä. Tämä on oppitunti 4/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Machine Learning Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Machine Learning Academy-kurssilla on yhteensä 4 oppituntia.

Jokaisen koulutussilmukan neljä vaihetta

PyTorchin koulutussilmukassa on neljä pakollista vaihetta, jotka toistetaan jokaiselle erälle: (1) gradienttien nollaus, (2) forward-pass, (3) backward-pass ja (4) optimoijan päivitys. Näiden vaiheiden ohittaminen tai suorittaminen väärässä järjestyksessä tuottaa huomaamatta virheellisiä tuloksia — gradientit kertyvät, parametrit päivittyvät väärin tai syntyy muistivuotoja. Tämän rakenteen sisäistäminen on tärkein tapa kouluttaa neuroverkkoja PyTorchilla.

import torch
import torch.nn as nn
import torch.optim as optim

model = nn.Linear(2, 1)
optimizer = optim.SGD(model.parameters(), lr=0.01)
criterion = nn.MSELoss()

X = torch.randn(20, 2)
y = torch.randn(20, 1)

for step in range(1):
    optimizer.zero_grad()           # (1) zero grads
    y_pred = model(X)               # (2) forward
    loss = criterion(y_pred, y)     # (2) loss
    loss.backward()                 # (3) backward
    optimizer.step()                # (4) update
    print('Loss:', loss.item())

Häviöfunktiot: oikean kriteerin valitseminen

Häviöfunktio mittaa, kuinka väärin mallin ennusteet menevät. PyTorchin nn-moduuli tarjoaa useita häviöfunktioita: nn.MSELoss regressioon (keskimääräinen neliövirhe), nn.CrossEntropyLoss moniluokkaiseen luokitteluun (yhdistää log-softmaxin ja NLL:n) sekä nn.BCEWithLogitsLoss binääriseen luokitteluun (yhdistää sigmoidin ja binäärisen ristientropian). Tehtävään sopimattoman häviöfunktion käyttäminen on yleinen aloittelijan virhe, joka estää mallia oppimasta.

import torch
import torch.nn as nn

# Regression
mse = nn.MSELoss()
y_pred = torch.tensor([2.5, 3.0])
y_true = torch.tensor([2.0, 3.5])
print('MSE:', mse(y_pred, y_true).item())

# Multi-class: logits (raw scores), not softmax
ce = nn.CrossEntropyLoss()
logits = torch.tensor([[2.0, 0.5, 1.0]])
labels = torch.tensor([0])
print('CE:', ce(logits, labels).item())

Optimoijat: SGD, Adam ja AdamW

Optimoija käyttää laskettuja gradientteja mallin parametrien päivittämiseen. SGD (Stochastic Gradient Descent) on perinteinen optimoija; momentum-termin lisääminen nopeuttaa konvergenssia. Adam mukauttaa oppimisnopeuden parametrikohtaisesti ensimmäisen ja toisen momentin estimaattien avulla, joten se konvergoi käytännössä nopeammin. AdamW lisää asianmukaisen painojen vaimennuksen (L2-regularisoinnin), ja se on transformer-mallien oletusvalinta. Kaikki optimoijat löytyvät moduulista torch.optim.

import torch.optim as optim
import torch.nn as nn

model = nn.Linear(4, 2)

# Stochastic Gradient Descent with momentum
sgd = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)

# Adam: adaptive learning rate
adam = optim.Adam(model.parameters(), lr=0.001,
                  betas=(0.9, 0.999))

# AdamW: Adam + proper weight decay
adamw = optim.AdamW(model.parameters(), lr=0.001,
                    weight_decay=0.01)

Iterointi epookkien ja erien yli

Koulutus kestää yleensä useita epookkeja eli täydellisiä kierroksia koulutusdatan läpi. Kunkin epookin aikana iteroidaan erien eli datajoukkojen osajoukkojen yli. DataLoader hoitaa sekoittamisen ja eriin jakamisen automaattisesti. Epookkikohtaisen keskimääräisen häviön seuraaminen auttaa tarkkailemaan, konvergoiko malli. Tulostamalla tiedot jokaisen epookin (tai joka N:nnen erän) jälkeen saadaan näkyviin koulutuksen eteneminen.

import torch
from torch.utils.data import TensorDataset, DataLoader
import torch.nn as nn
import torch.optim as optim

X = torch.randn(200, 4)
y = torch.randn(200, 1)
dataset = TensorDataset(X, y)
loader = DataLoader(dataset, batch_size=32, shuffle=True)

model = nn.Linear(4, 1)
optimizer = optim.Adam(model.parameters())
criterion = nn.MSELoss()

for epoch in range(3):
    total_loss = 0
    for X_batch, y_batch in loader:
        optimizer.zero_grad()
        pred = model(X_batch)
        loss = criterion(pred, y_batch)
        loss.backward()
        optimizer.step()
        total_loss += loss.item()
    print(f'Epoch {epoch}: avg_loss={total_loss/len(loader):.4f}')

DataLoader: datan jakaminen eriin ja sekoittaminen

DataLoader käärii Dataset-olion ja tarjoaa iteraattorin, joka palauttaa eriä. Tärkeitä parametreja ovat seuraavat: batch_size määrittää, kuinka monta näytettä käsitellään yhtä gradienttipäivitystä kohti; shuffle=True sekoittaa järjestyksen jokaisella epookilla (mikä on koulutuksessa välttämätöntä); num_workers mahdollistaa datan lataamisen rinnakkain. Mukautettuja datasettejä varten periyttäkää luokka torch.utils.data.Dataset ja toteuttakaa metodit __len__ ja __getitem__.

import torch
from torch.utils.data import Dataset, DataLoader

class MyDataset(Dataset):
    def __init__(self, X, y):
        self.X = X
        self.y = y

    def __len__(self):
        return len(self.X)

    def __getitem__(self, idx):
        return self.X[idx], self.y[idx]

X = torch.randn(100, 5)
y = torch.randint(0, 3, (100,))
dataset = MyDataset(X, y)
loader = DataLoader(dataset, batch_size=16, shuffle=True)

X_batch, y_batch = next(iter(loader))
print(X_batch.shape)   # torch.Size([16, 5])

CrossEntropyLoss: logitit ja luokkien indeksit

nn.CrossEntropyLoss odottaa raakoja logitteja (normalisoimattomia pisteitä), ei softmax-todennäköisyyksiä. Se käyttää sisäisesti log-softmaxia ja laskee negatiivisen log-todennäköisyyden. Kohdetunnisteiden tulee olla kokonaislukumuotoisia luokkaindeksejä, eivät one-hot-vektoreita. Tämä on oikea häviöfunktio moniluokkaiseen luokitteluun, ja se on numeerisesti vakaampi kuin softmaxin ja sen jälkeen NLLLossin käyttäminen manuaalisesti. Mallin viimeisellä kerroksella EI tule olla softmax-aktivointia, kun tätä häviöfunktiota käytetään.

import torch
import torch.nn as nn

criterion = nn.CrossEntropyLoss()

# Batch of 4 samples, 3 classes
logits = torch.tensor([
    [2.1, 0.5, 0.3],
    [0.1, 3.0, 0.2],
    [0.8, 0.9, 2.0],
    [1.5, 0.1, 0.4]
])

# True labels as class indices (not one-hot)
labels = torch.tensor([0, 1, 2, 0])

loss = criterion(logits, labels)
print('Loss:', loss.item())

Tarkkuuden seuraaminen koulutuksen aikana

Häviön pieneneminen vahvistaa, että malli oppii, mutta tarkkuus kertoo, ovatko ennusteet todella oikein. Moniluokkaisessa luokittelussa logitit muunnetaan ennustetuksi luokaksi käyttämällä torch.argmax-funktiota luokkaulottuvuuden suhteen, minkä jälkeen tulosta verrataan oikeisiin tunnisteisiin. Sekä koulutuksen häviön että tarkkuuden ja haluttaessa myös validointitarkkuuden seuraaminen antaa kattavan kuvan oppimisen dynamiikasta.

import torch

def compute_accuracy(logits, labels):
    preds = torch.argmax(logits, dim=1)
    correct = (preds == labels).sum().item()
    return correct / len(labels)

logits = torch.tensor([
    [2.0, 0.1, 0.3],
    [0.1, 0.2, 3.5],
    [1.0, 0.5, 0.2]
])
labels = torch.tensor([0, 2, 0])

print('Accuracy:', compute_accuracy(logits, labels))
# 1.0 (all three correct)

Validointisilmukka: arviointi ilman päivityksiä

Suorittakaa jokaisen koulutusepookin jälkeen validointisilmukka arvioidaksenne suorituskykyä aiemmin näkemättömällä datalla. Kääritkää se torch.no_grad()-kontekstiin gradienttien laskennan poistamiseksi käytöstä ja kutsukaa model.eval()-metodia Dropoutin ja BatchNormin stokastisuuden poistamiseksi käytöstä. Koulutushäviön ja validointihäviön vertaaminen on ensisijainen tapa havaita ylisovittaminen: kun validointihäviö kasvaa samalla kun koulutushäviö pienenee edelleen, malli on ylisovittanut koulutusjoukon.

import torch

def validate(model, val_loader, criterion):
    model.eval()
    total_loss = 0
    with torch.no_grad():
        for X_batch, y_batch in val_loader:
            logits = model(X_batch)
            loss = criterion(logits, y_batch)
            total_loss += loss.item()
    model.train()   # restore training mode
    return total_loss / len(val_loader)

# Usage inside training loop:
# val_loss = validate(model, val_loader, criterion)
# print(f'Val loss: {val_loss:.4f}')

Oppimisnopeuden ajoitus

Kiinteä oppimisnopeus johtaa usein hitaaseen konvergenssiin tai värähtelyyn minimin lähellä. Oppimisnopeuden ajastimet säätävät oppimisnopeutta automaattisesti koulutuksen aikana. StepLR pienentää oppimisnopeutta kertoimella joka N:nnen epookin jälkeen; CosineAnnealingLR pienentää sitä tasaisesti lähes nollaan kosinikäyrän mukaisesti; ReduceLROnPlateau pienentää oppimisnopeutta, kun validointihäviö lakkaa paranemasta. Ajastimen askel otetaan optimoijan jälkeen, yleensä kerran epookkia kohti.

import torch.optim as optim
import torch.nn as nn

model = nn.Linear(4, 2)
optimizer = optim.Adam(model.parameters(), lr=0.01)

# Decay LR by 0.5 every 2 epochs
scheduler = optim.lr_scheduler.StepLR(
    optimizer, step_size=2, gamma=0.5
)

for epoch in range(6):
    # ... training code ...
    scheduler.step()
    print(f'Epoch {epoch}: LR={scheduler.get_last_lr()[0]}')
# LR: 0.01, 0.01, 0.005, 0.005, 0.0025, 0.0025

Tarkistuspisteiden tallentaminen koulutuksen aikana

Koulutus voi kestää tunteja tai päiviä. Tarkistuspisteiden säännöllinen tallentaminen suojaa kaatumisilta ja mahdollistaa jatkamisen parhaasta kohdasta. Hyvä tarkistuspiste sisältää mallin state dictin, optimoijan state dictin (joka sisältää momentum-termit), epookin numeron ja parhaan validointimittarin arvon. Optimoijan tilan palauttaminen mahdollistaa koulutuksen jatkamisen täsmälleen siitä kohdasta, johon se jäi, mukaan lukien seuraaviin päivityksiin vaikuttavat momentum-puskurit.

import torch

def save_checkpoint(model, optimizer, epoch, loss, path):
    torch.save({
        'epoch': epoch,
        'model_state_dict': model.state_dict(),
        'optimizer_state_dict': optimizer.state_dict(),
        'loss': loss
    }, path)

def load_checkpoint(model, optimizer, path):
    ckpt = torch.load(path)
    model.load_state_dict(ckpt['model_state_dict'])
    optimizer.load_state_dict(ckpt['optimizer_state_dict'])
    return ckpt['epoch'], ckpt['loss']

Täydellinen koulutussilmukka: kokonaisuuden kokoaminen

Tuotantolaatuinen koulutussilmukka yhdistää kaikki osat: DataLoader hoitaa eriin jakamisen, jokaiselle erälle tehdään nelivaiheinen päivitys, jokaisen epookin jälkeen suoritetaan validointikierros, oppimisnopeutta ajoitetaan, häviötä ja tarkkuutta seurataan ja tarkistuspisteitä tallennetaan. Alla oleva koodi esittelee koko rakenteen yksinkertaisen luokittelumallin avulla. Tämän mallin sovittaminen mihin tahansa ohjattuun oppimistehtävään edellyttää vain mallin, datasetin ja häviöfunktion vaihtamista.

import torch, torch.nn as nn, torch.optim as optim
from torch.utils.data import TensorDataset, DataLoader

X_tr = torch.randn(160, 4); y_tr = torch.randint(0, 3, (160,))
X_val = torch.randn(40, 4); y_val = torch.randint(0, 3, (40,))
tr_loader = DataLoader(TensorDataset(X_tr, y_tr), 32, shuffle=True)
val_loader = DataLoader(TensorDataset(X_val, y_val), 32)

model = nn.Sequential(nn.Linear(4, 16), nn.ReLU(), nn.Linear(16, 3))
optimizer = optim.Adam(model.parameters())
criterion = nn.CrossEntropyLoss()

for epoch in range(5):
    model.train()
    for Xb, yb in tr_loader:
        optimizer.zero_grad()
        loss = criterion(model(Xb), yb)
        loss.backward(); optimizer.step()
    model.eval()
    with torch.no_grad():
        val_loss = sum(criterion(model(Xb), yb).item()
                       for Xb, yb in val_loader) / len(val_loader)
    print(f'Epoch {epoch}: val_loss={val_loss:.3f}')

Pikatarkistus

Testatkaa tässä oppitunnissa oppimianne Pythonin koneoppimiseen liittyviä käsitteitä.

Oppitunnin yhteenveto

Tässä oppitunnissa opitte, että nelivaiheinen koulutussilmukka (zero_grad, forward, backward, step) on kaiken PyTorch-koulutuksen perusta, DataLoader hoitaa eriin jakamisen ja sekoittamisen automaattisesti ja CrossEntropyLoss logiteilla on luokittelun vakiovalinta. Seuraavaksi tutustumme oppimisnopeuden ajoitukseen ja oppimisnopeuden vaikutukseen koulutuksen dynamiikkaan.

Aloita maksutta

Opi Python tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
30
Oppitunnit
120

Usein kysytyt kysymykset

Onko oppitunti ”Koulutussilmukka: häviö, optimoija ja epookit” ilmainen?

Kyllä – oppitunnin ”Koulutussilmukka: häviö, optimoija ja epookit” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Machine Learning Academy-kurssin, päivitä CoddyKit PROhon. Machine Learning Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Koulutussilmukka: häviö, optimoija ja epookit”?

Oppijat kirjoittavat PyTorch-koulutussilmukan: zero_grad, forward, CrossEntropyLossin laskeminen, backward ja optimizer.step sekä seuraavat häviötä ja tarkkuutta epookkien aikana. Harjoittelet Machine Learning Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Machine Learning Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Machine Learning Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 4/4.

Kuinka kauan ”Koulutussilmukka: häviö, optimoija ja epookit”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Machine Learning Academy-oppitunnilla?

Kyllä. Jokainen Machine Learning Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. PyTorch-tensorit: luominen, operaatiot ja siirto GPU:lle
  2. Autograd: automaattinen derivointi takaisinkuljetusta varten
  3. Syöttöä eteenpäin välittävän verkon rakentaminen nn.Modulella
  4. Koulutussilmukka: häviö, optimoija ja epookit
← Takaisin: Machine Learning Academy