[PYTHON] [Tutoriel PyTorch ⑥] Qu'est-ce que torch.nn?

introduction

Ceci est le 6ème volet de PyTorch Tutoriel officiel après Dernière fois. Cette fois, nous allons procéder avec Qu'est-ce que torch.nn vraiment?.

What is torch.nn really?

Ce didacticiel décrit torch.nn, torch.optim, Dataset et DataLoader. (Bien que torch.nn et torch.optim aient été expliqués la dernière fois, il y a des chevauchements car plusieurs personnes ont écrit des tutoriels.)

L'ensemble de données utilisé est l'ensemble de données MNIST. L'ensemble de données MNIST est un ensemble de données d'images numériques manuscrites de 0 à 9. Pour mieux comprendre, commencez par créer le modèle sans utiliser les packages ci-dessus. Ensuite, nous allons procéder en remplaçant le code un par un dans l'ordre torch.nn, torch.optim, Dataset, DataLoader.

  1. MNIST data setup

Tout d'abord, téléchargez le jeu de données MNIST (jeu de données d'images numériques manuscrites).

from pathlib import Path
import requests

DATA_PATH = Path("data")
PATH = DATA_PATH / "mnist"

PATH.mkdir(parents=True, exist_ok=True)

URL = "http://deeplearning.net/data/mnist/"
FILENAME = "mnist.pkl.gz"

if not (PATH / FILENAME).exists():
        content = requests.get(URL + FILENAME).content
        (PATH / FILENAME).open("wb").write(content)

Cet ensemble de données est un tableau numpy. Il est enregistré au format pickle.

import pickle
import gzip

with gzip.open((PATH / FILENAME).as_posix(), "rb") as f:
        ((x_train, y_train), (x_valid, y_valid), _) = pickle.load(f, encoding="latin-1")

Une donnée (x_train [0]) est une image de taille 28x28, mais elle est conservée comme une ligne avec 784 colonnes. Pour l'afficher avec pyplot.imshow, vous devez le convertir en 28x28.

from matplotlib import pyplot
import numpy as np

pyplot.imshow(x_train[0].reshape((28, 28)), cmap="gray")
print(x_train.shape)

out


(50000, 784)

ダウンロード.png

À partir de maintenant, nous utiliserons le Tensor de PyTorch. Conversion d'un tableau numpy en Tensor.

import torch

x_train, y_train, x_valid, y_valid = map(
    torch.tensor, (x_train, y_train, x_valid, y_valid)
)
n, c = x_train.shape
x_train, x_train.shape, y_train.min(), y_train.max()
print(x_train, y_train)
print(x_train.shape)
print(y_train.min(), y_train.max())

out


tensor([[0., 0., 0.,  ..., 0., 0., 0.],
        [0., 0., 0.,  ..., 0., 0., 0.],
        [0., 0., 0.,  ..., 0., 0., 0.],
        ...,
        [0., 0., 0.,  ..., 0., 0., 0.],
        [0., 0., 0.,  ..., 0., 0., 0.],
        [0., 0., 0.,  ..., 0., 0., 0.]]) tensor([5, 0, 4,  ..., 8, 4, 8])
torch.Size([50000, 784])
tensor(0) tensor(9)

Vous pouvez voir que le nombre de données d'entraînement est de 50 000 (× 784) et que les données d'enseignant sont un nombre compris entre 0 et 9.

  1. Neural net from scratch (no torch.nn)

Tout d'abord, créez un réseau neuronal uniquement avec Tensor sans utiliser torch.nn. Le modèle à créer est un modèle linéaire simple $ y = w \times x + b$ est.

Initialisez le poids $ w $ avec la méthode aléatoire de PyTorch randn. randn est une valeur aléatoire normalisée (0 moyenne, 1 écart type). Nous ne voulons pas inclure le gradient lors de l'initialisation, nous faisons donc require_grad_ () après l'initialisation et définissons require_grad = True. L'initialisation du poids utilise "l'initialisation Xavier". (Il y en a, mais j'ai l'impression que la formule de calcul est un peu différente) Le biais est initialisé à zéro.

import math

weights = torch.randn(784, 10) / math.sqrt(784)
weights.requires_grad_()
bias = torch.zeros(10, requires_grad=True)

