Trénování modelů pomocí PyTorchu

Dokončeno

PyTorch je běžně používaná architektura strojového učení pro trénování modelů hlubokého učení. V Azure Databricks je PyTorch předinstalovaný v clusterech ML .

Poznámka:

Fragmenty kódu v této lekci jsou k dispozici jako příklady pro zdůraznění klíčových bodů. Budete mít možnost spustit kód pro úplný, funkční příklad ve cvičení později v tomto modulu.

Definování sítě PyTorch

V PyTorchu jsou modely založené na síti, kterou definujete. Síť se skládá z několika vrstev, z nichž každý má zadané vstupy a výstupy. Kromě toho práce definuje dopřednou funkci, která použije funkce na každou vrstvu, protože data se předávají přes síť.

Následující příklad kódu definuje síť.

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

I když se kód může zpočátku zdát složitý, tato třída definuje relativně jednoduchou síť se třemi vrstvami:

  • Vstupní vrstva, která přijímá čtyři vstupní hodnoty a vygeneruje pět výstupních hodnot pro další vrstvu.
  • Vrstva, která přijímá pět vstupů a generuje pět výstupů.
  • Konečná výstupní vrstva, která přijímá pět vstupů a generuje tři výstupy.

Funkce vpřed použije vrstvy na vstupní data (x), předá výstup z každé vrstvy do další a nakonec vrátí výstup z poslední vrstvy (která obsahuje vektor předpovědi popisku, y). Rektifikovaná aktivační funkce lineární jednotky (ReLU) se použije na výstupy vrstev 1 a 2 k omezení výstupních hodnot na kladná čísla.

Poznámka:

V závislosti na použitém typu kritéria ztráty se můžete rozhodnout použít aktivační funkci, jako je například log_softmax , na vrácenou hodnotu, která ji vynutí do rozsahu 0 až 1. Některá kritéria ztráty (například CrossEntropyLoss, která se běžně používají pro klasifikaci s více třídami), však automaticky používají vhodnou funkci.

Pokud chcete vytvořit model pro trénování, stačí vytvořit instanci třídy sítě takto:

myModel = MyNet()

Příprava dat pro modelování

PyTorch vrstvy pracují na datech formátovaných jako tensory – struktury podobné matici. Existují různé funkce pro převod jiných běžných datových formátů na tensory a můžete definovat zavaděč dat PyTorch pro čtení tenzorů dat do modelu pro trénování nebo odvozování.

Stejně jako u většiny technik strojového učení pod dohledem byste měli definovat samostatné datové sady pro trénování a ověřování. Toto oddělení umožňuje ověřit, že model predikuje přesně, když se zobrazí data, na kterých nebyla natrénována.

Následující kód definuje dva zavaděče dat; jeden pro trénování a druhý pro testování. Zdrojová data pro každý zavaděč v tomto příkladu se předpokládá jako pole Numpy s hodnotami vlastností a pole Numpy s odpovídajícími hodnotami popisku.

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

Zavaděče v tomto příkladu rozdělují data na dávky 30, které se předávají funkci vpřed během trénování nebo odvozování.

Volba kritéria ztráty a algoritmu optimalizátoru

Model se vytrénuje tak, že do sítě předá trénovací data, změří ztrátu (agregovaný rozdíl mezi predikovanými a skutečnými hodnotami) a optimalizuje síť úpravou váhy a rovnováhy, aby se minimalizovala ztráta. Konkrétní podrobnosti o výpočtu a minimalizaci ztráty se řídí kritériem ztráty a algoritmem optimalizátoru, který zvolíte.

Kritéria ztráty

PyTorch podporuje více funkcí kritérií ztráty, včetně (mimo jiné):

  • cross_entropy: Funkce, která měří agregační rozdíl mezi předpovídanými a skutečnými hodnotami pro více proměnných (obvykle se používá k měření ztráty pravděpodobností tříd ve vícetřídové klasifikaci).
  • binary_cross_entropy: Funkce, která měří rozdíl mezi predikovanými a skutečnými pravděpodobnostmi (obvykle se používá k měření ztráty pravděpodobností tříd v binární klasifikaci).
  • mse_loss: Funkce, která měří průměrnou druhou ztrátu chyb pro predikované a skutečné číselné hodnoty (obvykle se používá pro regresi).

Chcete-li určit kritérium ztráty, které chcete použít při trénování modelu, vytvoříte instanci příslušné funkce; Nějak tak:

import torch.nn as nn

loss_criteria = nn.CrossEntropyLoss

Tip

Další informace o dostupných kritériích ztráty v nástroji PyTorch naleznete v dokumentaci k nástroji PyTorch.

Algoritmy optimalizátoru

Při výpočtu ztráty se optimalizátor používá k určení toho, jak nejlépe upravit váhy a vyvážení, aby bylo možné ji minimalizovat. Optimalizátory jsou specifické implementace přístupu gradientního sestupu pro minimalizaci funkce. Mezi dostupné optimalizátory v PyTorch patří (mimo jiné):

Pokud chcete k trénování modelu použít některý z těchto algoritmů, musíte vytvořit instanci optimalizátoru a nastavit všechny požadované parametry. Konkrétní parametry se liší v závislosti na zvoleném optimalizátoru, ale většina vyžaduje, abyste zadali míru učení, která řídí velikost úprav provedených při každé optimalizaci.

Následující kód vytvoří instanci Adam optimizeru.

import torch.optim as opt

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

Tip

Další informace o dostupných optimalizátorech v PyTorch naleznete v dokumentaci k PyTorch.

Vytvoření trénování a testování funkcí

Jakmile nadefinujete síť a připravíte pro ni data, můžete tato data použít k trénování a otestování modelu předáním trénovacích dat přes síť, výpočtem ztráty, optimalizací váhy sítě a předsudky a ověřením výkonu sítě pomocí testovacích dat. Je běžné definovat funkci, která předává data přes síť, aby model vytrénuje s trénovacími daty, a samostatnou funkci pro testování modelu s testovacími daty.

Vytvoření trénové funkce

Následující příklad ukazuje funkci pro trénování modelu.

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

Následující příklad ukazuje funkci, která model otestuje.

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

Trénování modelu v několika epochách

Pokud chcete vytrénovat model hlubokého učení, obvykle spustíte trénovací funkci několikrát (označovanou jako epochy) s cílem snížit ztrátu vypočítanou z trénovacích dat každé epochy. Testovací funkci můžete použít k ověření, že ztráta z testovacích dat (na kterých nebyl model natrénován) také snižuje v souladu se ztrátou trénování – jinými slovy, že trénování modelu nevytrénuje model, který je přetažen na trénovací data.

Tip

Testovací funkci nemusíte spouštět pro každou epochu. Můžete se rozhodnout, že ji spustíte každou druhou epochu nebo jednou na konci. Testování modelu při trénování ale může být užitečné při určování, kolik epoch začne model převyšovat.

Následující kód trénuje model přes 50 epoch.

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)

Uložení stavu trénovaného modelu

Po úspěšném vytrénování modelu můžete ušetřit jeho hmotnosti a předsudky, jako je tato:

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

Pokud chcete model načíst a použít později, vytvořte instanci třídy sítě, na které je model založen, a načtěte uložené váhy a předsudky.

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