Modellen trainen met PyTorch
PyTorch is een veelgebruikt machine learning-framework voor het trainen van deep learning-modellen. In Azure Databricks is PyTorch vooraf geïnstalleerd in ML-clusters .
Notitie
De codefragmenten in deze eenheid worden gegeven als voorbeelden om belangrijke punten te benadrukken. U hebt de kans om code uit te voeren voor een volledig, werkend voorbeeld in de oefening verderop in deze module.
Een PyTorch-netwerk definiëren
In PyTorch zijn modellen gebaseerd op een netwerk dat u definieert. Het netwerk bestaat uit meerdere lagen, elk met opgegeven invoer en uitvoer. Daarnaast definieert het werk een doorstuurfunctie die functies toepast op elke laag wanneer gegevens via het netwerk worden doorgegeven.
Met de volgende voorbeeldcode wordt een netwerk gedefinieerd.
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
Hoewel de code in het begin complex kan lijken, definieert deze klasse een relatief eenvoudig netwerk met drie lagen:
- Een invoerlaag die vier invoerwaarden accepteert en vijf uitvoerwaarden genereert voor de volgende laag.
- Een laag die vijf invoer accepteert en vijf uitvoer genereert.
- Een laatste uitvoerlaag die vijf invoer accepteert en drie uitvoer genereert.
De doorstuurfunctie past de lagen toe op de invoergegevens (x), waarbij de uitvoer van elke laag wordt doorgegeven aan de volgende en ten slotte de uitvoer van de laatste laag wordt geretourneerd (die de labelvoorspellingsvector, y bevat). Een gerectificeerde lineaire eenheid (ReLU) activeringsfunctie wordt toegepast op de uitvoer van laag 1 en 2 om de uitvoerwaarden te beperken tot positieve getallen.
Notitie
Afhankelijk van het gebruikte type verliescriterium, kunt u ervoor kiezen om een activeringsfunctie, zoals een log_softmax , toe te passen op de retourwaarde om deze in het bereik van 0 tot en met 1 af te dwingen. Sommige verliescriteria (zoals CrossEntropyLoss, die vaak worden gebruikt voor classificatie met meerdere klassen), passen echter automatisch een geschikte functie toe.
Als u een model voor training wilt maken, hoeft u alleen maar een exemplaar van de netwerkklasse te maken als volgt:
myModel = MyNet()
Gegevens voorbereiden voor modellering
PyTorch-lagen werken aan gegevens die zijn opgemaakt als tensors - matrixachtige structuren. Er zijn verschillende functies om andere algemene gegevensindelingen te converteren naar tensors en u kunt een PyTorch-gegevenslaadprogramma definiëren om gegevenstenors te lezen in een model voor training of deductie.
Net als bij de meeste technieken voor machine learning onder supervisie moet u afzonderlijke gegevenssets definiëren voor training en validatie. Met deze scheiding kunt u valideren dat het model nauwkeurig voorspelt bij het weergeven van gegevens waarvoor het niet is getraind.
Met de volgende code worden twee gegevensladers gedefinieerd; een voor training en de andere voor het testen. In dit voorbeeld wordt ervan uitgegaan dat de brongegevens voor elk laadprogramma een Numpy-matrix met functiewaarden en een Numpy-matrix met overeenkomende labelwaarden zijn.
# 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)
De loaders in dit voorbeeld splitsen de gegevens op in batches van 30, die tijdens de training of deductie worden doorgegeven aan de doorstuurfunctie .
Kies een verliescriterium en optimalisatie-algoritme
Het model wordt getraind door de trainingsgegevens in het netwerk in te voeren, het verlies te meten (het geaggregeerde verschil tussen voorspelde en werkelijke waarden) en het netwerk te optimaliseren door de gewichten en balansen aan te passen om verlies te minimaliseren. De specifieke details van hoe verlies wordt berekend en geminimaliseerd, wordt bepaald door het verliescriterium en het optimalisatie-algoritme dat u kiest.
Verliescriteria
PyTorch ondersteunt meerdere functies voor verliescriteria, waaronder (onder andere):
- cross_entropy: Een functie die het geaggregeerde verschil meet tussen voorspelde en werkelijke waarden voor meerdere variabelen (meestal gebruikt om verlies voor klassekansen in classificatie met meerdere klassen te meten).
- binary_cross_entropy: Een functie die het verschil meet tussen voorspelde en werkelijke waarschijnlijkheden (meestal gebruikt om verlies voor klassekansen in binaire classificatie te meten).
- mse_loss: Een functie die het gemiddelde kwadratische foutverlies meet voor voorspelde en werkelijke numerieke waarden (meestal gebruikt voor regressie).
Als u het verliescriterium wilt opgeven dat u wilt gebruiken bij het trainen van uw model, maakt u een exemplaar van de juiste functie; als volgt:
import torch.nn as nn
loss_criteria = nn.CrossEntropyLoss
Tip
Zie de documentatie van PyTorch voor meer informatie over beschikbare verliescriteria in PyTorch.
Optimizer-algoritmen
Nadat u het verlies hebt berekend, wordt een optimizer gebruikt om te bepalen hoe u het gewicht en de balansen het beste kunt aanpassen om dit te minimaliseren. Optimalisaties zijn specifieke implementaties van een gradiëntafnamebenadering om een functie te minimaliseren. Beschikbare optimalisatiefuncties in PyTorch zijn onder andere:
- Adadelta: Een optimizer op basis van het algoritme adaptieve leersnelheid .
- Adam: Een rekenkrachtefficiënte optimizer op basis van het Adam-algoritme .
- SGD: Een optimizer op basis van het stochastische gradiëntafname-algoritme .
Als u een van deze algoritmen wilt gebruiken om een model te trainen, moet u een exemplaar van de optimizer maken en eventuele vereiste parameters instellen. De specifieke parameters variëren, afhankelijk van de gekozen optimalisatie, maar de meeste vereisen dat u een leersnelheid opgeeft die de grootte van aanpassingen bepaalt die bij elke optimalisatie worden aangebracht.
Met de volgende code wordt een exemplaar van de Adam Optimizer gemaakt.
import torch.optim as opt
learning_rate = 0.001
optimizer = opt.Adam(model.parameters(), lr=learning_rate)
Tip
Zie Algoritmen in de pyTorch-documentatie voor meer informatie over beschikbare optimalisaties in PyTorch.
Train- en testfuncties maken
Nadat u een netwerk hebt gedefinieerd en er gegevens voor hebt voorbereid, kunt u de gegevens gebruiken om een model te trainen en te testen door de trainingsgegevens door te geven via het netwerk, het verlies te berekenen, de netwerkgewichten en vooroordelen te optimaliseren en de prestaties van het netwerk te valideren met de testgegevens. Het is gebruikelijk om een functie te definiëren die gegevens via het netwerk doorgeeft om het model te trainen met de trainingsgegevens en een afzonderlijke functie om het model te testen met de testgegevens.
Een trainfunctie maken
In het volgende voorbeeld ziet u een functie om een model te trainen.
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
In het volgende voorbeeld ziet u een functie om het model te testen.
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
Het model trainen over meerdere tijdvakken
Als u een Deep Learning-model wilt trainen, voert u doorgaans de trainingsfunctie meerdere keren uit (ook wel epochs genoemd), met als doel het verlies te verminderen dat wordt berekend op basis van de trainingsgegevens in elk tijdvak. U kunt uw testfunctie gebruiken om te controleren of het verlies van de testgegevens (waarop het model niet is getraind) ook afneemt in overeenstemming met het trainingsverlies, met andere woorden dat de modeltraining geen model produceert dat is aangepast aan de trainingsgegevens.
Tip
U hoeft de testfunctie niet uit te voeren voor elk tijdvak. U kunt ervoor kiezen om het om de tweede periode of één keer aan het einde uit te voeren. Het testen van het model zoals het is getraind, kan echter nuttig zijn bij het bepalen van het aantal tijdvakken dat een model begint te worden aangepast.
Met de volgende code traint u een model van meer dan 50 epochs.
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)
De getrainde modelstatus opslaan
Nadat u een model hebt getraind, kunt u de gewichten en vooroordelen als volgt besparen:
model_file = '/dbfs/my_model.pkl'
torch.save(model.state_dict(), model_file)
Als u het model op een later tijdstip wilt laden en gebruiken, maakt u een exemplaar van de netwerkklasse waarop het model is gebaseerd en laadt u de opgeslagen gewichten en vooroordelen.
model = myNet()
model.load_state_dict(torch.load(model_file))