Nous avons également besoin d'une fonction d'activation, alors créez une fonction log_softmax. PyTorch fournit un certain nombre de fonctions de perte et d'activation, mais vous pouvez également créer les vôtres de cette manière.

def log_softmax(x):
    return x - x.exp().sum(-1).log().unsqueeze(-1)

def model(xb):
    return log_softmax(xb @ weights + bias)

@ Représente une opération de produit interne. Cette fonction est appelée en taille de lot (64 images cette fois).

bs = 64  # batch size

xb = x_train[0:bs]  #Mini lot
preds = model(xb)  #Attendez avec le modèle
preds[0], preds.shape
print(preds[0], preds.shape)

out


tensor([-2.8486, -2.2823, -2.2740, -2.7800, -2.1906, -1.3280, -2.4680, -2.2958,
        -2.8856, -2.8650], grad_fn=<SelectBackward>) torch.Size([64, 10])

Si vous sortez les preds de valeur prédite, vous pouvez voir que Tensor contient une fonction de gradient (grad_fn). Plus tard, nous utiliserons cette fonction de gradient pour calculer la rétropropagation. En tant que fonction de perte, implémentez la probabilité logarithmique négative des données de l'enseignant et de la valeur prédite. La probabilité logarithmique négative est communément appelée fonction d'erreur d'entropie croisée.

def nll(input, target):
    return -input[range(target.shape[0]), target].mean()

loss_func = nll

Calculez la perte avec la valeur prévue et les données de l'enseignant, et vérifiez les paramètres après la formation.

yb = y_train[0:bs]
print(loss_func(preds, yb))

out


tensor(2.4101, grad_fn=<NegBackward>)

Il implémente également une fonction d'évaluation qui calcule la précision du modèle. Puisque out contient les probabilités des nombres manuscrits de 0 à 9 dans un tableau, la valeur maximale de argmax est le nombre manuscrit le plus probable. Le taux de réponse correct est calculé en prenant la moyenne correspondante de la valeur et des données de l'enseignant.

def accuracy(out, yb):
    preds = torch.argmax(out, dim=1)
    return (preds == yb).float().mean()
print(accuracy(preds, yb))

out


tensor(0.0781)

Vous êtes maintenant prêt à apprendre. Répétez ce qui suit pour apprendre.

--Acquérir des données d'entraînement dans des unités mini-batch. --Utilisez un modèle pour faire des prédictions à partir des données d'entraînement. --Calculez la perte. --Mettez à jour le gradient du modèle (poids et biais) avec loss.backward ().

Après avoir mis à jour les poids et le biais, j'initialise le dégradé avec grad.zero_ (). En effet, lors du calcul du dégradé avec loss.backward (), il est ajouté à ce qui est déjà enregistré.

from IPython.core.debugger import set_trace

lr = 0.5  # learning rate
epochs = 2  # how many epochs to train for

