Oplær modeller med PyTorch

Fuldført

PyTorch er en almindeligt brugt maskinel indlæringsramme til oplæring af modeller til dyb læring. I Azure Databricks er PyTorch forudinstalleret i ML-klynger .

Seddel

Kodestykkerne i dette undermodul er angivet som eksempler for at fremhæve vigtige punkter. Du har mulighed for at køre kode for at få et fuldt eksempel i øvelsen senere i dette modul.

Definer et PyTorch-netværk

I PyTorch er modeller baseret på et netværk, som du definerer. Netværket består af flere lag, hver med angivne input og output. Derudover definerer arbejdet en fremadrettet funktion, der anvender funktioner på hvert lag, når data overføres via netværket.

Følgende eksempelkode definerer et netværk.

import torch
import torch.nn as nn
import torch.nn.functional as F

class MyNet(nn.Module):
    def __init__(self):
        super(MyNet, self).__init__()
        self.layer1 = nn.Linear(4, 5)
        self.layer2 = nn.Linear(5, 5)
        self.layer3 = nn.Linear(5, 3)

    def forward(self, x):
        layer1_output = torch.relu(self.layer1(x))
        layer2_output = torch.relu(self.layer2(layer1_output))
        y = self.layer3(layer2_output)
        return y

Selvom koden kan virke kompleks i starten, definerer denne klasse et relativt simpelt netværk med tre lag:

  • Et inputlag, der accepterer fire inputværdier og genererer fem outputværdier for det næste lag.
  • Et lag, der accepterer fem input og genererer fem output.
  • Et endeligt outputlag, der accepterer fem input og genererer tre output.

Funktionen forward anvender lagene på inputdataene (x), overfører outputtet fra hvert lag til det næste og returnerer til sidst outputtet fra det sidste lag (som indeholder etiketforudsigelsesvektoren y). En rektificeret aktiveringsfunktion for lineær enhed (ReLU) anvendes på outputtet fra lag 1 og 2 for at begrænse outputværdierne til positive tal.

Seddel

Afhængigt af den anvendte type tabskriterium kan du vælge at anvende en aktiveringsfunktion, f.eks. en log_softmax på returværdien for at tvinge den ind i intervallet 0 til 1. Nogle kriterier for tab (f.eks . CrossEntropyLoss, som ofte bruges til klassificering i flere klasse) anvender dog automatisk en passende funktion.

Hvis du vil oprette en model til oplæring, skal du blot oprette en forekomst af netværksklassen som denne:

myModel = MyNet()

Forbered data til modellering

PyTorch-lag fungerer på data, der er formateret som tensors – matrixlignende strukturer. Der er forskellige funktioner til at konvertere andre almindelige dataformater til tensors, og du kan definere en PyTorch-dataindlæser til at læse data tensors i en model til oplæring eller udledning.

Som med de fleste overvågede teknikker til maskinel indlæring skal du definere separate datasæt til oplæring og validering. Denne adskillelse giver dig mulighed for at validere, at modellen forudsiger nøjagtigt, når den præsenteres for data, som den ikke blev oplært i.

Følgende kode definerer to dataindlæsningsmaskiner. den ene til oplæring og den anden til test. Kildedataene for hver indlæsser i dette eksempel antages at være en Numpy-matrix med funktionsværdier og en Numpy-matrix med tilsvarende mærkatværdier.

# Create a dataset and loader for the training data and labels
train_x = torch.Tensor(x_train).float()
train_y = torch.Tensor(y_train).long()
train_ds = td.TensorDataset(train_x,train_y)
train_loader = td.DataLoader(train_ds, batch_size=20,
    shuffle=False, num_workers=1)

# Create a dataset and loader for the test data and labels
test_x = torch.Tensor(x_test).float()
test_y = torch.Tensor(y_test).long()
test_ds = td.TensorDataset(test_x,test_y)
test_loader = td.DataLoader(test_ds, batch_size=20,
    shuffle=False, num_workers=1)

Indlæsningsmaskinerne i dette eksempel opdeler dataene i batches på 30, som overføres til fremadrettet funktion under oplæring eller konklusion.

Vælg et tabskriterium og en optimeringsalgoritme

Modellen oplæres ved at overføre træningsdataene til netværket, måle tabet (den aggregerede forskel mellem forudsagte og faktiske værdier) og optimere netværket ved at justere vægte og balancer for at minimere tab. De specifikke oplysninger om, hvordan tab beregnes og minimeres, er underlagt det tabskriterium og den optimeringsalgoritme, du vælger.

Kriterier for tab

PyTorch understøtter flere kriterier for tab, herunder (blandt mange andre):

  • cross_entropy: En funktion, der måler den samlede forskel mellem forudsagte og faktiske værdier for flere variabler (bruges typisk til at måle tab for klassesandsynlighed i klassificering med flere klasser).
  • binary_cross_entropy: En funktion, der måler forskellen mellem forudsagte og faktiske sandsynligheder (bruges typisk til at måle tab for klassesandsynlighed i binær klassificering).
  • mse_loss: En funktion, der måler det gennemsnitlige kvadratiske fejltab for forudsagte og faktiske numeriske værdier (typisk brugt til regression).

Hvis du vil angive det tabskriterium, du vil bruge til oplæring af din model, skal du oprette en forekomst af den relevante funktion. Som dette:

