Ceci est le 5ème volet de PyTorch Tutoriel officiel après Dernière fois. Cette fois, nous allons procéder à Apprendre PyTorch avec des exemples.
Learning PyTorch with Examples
Ce didacticiel vous présentera deux fonctionnalités principales de PyTorch via un exemple de code.
Le réseau (modèle) géré par l'exemple de code est composé de 3 couches (couche d'entrée, couche cachée x 1, couche de sortie). La fonction d'activation utilise ReLU.
1.1. Warm-up: numpy
Avant PyTorch, implémentez d'abord le réseau en utilisant numpy. Numpy n'a pas de fonctionnalités pour l'apprentissage en profondeur, les dégradés, Vous pouvez créer un réseau neuronal simple en l'implémentant manuellement.
import numpy as np
#N: taille du lot
# D_in: Nombre de dimensions d'entrée
#H: nombre de dimensions du calque caché
# D_out: nombre de dimensions de sortie
N, D_in, H, D_out = 64, 1000, 100, 10
#Créer une entrée aléatoire et des données sur les enseignants
x = np.random.randn(N, D_in)
y = np.random.randn(N, D_out)
#Initialisez le poids avec une valeur aléatoire
w1 = np.random.randn(D_in, H)
w2 = np.random.randn(H, D_out)
learning_rate = 1e-6
for t in range(500):
#Propagation vers l'avant:Calcule la valeur prévue y avec la valeur de poids actuelle
h = x.dot(w1)
h_relu = np.maximum(h, 0)
y_pred = h_relu.dot(w2)
#Calcule et génère la perte
loss = np.square(y_pred - y).sum()
print(t, loss)
#En référence à la valeur de perte, calculez le gradient des poids w1 et w2 par rétro-propagation.
grad_y_pred = 2.0 * (y_pred - y)
grad_w2 = h_relu.T.dot(grad_y_pred)
grad_h_relu = grad_y_pred.dot(w2.T)
grad_h = grad_h_relu.copy()
grad_h[h < 0] = 0
grad_w1 = x.T.dot(grad_h)
#Mettez à jour le poids.
w1 -= learning_rate * grad_w1
w2 -= learning_rate * grad_w2
Lorsque vous exécutez ce code, vous pouvez voir que la valeur de la perte a diminué et que l'apprentissage progresse.
1.2. PyTorch: Tensors
Numpy ne peut pas être calculé à l'aide du GPU, mais le Tensor de PyTorch peut utiliser le GPU pour accélérer les calculs numériques. Tensor peut également calculer des dégradés, mais pour l'instant, implémentons-le manuellement, comme dans l'exemple numpy ci-dessus.
import torch
dtype = torch.float
device = torch.device("cpu")
# device = torch.device("cuda:0") #Décommentez ici pour exécuter sur le GPU.
#N: taille du lot
# D_in: Nombre de dimensions d'entrée
#H: nombre de dimensions du calque caché
# D_out: nombre de dimensions de sortie
N, D_in, H, D_out = 64, 1000, 100, 10
#Créer une entrée aléatoire et des données sur les enseignants
x = torch.randn(N, D_in, device=device, dtype=dtype)
y = torch.randn(N, D_out, device=device, dtype=dtype)
#Initialisez le poids avec une valeur aléatoire
w1 = torch.randn(D_in, H, device=device, dtype=dtype)
w2 = torch.randn(H, D_out, device=device, dtype=dtype)
learning_rate = 1e-6
for t in range(500):
#Propagation vers l'avant:Calcule la valeur prévue y avec la valeur de poids actuelle
h = x.mm(w1)
h_relu = h.clamp(min=0)
y_pred = h_relu.mm(w2)
#Calcule et génère la perte
loss = (y_pred - y).pow(2).sum().item()
if t % 100 == 99:
print(t, loss)
#En référence à la valeur de perte, calculez le gradient des poids w1 et w2 par rétro-propagation.
grad_y_pred = 2.0 * (y_pred - y)
grad_w2 = h_relu.t().mm(grad_y_pred)
grad_h_relu = grad_y_pred.mm(w2.t())
grad_h = grad_h_relu.clone()
grad_h[h < 0] = 0
grad_w1 = x.t().mm(grad_h)
#Mettre à jour les poids en utilisant la méthode de descente de gradient
w1 -= learning_rate * grad_w1
w2 -= learning_rate * grad_w2
Même avec ce code, vous pouvez voir que la valeur de la perte a diminué et que l'apprentissage progresse.
2.1. PyTorch: Tensors and autograd
Dans l'exemple ci-dessus, nous avons implémenté manuellement la propagation avant et arrière, mais vous pouvez utiliser le package autograd de PyTorch pour automatiser le calcul de la rétropropagation.
-Set requires_grad = True pour la variable (Tensor) pour laquelle vous voulez calculer le gradient. ・ Exécuter en arrière () Ces deux peuvent automatiser le calcul de rétropropagation.
import torch
dtype = torch.float
device = torch.device("cpu")
# device = torch.device("cuda:0") #Décommentez ici pour exécuter sur le GPU.
#N: taille du lot
# D_in: Nombre de dimensions d'entrée
#H: nombre de dimensions du calque caché
# D_out: nombre de dimensions de sortie
N, D_in, H, D_out = 64, 1000, 100, 10
#Créez un Tensor aléatoire pour contenir les données d'entrée et de l'enseignant.
# require_grad =Définissez sur False pour indiquer que le dégradé n'a pas besoin d'être calculé.
x = torch.randn(N, D_in, device=device, dtype=dtype)
y = torch.randn(N, D_out, device=device, dtype=dtype)
#Créez un Tensor aléatoire qui contient les poids.
# requires_grad =La valeur True indique que le dégradé sera calculé.
w1 = torch.randn(D_in, H, device=device, dtype=dtype, requires_grad=True)
w2 = torch.randn(H, D_out, device=device, dtype=dtype, requires_grad=True)
learning_rate = 1e-6
for t in range(500):
#Propagation vers l'avant:Calculer la valeur prévue y en utilisant l'arithmétique de Tensor
#Valeur intermédiaire h car la rétropropagation n'est pas calculée manuellement_relu n'a pas besoin d'être conservé
y_pred = x.mm(w1).clamp(min=0).mm(w2)
#Calculer et afficher les pertes à l'aide des opérations de Tensor
#La perte est la forme (1,) Tenseur
# loss.item()Obtient la valeur scalaire contenue dans la perte
loss = (y_pred - y).pow(2).sum()
if t % 100 == 99:
print(t, loss.item())
#Utilisez autograd pour calculer la rétropropagation
# backward()A besoin_grad =Calcule la pente de perte pour tous les tenseurs qui sont vrais
#Après cet appel, w1.grad et w2.grad est w1 respectivement,Devient un Tensor qui détient le gradient de w2
loss.backward()
#Mettez à jour manuellement les poids en utilisant la méthode de descente la plus raide
#Exiger pour le poids_grad =Parce qu'il y a vrai, torche.no_grad()Empêche la mise à jour du graphique de calcul avec
# torch.optim.Vous pouvez faire de même avec SGD
with torch.no_grad():
w1 -= learning_rate * w1.grad
w2 -= learning_rate * w2.grad
#Après avoir mis à jour les poids, définissez manuellement le dégradé sur zéro
w1.grad.zero_()
w2.grad.zero_()
Bien que pas dans le didacticiel, illustrons le graphique de calcul de rétropropagation. Les graphiques de calcul peuvent être illustrés en utilisant torchviz. Si vous utilisez colaboratory, vous devez l'installer.
!pip install torchviz
PyTorch: une petite modification de l'exemple de code Tensors. Arrêtez la boucle pour que le gradient ne soit calculé qu'une seule fois.
#Créer une entrée aléatoire et des données sur les enseignants
x = torch.randn(N, D_in, device=device, dtype=dtype)
y = torch.randn(N, D_out, device=device, dtype=dtype)
#Initialisez le poids avec une valeur aléatoire
w1 = torch.randn(D_in, H, device=device, dtype=dtype, requires_grad=True)
w2 = torch.randn(H, D_out, device=device, dtype=dtype, requires_grad=True)
#Propagation vers l'avant:Calcule la valeur prévue y avec la valeur de poids actuelle
h = x.mm(w1)
h_relu = h.clamp(min=0)
y_pred = h_relu.mm(w2)
#Calcule et génère la perte
loss = (y_pred - y).pow(2).sum().item()
#En référence à la valeur de perte, calculez le gradient des poids w1 et w2 par rétro-propagation.
grad_y_pred = 2.0 * (y_pred - y)
grad_w2 = h_relu.t().mm(grad_y_pred)
grad_h_relu = grad_y_pred.mm(w2.t())
grad_h = grad_h_relu.clone()
grad_h[h < 0] = 0
grad_w1 = x.t().mm(grad_h)
Diagrammez le graphe de calcul avec make_dot de torchviz. Illustre la propagation vers l'avant et le gradient. param_dict n'est pas obligatoire, mais il vous permet d'écrire des noms de variables dans le diagramme.
#Le graphe de calcul de la propagation vers l'avant est illustré.
from torchviz import make_dot
param_dict = {'w1': w1, 'w2': w2}
make_dot(loss, param_dict)
#Le graphique de calcul du gradient de w1 est affiché.
make_dot(grad_w1, param_dict)
#Le graphique de calcul du gradient de w2 est affiché.
make_dot(grad_w2, param_dict)
Le graphique de calcul est ci-dessous.
De même, modifiez l'exemple de code dans PyTorch: Tensors et autograd afin que le gradient ne soit calculé qu'une seule fois. La spécification de create_graph = True à l'exécution () préserve le graphe dérivé.
import torch
#Créez un Tensor aléatoire pour contenir les données d'entrée et de l'enseignant.
# require_grad =Définissez sur False pour indiquer que le dégradé n'a pas besoin d'être calculé.
x = torch.randn(N, D_in, device=device, dtype=dtype)
y = torch.randn(N, D_out, device=device, dtype=dtype)
#Créez un Tensor aléatoire qui contient les poids.
# requires_grad =La valeur True indique que le dégradé sera calculé.
w1 = torch.randn(D_in, H, device=device, dtype=dtype, requires_grad=True)
w2 = torch.randn(H, D_out, device=device, dtype=dtype, requires_grad=True)
#Propagation vers l'avant:Calculer la valeur prévue y en utilisant l'arithmétique de Tensor
#Valeur intermédiaire h car la rétropropagation n'est pas calculée manuellement_relu n'a pas besoin d'être conservé
y_pred = x.mm(w1).clamp(min=0).mm(w2)
#Calculer et afficher les pertes à l'aide des opérations de Tensor
#La perte est la forme (1,) Tenseur
# loss.item()Obtient la valeur scalaire contenue dans la perte
loss = (y_pred - y).pow(2).sum()
#Utilisez autograd pour calculer la rétropropagation
# backward()A besoin_grad =Calcule la pente de perte pour tous les tenseurs qui sont vrais
#Après cet appel, w1.grad et w2.grad est w1 respectivement,Devient un Tensor qui détient le gradient de w2
loss_backward = loss.backward(create_graph=True)
De même, le gradient calculé par propagation directe et autograde est illustré.
#Le graphe de calcul de la propagation vers l'avant est illustré.
param_dict = {'w1': w1, 'w2': w2}
make_dot(loss, param_dict)
#Le graphique de calcul du gradient de w1 est affiché.
make_dot(w1.grad, param_dict)
#Le graphique de calcul du gradient de w2 est affiché.
make_dot(w2.grad, param_dict)
La propagation vers l'avant est la même. La forme de la rétropropagation est légèrement différente, mais vous pouvez voir que le calcul de la rétropropagation se fait automatiquement par autograd.
2.2. PyTorch: Defining new autograd functions
Dans PyTorch, vous pouvez définir votre propre fonction (opérateur) en définissant une sous-classe de torch.autograd.Function. Implémentez les deux méthodes suivantes dans la sous-classe.
Dans cet exemple, nous définissons un réseau à deux niveaux avec notre propre fonction, ce qui signifie la fonction ReLU.
import torch
class MyReLU(torch.autograd.Function):
"""
torch.autograd.Fonction de sous-classe et
En mettant en œuvre des chemins vers l'avant et vers l'arrière qui fonctionnent avec Tensors
Vous pouvez implémenter votre propre fonction d'autogradation personnalisée.
"""
@staticmethod
def forward(ctx, input):
"""
Dans la passe avant, il reçoit le Tensor contenant l'entrée et
Renvoie le Tensor contenant la sortie.
ctx est un objet pour les calculs de rétropropagation.
ctx.save_for_Utilisez la méthode inverse
Vous pouvez mettre en cache des objets.
"""
ctx.save_for_backward(input)
return input.clamp(min=0)
@staticmethod
def backward(ctx, grad_output):
"""
En arrière, il reçoit un Tensor contenant le gradient de perte par rapport à la sortie.
Vous devez calculer le gradient de perte pour l'entrée.
"""
input, = ctx.saved_tensors
grad_input = grad_output.clone()
grad_input[input < 0] = 0
return grad_input
dtype = torch.float
device = torch.device("cpu")
# device = torch.device("cuda:0") #Décommentez ici pour exécuter sur le GPU.
#N: taille du lot
# D_in: Nombre de dimensions d'entrée
#H: nombre de dimensions du calque caché
# D_out: nombre de dimensions de sortie
N, D_in, H, D_out = 64, 1000, 100, 10
#Créez un Tensor aléatoire pour contenir les données d'entrée et de l'enseignant.
x = torch.randn(N, D_in, device=device, dtype=dtype)
y = torch.randn(N, D_out, device=device, dtype=dtype)
#Créez un Tensor aléatoire qui contient les poids.
w1 = torch.randn(D_in, H, device=device, dtype=dtype, requires_grad=True)
w2 = torch.randn(H, D_out, device=device, dtype=dtype, requires_grad=True)
learning_rate = 1e-6
for t in range(500):
#Pour appliquer une fonction, une fonction.Utilisez la méthode Apply.
relu = MyReLU.apply
#Propagation vers l'avant:Calculez la valeur prévue y à l'aide d'une fonction d'autogradation personnalisée
y_pred = relu(x.mm(w1)).mm(w2)
#Calculer et afficher la perte
loss = (y_pred - y).pow(2).sum()
if t % 100 == 99:
print(t, loss.item())
#Utilisez autograd pour calculer la rétropropagation
loss.backward()
#Mettre à jour les poids en utilisant la méthode de descente la plus raide
with torch.no_grad():
w1 -= learning_rate * w1.grad
w2 -= learning_rate * w2.grad
#Après avoir mis à jour les poids, définissez manuellement le dégradé sur zéro
w1.grad.zero_()
w2.grad.zero_()
Visualisons également la fonction d'origine. Comme auparavant, assurez-vous qu'il n'est traité qu'une seule fois.
#Créez un Tensor aléatoire pour contenir les données d'entrée et de l'enseignant.
x = torch.randn(N, D_in, device=device, dtype=dtype)
y = torch.randn(N, D_out, device=device, dtype=dtype)
#Créez un Tensor aléatoire qui contient les poids.
w1 = torch.randn(D_in, H, device=device, dtype=dtype, requires_grad=True)
w2 = torch.randn(H, D_out, device=device, dtype=dtype, requires_grad=True)
#Pour appliquer une fonction, une fonction.Utilisez la méthode Apply.
relu = MyReLU.apply
#Propagation vers l'avant:Calculez la valeur prévue y à l'aide d'une fonction d'autogradation personnalisée
y_pred = relu(x.mm(w1)).mm(w2)
#Calculer et afficher la perte
loss = (y_pred - y).pow(2).sum()
#Utilisez autograd pour calculer la rétropropagation
loss.backward(create_graph=True)
At-il un graphique de calcul similaire?
Cela fait longtemps, alors j'aimerais diviser PyTorch: nn dans la deuxième partie.
2020/05/27 Première édition publiée
Recommended Posts