Freigeben über


Trainieren von Modellen mit PyTorch in Microsoft Fabric

In diesem Artikel wird beschrieben, wie Sie die Iterationen eines PyTorch-Modells trainieren und verfolgen können. Das Framework für maschinelles Lernen PyTorch basiert auf der Torch-Bibliothek. PyTorch wird häufig für Anwendungen für maschinelles Sehen und linguistische Datenverarbeitung verwendet.

Voraussetzungen

Installieren Sie PyTorch und torchvision in Ihrem Notebook. Sie können die Version dieser Bibliotheken in Ihrer Umgebung mit dem folgenden Befehl installieren oder upgraden:

pip install torch torchvision

Einrichten des Machine Learning-Experiments

Mithilfe der MLFLow-API können Sie ein Machine Learning-Experiment erstellen. Die MLflow-Funktion set_experiment() erstellt ein neues Machine Learning-Experiment namens sample-pytorch, sofern noch nicht vorhanden.

Führen Sie den folgenden Code in Ihrem Notebook aus, und erstellen Sie das Experiment:

import mlflow

mlflow.set_experiment("sample-pytorch")

Trainieren und Auswerten eines PyTorch-Modells

Nach Einrichtung des Experiments laden Sie das MNIST-Dataset (Modified National Institute of Standards and Technology). Sie generieren die Test- und Trainings-Datasets und erstellen dann eine Trainingsfunktion.

Führen Sie den folgenden Code im Notebook aus, und trainieren Sie das Pytorch-Modell:

import os
import torch
import torch.nn as nn
from torch.autograd import Variable
import torchvision.datasets as dset
import torchvision.transforms as transforms
import torch.nn.functional as F
import torch.optim as optim

# Load the MNIST dataset
root = "/tmp/mnist"
if not os.path.exists(root):
    os.mkdir(root)

trans = transforms.Compose(
    [transforms.ToTensor(), transforms.Normalize((0.5,), (1.0,))]
)

# If the data doesn't exist, download the MNIST dataset
train_set = dset.MNIST(root=root, train=True, transform=trans, download=True)
test_set = dset.MNIST(root=root, train=False, transform=trans, download=True)

batch_size = 100

train_loader = torch.utils.data.DataLoader(
    dataset=train_set, batch_size=batch_size, shuffle=True
)
test_loader = torch.utils.data.DataLoader(
    dataset=test_set, batch_size=batch_size, shuffle=False
) 

print("==>>> total trainning batch number: {}".format(len(train_loader)))
print("==>>> total testing batch number: {}".format(len(test_loader)))

# Define the network
class LeNet(nn.Module):
    def __init__(self):
        super(LeNet, self).__init__()
        self.conv1 = nn.Conv2d(1, 20, 5, 1)
        self.conv2 = nn.Conv2d(20, 50, 5, 1)
        self.fc1 = nn.Linear(4 * 4 * 50, 500)
        self.fc2 = nn.Linear(500, 10)

    def forward(self, x): 
        x = F.relu(self.conv1(x))
        x = F.max_pool2d(x, 2, 2)
        x = F.relu(self.conv2(x))
        x = F.max_pool2d(x, 2, 2)
        x = x.view(-1, 4 * 4 * 50)
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return x

    def name(self):
        return "LeNet"

# Train the model
model = LeNet()

optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)

criterion = nn.CrossEntropyLoss()

for epoch in range(1):
    # Model training
    ave_loss = 0
    for batch_idx, (x, target) in enumerate(train_loader):
        optimizer.zero_grad()
        x, target = Variable(x), Variable(target)
        out = model(x)
        loss = criterion(out, target)
        ave_loss = (ave_loss * batch_idx + loss.item()) / (batch_idx + 1)
        loss.backward()
        optimizer.step()
        if (batch_idx + 1) % 100 == 0 or (batch_idx + 1) == len(train_loader):
            print(
                "==>>> epoch: {}, batch index: {}, train loss: {:.6f}".format(
                    epoch, batch_idx + 1, ave_loss
                )
            )
    # Model testing
    correct_cnt, total_cnt, ave_loss = 0, 0, 0
    for batch_idx, (x, target) in enumerate(test_loader):
        x, target = Variable(x, volatile=True), Variable(target, volatile=True)
        out = model(x)
        loss = criterion(out, target)
        _, pred_label = torch.max(out.data, 1)
        total_cnt += x.data.size()[0]
        correct_cnt += (pred_label == target.data).sum()
        ave_loss = (ave_loss * batch_idx + loss.item()) / (batch_idx + 1)

        if (batch_idx + 1) % 100 == 0 or (batch_idx + 1) == len(test_loader):
            print(
                "==>>> epoch: {}, batch index: {}, test loss: {:.6f}, acc: {:.3f}".format(
                    epoch, batch_idx + 1, ave_loss, correct_cnt * 1.0 / total_cnt
                )
            )

torch.save(model.state_dict(), model.name())

Protokollieren eines Modells mit MLflow

Die nächste Aufgabe startet eine MLflow-Ausführung und verfolgt die Ergebnisse im Machine Learning-Experiment. Mit dem Beispielcode wird ein neues Modell mit dem Namen sample-pytorch erstellt. Mit dem Code wird eine Ausführung mit den angegebenen Parametern erstellt und die Ausführung im Experiment sample-pytorch protokolliert.

Führen Sie den folgenden Code im Notebook aus, und protokollieren Sie das Modell:

with mlflow.start_run() as run:
    print("log pytorch model:")
    mlflow.pytorch.log_model(
        model, "pytorch-model", registered_model_name="sample-pytorch"
    )

    model_uri = "runs:/{}/pytorch-model".format(run.info.run_id)
    print("Model saved in run %s" % run.info.run_id)
    print(f"Model URI: {model_uri}")

Laden, Binden und Auswerten des Modells

Nach dem Speichern des Modells können Sie es für das Rückschließen laden.

Führen Sie den folgenden Code im Notebook aus, und laden Sie das Modell für das Rückschließen:

# Inference with loading the logged model
loaded_model = mlflow.pytorch.load_model(model_uri)
print(type(loaded_model))

correct_cnt, total_cnt, ave_loss = 0, 0, 0
for batch_idx, (x, target) in enumerate(test_loader):
    x, target = Variable(x, volatile=True), Variable(target, volatile=True)
    out = loaded_model(x)
    loss = criterion(out, target)
    _, pred_label = torch.max(out.data, 1)
    total_cnt += x.data.size()[0]
    correct_cnt += (pred_label == target.data).sum()
    ave_loss = (ave_loss * batch_idx + loss.item()) / (batch_idx + 1)

    if (batch_idx + 1) % 100 == 0 or (batch_idx + 1) == len(test_loader):
        print(
            "==>>> epoch: {}, batch index: {}, test loss: {:.6f}, acc: {:.3f}".format(
                epoch, batch_idx + 1, ave_loss, correct_cnt * 1.0 / total_cnt
            )
        )