import torch.nn as nn

loss_criteria = nn.CrossEntropyLoss

Drikkepenge

Du kan få flere oplysninger om tilgængelige tabskriterier i PyTorch under Tabsfunktioner i dokumentationen til PyTorch.

Optimeringsalgoritmer

Når du har beregnet tabet, bruges en optimering til at bestemme, hvordan du bedst justerer vægte og saldi for at minimere det. Optimering er specifikke implementeringer af en gradueringsstigningstilgang for at minimere en funktion. Tilgængelige optimeringer i PyTorch omfatter (blandt andet):

Hvis du vil bruge en af disse algoritmer til at oplære en model, skal du oprette en forekomst af optimeringsfunktionen og angive eventuelle påkrævede parametre. De specifikke parametre varierer afhængigt af den valgte optimering, men de fleste kræver, at du angiver en læringsfrekvens , der styrer størrelsen af justeringer, der foretages med hver optimering.

Følgende kode opretter en forekomst af Adam-optimeringsprogrammet .

import torch.optim as opt

learning_rate = 0.001
optimizer = opt.Adam(model.parameters(), lr=learning_rate)

Drikkepenge

Du kan få flere oplysninger om tilgængelige optimeringer i PyTorch under Algoritmer i dokumentationen til PyTorch.

Opret oplær- og testfunktioner

Når du har defineret et netværk og forberedt data til det, kan du bruge dataene til at oplære og teste en model ved at overføre træningsdataene via netværket, beregne tabet, optimere netværksvægte og -forskelle og validere netværkets ydeevne med testdataene. Det er almindeligt at definere en funktion, der overfører data gennem netværket for at oplære modellen med træningsdataene, og en separat funktion til at teste modellen med testdataene.

Opret en oplæringsfunktion

I følgende eksempel vises en funktion til at oplære en model.

def train(model, data_loader, optimizer):

    # Use GPU if available, otherwise CPU
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    model.to(device)
    
    # Set the model to training mode (to enable backpropagation)
    model.train()
    train_loss = 0
    
    # Feed the batches of data forward through the network
    for batch, tensor in enumerate(data_loader):
        data, target = tensor # Specify features and labels in a tensor
        optimizer.zero_grad() # Reset optimizer state
        out = model(data) # Pass the data through the network
        loss = loss_criteria(out, target) # Calculate the loss
        train_loss += loss.item() # Keep a running total of loss for each batch

        # backpropagate adjustments to weights/bias
        loss.backward()
        optimizer.step()

    #Return average loss for all batches
    avg_loss = train_loss / (batch+1)
    print('Training set: Average loss: {:.6f}'.format(avg_loss))
    return avg_loss

I følgende eksempel vises en funktion til test af modellen.

def test(model, data_loader):
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    model.to(device)
    # Switch the model to evaluation mode (so we don't backpropagate)
    model.eval()
    test_loss = 0
    correct = 0

    # Pass the data through with no gradient computation
    with torch.no_grad():
        batch_count = 0
        for batch, tensor in enumerate(data_loader):
            batch_count += 1
            data, target = tensor
            # Get the predictions
            out = model(data)

            # calculate the loss
            test_loss += loss_criteria(out, target).item()

            # Calculate the accuracy
            _, predicted = torch.max(out.data, 1)
            correct += torch.sum(target==predicted).item()
            
    # Calculate the average loss and total accuracy for all batches
    avg_loss = test_loss/batch_count
    print('Validation set: Average loss: {:.6f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
        avg_loss, correct, len(data_loader.dataset),
        100. * correct / len(data_loader.dataset)))
    return avg_loss

Oplær modellen over flere epoker

Hvis du vil oplære en model til dyb læring, kører du typisk oplæringsfunktionen flere gange (kaldet epoker) med det mål at reducere tabet beregnet ud fra træningsdataene hver epoke. Du kan bruge din testfunktion til at validere, at tabet fra testdataene (som modellen ikke blev oplært på) også reduceres i overensstemmelse med træningstabet – med andre ord, at modeltræningen ikke producerer en model, der overbelastes til oplæringsdataene.

Drikkepenge

Du behøver ikke at køre testfunktionen for hver epoke. Du kan vælge at køre den hver anden epoke eller én gang til sidst. Det kan dog være nyttigt at teste modellen, efterhånden som den oplæres, når det afgøres, hvor mange epoker en model begynder at blive overfitted.

Følgende kode oplærer en model over 50 epoker.

epochs = 50
for epoch in range(1, epochs + 1):

    # print the epoch number
    print('Epoch: {}'.format(epoch))
    
    # Feed training data into the model to optimize the weights
    train_loss = train(model, train_loader, optimizer)
    print(train_loss)
    
    # Feed the test data into the model to check its performance
    test_loss = test(model, test_loader)
    print(test_loss)

Gem tilstanden for den oplærte model

Når du har oplært en model, kan du gemme dens vægte og forskelle som denne:

model_file = '/dbfs/my_model.pkl'
torch.save(model.state_dict(), model_file)

Hvis du vil indlæse og bruge modellen på et senere tidspunkt, skal du oprette en forekomst af den netværksklasse, som modellen er baseret på, og indlæse de gemte vægte og forskelle.

model = myNet()
model.load_state_dict(torch.load(model_file))