Modele de tren cu PyTorch

Finalizat

PyTorch este un cadru de învățare programată utilizat de obicei pentru instruirea modelelor de învățare profundă. În Azure Databricks, PyTorch este preinstalat în clusterele ML .

Notă

Fragmentele de cod din această unitate sunt furnizate ca exemple pentru a sublinia punctele cheie. Veți avea ocazia să rulați cod pentru un exemplu complet, de lucru în exercițiul următor în acest modul.

Definiți o rețea PyTorch

În PyTorch, modelele se bazează pe o rețea pe care o definiți. Rețeaua constă din mai multe straturi, fiecare cu intrări și ieșiri specificate. În plus, munca definește o funcție de redirecționare care aplică funcții fiecărui strat pe măsură ce datele sunt transmise prin rețea.

Următorul exemplu de cod definește o rețea.

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

În timp ce codul poate părea complex la început, această clasă definește o rețea relativ simplă cu trei straturi:

  • Un strat de intrare care acceptă patru valori de intrare și generează cinci valori de ieșire pentru următorul strat.
  • Un strat care acceptă cinci intrări și generează cinci ieșiri.
  • Un strat final de ieșire care acceptă cinci intrări și generează trei ieșiri.

Funcția forward aplică straturile la datele de intrare (x), care transmite ieșirea din fiecare strat în următorul și, în cele din urmă, returnează rezultatul din ultimul strat (care conține vectorul de predicție a etichetei, y). O funcție de activare a unității liniare rectificate (ReLU) se aplică ieșirilor nivelurilor 1 și 2 pentru a limita valorile de ieșire la numere pozitive.

Notă

În funcție de tipul de criteriu de pierdere utilizat, puteți alege să aplicați o funcție de activare, cum ar fi o log_softmax la valoarea returnată, pentru a o forța în intervalul 0-1. Cu toate acestea, unele criterii de pierdere (cum ar fi CrossEntropyLoss, care este utilizat de obicei pentru clasificarea multiclass) aplică automat o funcție adecvată.

Pentru a crea un model de instruire, trebuie doar să creați o instanță a clasei de rețea astfel:

myModel = MyNet()

Pregătirea datelor pentru modelare

Straturile PyTorch lucrează la date formatate ca tensori - structuri de matrice asemănătoare. Există diverse funcții pentru a efectua conversia altor formate de date comune în tensoruri și puteți defini un încărcător de date PyTorch pentru a citi tensori de date într-un model pentru instruire sau deducere.

La fel ca în cazul celor mai supravegheate tehnici de învățare programată, ar trebui să definiți seturi de date separate pentru instruire și validare. Această separare vă permite să validați că modelul prezice corect atunci când este prezentat cu date pe care nu a fost instruit.

Următorul cod definește două încărcătoare de date; una pentru instruire, iar cealaltă pentru testare. Datele sursă pentru fiecare încărcător din acest exemplu se consideră a fi o matrice Numpy de valori de caracteristici și o matrice Numpy de valori de etichete corespondente.

# 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)

Încărcătoarele din acest exemplu scindează datele în grupuri de 30, care sunt transmise funcției de redirecționare în timpul instruirii sau al deducerii.

Alegeți un criteriu de pierdere și algoritmul de optimizare

Modelul este instruit prin alimentarea datelor de instruire în rețea, prin măsurarea pierderii (diferența agregată dintre valorile estimate și cele reale) și optimizarea rețelei prin ajustarea greutăților și soldurilor pentru a reduce pierderea. Detaliile specifice ale modului în care este calculată și minimizată pierderea este guvernată de criteriul de pierdere și de algoritmul de optimizare pe care îl alegeți.

Criterii de pierdere

PyTorch acceptă mai multe funcții de criterii de pierdere, inclusiv (printre multe altele):

  • cross_entropy: O funcție care măsoară diferența agregată dintre valorile estimate și valorile reale pentru mai multe variabile (utilizată de obicei pentru a măsura pierderile pentru probabilitățile de clasă în clasificarea multiclasă).
  • binary_cross_entropy: O funcție care măsoară diferența dintre probabilitățile estimate și cele reale (utilizată de obicei pentru a măsura pierderile pentru probabilitățile de clasă în clasificarea binară).
  • mse_loss: O funcție care măsoară pierderea de eroare pătrată medie pentru valorile numerice estimate și reale (utilizată de obicei pentru regresie).

Pentru a specifica criteriul de pierdere pe care doriți să-l utilizați atunci când vă instruiți modelul, creați o instanță a funcției corespunzătoare; aşa:

import torch.nn as nn

loss_criteria = nn.CrossEntropyLoss

Sfat

Pentru mai multe informații despre criteriile de pierdere disponibile în PyTorch, consultați Funcții de pierdere în documentația PyTorch.

Algoritmi de optimizare

După ce ați calculat pierderea, se utilizează un optimizator pentru a determina cât mai bine să ajustați greutățile și soldurile pentru a-l minimiza. Optimizatorii sunt implementări specifice ale unei abordări descendentă gradient pentru minimizarea unei funcții. Optimizatoarele disponibile în PyTorch includ (printre altele):

Pentru a utiliza oricare dintre acești algoritmi pentru a instrui un model, trebuie să creați o instanță a optimizatorului și să setați toți parametrii necesari. Parametrii specifici variază în funcție de optimizatorul ales, dar cel mai mult vă solicită să specificați o rată de învățare care guvernează dimensiunea ajustărilor efectuate cu fiecare optimizare.

Următorul cod creează o instanță a optimizatorului Adam .

import torch.optim as opt

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

Sfat

Pentru mai multe informații despre optimizatorii disponibili în PyTorch, consultați Algoritmi în documentația PyTorch.

Crearea funcțiilor de instruire și testare

După ce ați definit o rețea și date pregătite pentru aceasta, puteți utiliza datele pentru a instrui și a testa un model, trecând datele de instruire prin rețea, calculând pierderile, optimizând greutățile și biza rețelei și validând performanța rețelei cu datele de test. Este comun să definiți o funcție care transmite date prin rețea pentru a instrui modelul cu datele de instruire și o funcție separată pentru a testa modelul cu datele de test.

Crearea unei funcții de tren

Următorul exemplu arată o funcție pentru instruirea unui 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

Următorul exemplu arată o funcție pentru a testa modelul.

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

Instruiți modelul peste mai multe epoci

Pentru a instrui un model de învățare profundă, rulați de obicei funcția de instruire de mai multe ori (denumite epoci), cu scopul de a reduce pierderea calculată din datele de instruire pe fiecare epocă. Puteți utiliza funcția de testare pentru a valida faptul că pierderea datelor de test (pe care modelul nu a fost instruit) reduce, de asemenea, în conformitate cu pierderile de instruire, cu alte cuvinte, că instruirea modelului nu produce un model care este supraasistat cu datele de instruire.

Sfat

Nu trebuie să rulați funcția de test pentru fiecare epocă. Puteți alege să-l rulați la fiecare a doua epocă sau o dată la sfârșit. Totuși, testarea modelului în timp ce este instruit poate fi utilă pentru a determina după câte epoci începe să devină supraaplicate.

Următorul cod instruiește un model de peste 50 de epoci.

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)

Salvați starea modelului instruit

După ce ați instruit cu succes un model, îi puteți economisi greutățile și biaza astfel:

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

Pentru a încărca și a utiliza modelul ulterior, creați o instanță a clasei de rețea pe care se bazează modelul și încărcați greutățile salvate și biază.

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