for epoch in range(epochs):
    for i in range((n - 1) // bs + 1):
        #set_trace()
        start_i = i * bs
        end_i = start_i + bs
        xb = x_train[start_i:end_i]
        yb = y_train[start_i:end_i]
        pred = model(xb)
        loss = loss_func(pred, yb)

        loss.backward()
        with torch.no_grad():
            weights -= weights.grad * lr
            bias -= bias.grad * lr
            weights.grad.zero_()
            bias.grad.zero_()

Vous pouvez voir que la précision s'est améliorée après l'apprentissage.

print(loss_func(model(xb), yb), accuracy(model(xb), yb))

out


tensor(0.0822, grad_fn=<NegBackward>) tensor(1.)

Avant l'apprentissage, le taux de réponse correcte était de 7%, mais après l'apprentissage, il est de 100%.

Vous disposez désormais d'un réseau neuronal simple construit à partir de zéro. Le réseau utilisant la fonction Softmax sans la couche cachée cette fois est appelé régression logistique.

  1. Using torch.nn.functional

À partir de là, nous utiliserons le package nn de PyTorch pour refactoriser notre code. Dans un premier temps, remplaçons la fonction d'activation et la fonction de perte. torch.nn.functional a F.cross_entropy, qui combine la fonction log_softmax avec une probabilité log négative. Remplacez la fonction de perte par F.cross_entropy. Puisque F.cross_entropy inclut la fonction log_softmax, vous pouvez également supprimer la def log_softmax (x) définie comme fonction d'activation.

import torch.nn.functional as F

loss_func = F.cross_entropy

def model(xb):
    return xb @ weights + bias

Le log_softmax qui a été appelé par model n'est plus nécessaire. (Inclus dans cross_entropy) Assurez-vous que la perte et la précision sont les mêmes qu'auparavant.

print(loss_func(model(xb), yb), accuracy(model(xb), yb))

out


tensor(0.0822, grad_fn=<NllLossBackward>) tensor(1.)
  1. Refactor using nn.Module

Ensuite, nous refactoriserons en utilisant nn.Module et nn.Parameter. nn.Module est la classe de base du réseau neuronal de Pytorch. Implémentez nn.Module en tant que sous-classe. Définissez les paramètres de pondération et de biais dans la sous-classe que vous avez créée. Décrivez également le processus de connexion de l'entrée à la sortie dans l'ordre dans la méthode de transfert. nn.Module est également fourni avec parameters (), qui renvoie les paramètres du modèle.

from torch import nn

class Mnist_Logistic(nn.Module):
    def __init__(self):
        super().__init__()
        self.weights = nn.Parameter(torch.randn(784, 10) / math.sqrt(784))
        self.bias = nn.Parameter(torch.zeros(10))

    def forward(self, xb):
        return xb @ self.weights + self.bias

Puisque nous utilisons des objets au lieu de fonctions, nous devons d'abord instancier le modèle.

model = Mnist_Logistic()

Vous pouvez maintenant apprendre comme vous l'avez fait avant la refactorisation. L'objet nn.Module peut être appelé et utilisé comme une fonction.

print(loss_func(model(xb), yb))

out


tensor(2.3918, grad_fn=<NllLossBackward>)

Dans la mise en œuvre jusqu'à présent, les mises à jour du poids et du biais ont été calculées respectivement comme suit, et le gradient a été réglé manuellement à zéro.

  with torch.no_grad():
      weights -= weights.grad * lr
      bias -= bias.grad * lr
      weights.grad.zero_()
      bias.grad.zero_()

Les mises à jour de poids et de biais peuvent être simplifiées en les remplaçant par les paramètres () et zero_grad () définis dans nn.Module.

  #Ne peut pas être exécuté car il s'agit d'un code explicatif (une erreur d'exécution se produira)
  with torch.no_grad():
      for p in model.parameters(): p -= p.grad * lr
      model.zero_grad()

Définissez la boucle d'apprentissage comme une fonction d'ajustement afin qu'elle puisse être appelée.

def fit():
    for epoch in range(epochs):
        for i in range((n - 1) // bs + 1):
            start_i = i * bs
            end_i = start_i + bs
            xb = x_train[start_i:end_i]
            yb = y_train[start_i:end_i]
            pred = model(xb)
            loss = loss_func(pred, yb)

            loss.backward()
            with torch.no_grad():
                for p in model.parameters():
                    p -= p.grad * lr
                model.zero_grad()

fit()

Reconfirmons que la perte est réduite.

print(loss_func(model(xb), yb))

out


tensor(0.0796, grad_fn=<NllLossBackward>)
  1. Refactor using nn.Linear

J'ai d'abord défini moi-même les poids et les biais et implémenté la fonction linéaire $ w \ times x + b $, mais remplaçons-la par nn.Linear (couche linéaire).

class Mnist_Logistic(nn.Module):
    def __init__(self):
        super().__init__()
        self.lin = nn.Linear(784, 10)

    def forward(self, xb):

        return self.lin(xb)

Instanciez le modèle comme précédemment et calculez la perte.

model = Mnist_Logistic()
print(loss_func(model(xb), yb))

out


tensor(2.3661, grad_fn=<NllLossBackward>)

Apprenez en appelant un ajustement fonctionnalisé.

fit()
print(loss_func(model(xb), yb))

out


tensor(0.0813, grad_fn=<NllLossBackward>)

La valeur de perte est passée de 2,3661 à 0,0813, confirmant que l'apprentissage est possible.

  1. Refactor using optim

Refactorisez ensuite l'algorithme d'optimisation. Le package torch.optim de Pytorch dispose d'une variété d'algorithmes d'optimisation. De plus, chaque classe de torch.optim met à jour les paramètres en exécutant la méthode step au lieu de mettre à jour les paramètres manuellement.

  with torch.no_grad():
      for p in model.parameters(): p -= p.grad * lr
      model.zero_grad()

Vous pouvez réécrire le code ci-dessus comme suit.

  #Ne peut pas être exécuté en raison d'un code explicatif
  opt.step()
  opt.zero_grad()
from torch import optim

La fonctionnalisation de la génération de modèles et d'optimiseurs simplifie le code.

def get_model():
    model = Mnist_Logistic()
    return model, optim.SGD(model.parameters(), lr=lr)

model, opt = get_model()
print(loss_func(model(xb), yb))

for epoch in range(epochs):
    for i in range((n - 1) // bs + 1):
        start_i = i * bs
        end_i = start_i + bs
        xb = x_train[start_i:end_i]
        yb = y_train[start_i:end_i]
        pred = model(xb)
        loss = loss_func(pred, yb)

        loss.backward()
        opt.step()
        opt.zero_grad()

print(loss_func(model(xb), yb))

out


tensor(2.3423, grad_fn=<NllLossBackward>)
tensor(0.0819, grad_fn=<NllLossBackward>)
  1. Refactor using Dataset

PyTorch a une classe abstraite Dataset. Dataset facilite la gestion des données de formation (x_train) et des données de l'enseignant (y_train) pendant la formation. L'ensemble de données doit implémenter une fonction __len__ qui renvoie le nombre d'éléments et une fonction __getitem__ qui renvoie des éléments en spécifiant un index. TensorDataset encapsule l'ensemble de données dans Tensor.

from torch.utils.data import TensorDataset

Créez TensorDataset en spécifiant x_train et y_train lors de sa création.

train_ds = TensorDataset(x_train, y_train)

Auparavant, les données de formation (x_train) et les données de l'enseignant (y_train) étaient traitées itérativement séparément.

    xb = x_train[start_i:end_i]
    yb = y_train[start_i:end_i]

Vous pouvez utiliser TensorDataset pour tout traiter en même temps.

    xb,yb = train_ds[i*bs : i*bs+bs]
model, opt = get_model()

for epoch in range(epochs):
    for i in range((n - 1) // bs + 1):
        xb, yb = train_ds[i * bs: i * bs + bs]
        pred = model(xb)
        loss = loss_func(pred, yb)

        loss.backward()
        opt.step()
        opt.zero_grad()

print(loss_func(model(xb), yb))

out


tensor(0.0803, grad_fn=<NllLossBackward>)
  1. Refactor using DataLoader

DataLoader peut être utilisé pour simplifier la mise en boucle avec Dataset. Créez un DataLoader basé sur l'ensemble de données.

from torch.utils.data import DataLoader

train_ds = TensorDataset(x_train, y_train)
train_dl = DataLoader(train_ds, batch_size=bs)

Dans le premier code, nous avons spécifié la position de départ pour chaque taille de lot et l'avons découpée en tranches.

for i in range((n-1)//bs + 1):
    xb,yb = train_ds[i*bs : i*bs+bs]
    pred = model(xb)

Le DataLoader simplifie la boucle car (xb, yb) sont automatiquement chargés séquentiellement à partir du DataLoader.

for xb,yb in train_dl:
    pred = model(xb)
model, opt = get_model()

for epoch in range(epochs):
    for xb, yb in train_dl:
        pred = model(xb)
        loss = loss_func(pred, yb)

        loss.backward()
        opt.step()
        opt.zero_grad()

print(loss_func(model(xb), yb))

out


tensor(0.0802, grad_fn=<NllLossBackward>)

Jusqu'à présent, nous avons utilisé nn.Module, nn.Parameter, Dataset et DataLoader. J'ai pu écrire le code de manière concise et simple. Ensuite, ajoutons les fonctions de base nécessaires pour créer un modèle efficace.

  1. Add validation

Jusqu'à présent, l'apprentissage ne s'est déroulé qu'avec des données d'entraînement, mais dans l'apprentissage réel, les données de validation sont utilisées pour vérifier si un surentraînement s'est produit et si l'apprentissage a progressé. Configurez le jeu de données de validation ci-dessous.

train_ds = TensorDataset(x_train, y_train)
train_dl = DataLoader(train_ds, batch_size=bs, shuffle=True)

valid_ds = TensorDataset(x_valid, y_valid)
valid_dl = DataLoader(valid_ds, batch_size=bs * 2)

À la fin de chaque époque, utilisez les données de validation pour calculer la perte. Mettez model.train () en mode entraînement avant l'entraînement et model.eval () en mode évaluation avant validation. Cela permet d'activer nn.Dropout etc. uniquement pendant l'entraînement.

model, opt = get_model()

for epoch in range(epochs):
    model.train()
    for xb, yb in train_dl:
        pred = model(xb)
        loss = loss_func(pred, yb)

        loss.backward()
        opt.step()
        opt.zero_grad()

    model.eval()
    with torch.no_grad():
        valid_loss = sum(loss_func(model(xb), yb) for xb, yb in valid_dl)

    print(epoch, valid_loss / len(valid_dl))

out


0 tensor(0.3679)
1 tensor(0.2997)
  1. Create fit() and get_data()

Ensuite, créez une fonction loss_batch qui peut effectuer à la fois la formation et la validation. La transmission de l'optimiseur à loss_batch calcule la rétropropagation et met à jour les paramètres. La rétropropagation n'est pas calculée en ne passant pas l'optimiseur pendant la vérification.

def loss_batch(model, loss_func, xb, yb, opt=None):
    loss = loss_func(model(xb), yb)

    if opt is not None:
        loss.backward()
        opt.step()
        opt.zero_grad()

    return loss.item(), len(xb)

Définissez la fonction d'ajustement. La fonction d'ajustement itère l'entraînement et la validation à chaque époque et affiche la perte.

import numpy as np

def fit(epochs, model, loss_func, opt, train_dl, valid_dl):
    for epoch in range(epochs):
        model.train()
        for xb, yb in train_dl:
            loss_batch(model, loss_func, xb, yb, opt)

        model.eval()
        with torch.no_grad():
            losses, nums = zip(
                *[loss_batch(model, loss_func, xb, yb) for xb, yb in valid_dl]
            )
        val_loss = np.sum(np.multiply(losses, nums)) / np.sum(nums)

        print(epoch, val_loss)

get_data renvoie un DataLoader pour les données d'entraînement et de validation.

def get_data(train_ds, valid_ds, bs):
    return (
        DataLoader(train_ds, batch_size=bs, shuffle=True),
        DataLoader(valid_ds, batch_size=bs * 2),
    )

Vous pouvez maintenant écrire le processus d'obtention du DataLoader et d'effectuer la formation en trois lignes de code.

train_dl, valid_dl = get_data(train_ds, valid_ds, bs)
model, opt = get_model()
fit(epochs, model, loss_func, opt, train_dl, valid_dl)

out


0 0.45953697173595426
1 0.3061695278286934

Vous pouvez créer différents modèles en refactorisant les trois lignes de code. Voyons si nous pouvons construire un réseau de neurones convolutifs (CNN)!

  1. Switch to CNN

À partir de là, nous allons construire un réseau de neurones avec trois couches de convolution. Les fonctions créées jusqu'à présent n'ont aucune restriction de modèle, vous pouvez donc basculer le CNN vers sans apporter de modifications.

Utilisez la classe Conv2d fournie par Pytorch comme couche de convolution. Définissez le CNN avec trois couches convolutives. La fonction d'activation pour chaque couche convolutive est ReLU. Enfin, ajoutez une couche de pooling moyenne. (La vue est une version PyTorch de la variante numpy)

class Mnist_CNN(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(1, 16, kernel_size=3, stride=2, padding=1)
        self.conv2 = nn.Conv2d(16, 16, kernel_size=3, stride=2, padding=1)
        self.conv3 = nn.Conv2d(16, 10, kernel_size=3, stride=2, padding=1)

    def forward(self, xb):
        xb = xb.view(-1, 1, 28, 28)
        xb = F.relu(self.conv1(xb))
        xb = F.relu(self.conv2(xb))
        xb = F.relu(self.conv3(xb))
        xb = F.avg_pool2d(xb, 4)
        return xb.view(-1, xb.size(1))

lr = 0.1

Momentum est une variante de la méthode de descente de gradient probabiliste qui prend également en compte la dernière valeur mise à jour, ce qui conduit généralement à un entraînement plus rapide.

model = Mnist_CNN()
opt = optim.SGD(model.parameters(), lr=lr, momentum=0.9)

fit(epochs, model, loss_func, opt, train_dl, valid_dl)

out


0 0.7808464194297791
1 0.6988550303936004
  1. nn.Sequential

torch.nn a une autre classe pratique, Sequential, que vous pouvez utiliser pour simplifier votre code. L'objet Sequential exécute chaque module qu'il contient en séquence. La caractéristique est que vous pouvez facilement décrire le réseau.

Vous aurez peut-être besoin d'un calque personnalisé pour tirer parti de Sequential. PyTorch n'a pas de couche qui transforme les dimensions du réseau (couche), vous devrez donc créer votre propre couche de vue. Le Lambda suivant définit la couche d'entrée / sortie gérée par Sequential.

class Lambda(nn.Module):
    def __init__(self, func):
        super().__init__()
        self.func = func

    def forward(self, x):
        return self.func(x)


def preprocess(x):
    return x.view(-1, 1, 28, 28)

Sequential permet de décrire facilement votre réseau comme suit:

model = nn.Sequential(
    Lambda(preprocess),
    nn.Conv2d(1, 16, kernel_size=3, stride=2, padding=1),
    nn.ReLU(),
    nn.Conv2d(16, 16, kernel_size=3, stride=2, padding=1),
    nn.ReLU(),
    nn.Conv2d(16, 10, kernel_size=3, stride=2, padding=1),
    nn.ReLU(),
    nn.AvgPool2d(4),
    Lambda(lambda x: x.view(x.size(0), -1)),
)

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

fit(epochs, model, loss_func, opt, train_dl, valid_dl)

out


0 0.4288556560516357
1 0.2115058801174164
  1. Wrapping DataLoader

Le CNN que j'ai créé est assez concis, mais il ne fonctionne qu'avec les données MNIST (images numériques manuscrites) en raison des restrictions suivantes:

Supprimez ces deux hypothèses et permettez au modèle de fonctionner avec n'importe quelle image 2D monocanal (image monochromatique). Tout d'abord, supprimez la première couche Lambda et déplacez le prétraitement des données vers le chargeur de données.

def preprocess(x, y):
    return x.view(-1, 1, 28, 28), y


class WrappedDataLoader:
    def __init__(self, dl, func):
        self.dl = dl
        self.func = func

    def __len__(self):
        return len(self.dl)

    def __iter__(self):
        batches = iter(self.dl)
        for b in batches:
            yield (self.func(*b))

train_dl, valid_dl = get_data(train_ds, valid_ds, bs)
train_dl = WrappedDataLoader(train_dl, preprocess)
valid_dl = WrappedDataLoader(valid_dl, preprocess)

Remplacez ensuite nn.AvgPool2d par nn.AdaptiveAvgPool2d. Cela vous permet de définir la taille du tenseur de sortie que vous voulez, pas le tenseur d'entrée. En conséquence, la couche de mise en commun moyenne fonctionne avec des entrées de toute taille.

model = nn.Sequential(
    nn.Conv2d(1, 16, kernel_size=3, stride=2, padding=1),
    nn.ReLU(),
    nn.Conv2d(16, 16, kernel_size=3, stride=2, padding=1),
    nn.ReLU(),
    nn.Conv2d(16, 10, kernel_size=3, stride=2, padding=1),
    nn.ReLU(),
    nn.AdaptiveAvgPool2d(1),
    Lambda(lambda x: x.view(x.size(0), -1)),
)

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

Essayons.

fit(epochs, model, loss_func, opt, train_dl, valid_dl)

out


0 0.3351769802570343
1 0.2583931807518005
  1. Using your GPU

Si vous disposez d'un GPU compatible CUDA (la plupart des fournisseurs de cloud coûtent environ 0,50 USD par heure), vous pouvez accélérer votre apprentissage. Tout d'abord, assurez-vous que votre GPU fonctionne sur Pytorch.

print(torch.cuda.is_available())

out


True

Ensuite, créez un objet périphérique. L'objet périphérique est défini sur «cuda» si le GPU est disponible ou sur «cpu» s'il n'est pas disponible.

dev = torch.device(
    "cuda") if torch.cuda.is_available() else torch.device("cpu")

Ajoutez un prétraitement pour déplacer le lot vers le GPU.

def preprocess(x, y):
    return x.view(-1, 1, 28, 28).to(dev), y.to(dev)

train_dl, valid_dl = get_data(train_ds, valid_ds, bs)
train_dl = WrappedDataLoader(train_dl, preprocess)
valid_dl = WrappedDataLoader(valid_dl, preprocess)

Enfin, déplacez le modèle vers le GPU.

model.to(dev)
opt = optim.SGD(model.parameters(), lr=lr, momentum=0.9)

Vous pouvez voir que la vitesse de traitement a augmenté.

fit(epochs, model, loss_func, opt, train_dl, valid_dl)

out


0 0.1938392831325531
1 0.18594802458286286

Lorsque j'ai vérifié avec Google Colaboratory, le processus ci-dessus, qui a pris environ 15 secondes pour le processeur, s'est terminé en environ 5 secondes.

15. Réflexions finales (résumé)

Dans ce didacticiel, vous avez créé des données et des processus d'entraînement indépendants du modèle. Nous aimerions ajouter de nombreux éléments, tels que l'augmentation des données, le réglage des hyperparamètres, le suivi de la formation et l'apprentissage par transfert. Ces fonctionnalités sont disponibles dans la bibliothèque fastai. La bibliothèque fastai a été développée en utilisant la même approche de conception que celle présentée dans ce didacticiel et sera une bonne étape pour quiconque apprend davantage l'apprentissage automatique.

Pour ce didacticiel, nous avons utilisé torch.nn, torch.optim, Dataset et DataLoader. Résumons ce que nous avons vu jusqu'à présent.

16. Enfin

C'est "Qu'est-ce que torch.nn vraiment?" C'était similaire à la dernière fois, mais j'ai pu approfondir ma compréhension de Pytorch et des réseaux de neurones. La prochaine fois, j'aimerais continuer avec "Visualisation des modèles, des données et de la formation avec Tensor Board".

Histoire

2020/10/10 Première édition publiée

Recommended Posts

[Tutoriel PyTorch ⑥] Qu'est-ce que torch.nn?
Qu'est-ce que l'espace de noms
Qu'est-ce que copy.copy ()
Qu'est-ce que Django? .. ..
Qu'est-ce que dotenv?
Qu'est-ce que POSIX
Qu'est-ce que Linux
Qu'est-ce que SALOME?
Qu'est-ce que python
Qu'est-ce que l'hyperopt?
Qu'est-ce que Linux
Qu'est-ce que pyvenv
Qu'est-ce que __call__
Qu'est-ce que Linux
Qu'est-ce que Python
Qu'est-ce qu'une distribution?
Qu'est-ce que le F-Score de Piotroski?
Qu'est-ce que Raspberry Pi?
[Python] Qu'est-ce que Pipeline ...
Qu'est-ce que Calmar Ratio?
Qu'est-ce que le réglage des hyper paramètres?
Qu'est-ce qu'un hacker?
PyTorch DataLoader est lent
À quoi sert Linux?
Qu'est-ce que l'apprentissage d'ensemble?
[Tutoriel PyTorch ③] RÉSEAUX NEURAUX
Qu'est-ce que __init__.py de Python?
Qu'est-ce qu'un itérateur?
Qu'est-ce que UNIT-V Linux?
[Python] Qu'est-ce que virtualenv
Qu'est-ce que l'apprentissage automatique?
Qu'est-ce que Mini Sam ou Mini Max?
Qu'est-ce que l'analyse de régression logistique?
[Tutoriel PyTorch ④] FORMATION D'UN CLASSIFICATEUR
Tutoriel [PyTorch] (version japonaise) ② ~ AUTOGRAD ~
Qu'est-ce qu'un arbre de décision?
Qu'est-ce qu'un changement de contexte?
Qu'est-ce que Google Cloud Dataflow?
[DL] Qu'est-ce que la décroissance du poids?
Qu'est-ce qu'un super utilisateur?
La programmation du concours, c'est quoi (bonus)
[Python] * args ** Qu'est-ce que kwrgs?
Qu'est-ce qu'un appel système
Tutoriel [PyTorch] (version japonaise) ① ~ Tensol ~
[Définition] Qu'est-ce qu'un cadre?
[Tutoriel PyTorch ②] Autograd: différenciation automatique
Tutoriel sur le réseau neuronal (CNN) de Pytorch 1.3.1.
A quoi sert l'interface ...
Qu'est-ce que Project Euler 3 Acceleration?
Qu'est-ce qu'une fonction de rappel?
Qu'est-ce que la fonction de rappel?
Quel est votre "coefficient de Tanimoto"?
Cours de base Python (1 Qu'est-ce que Python)