Fonction torch.nn.ReLU de PyTorch
Manuel de référence torch.nn de PyTorch
torch.nn.ReLUC'est l'une des fonctions d'activation les plus couramment utilisées dans PyTorch. Elle effectue une opération d'unité linéaire rectifiée (ReLU) élément par élément sur le tenseur d'entrée.
ReLU est l'une des fonctions d'activation les plus efficaces en apprentissage profond car elle est simple sur le plan calculatoire, converge rapidement et atténue efficacement le problème de disparition du gradient.
Définition de fonction
torch.nn.ReLU(inplace=False)
Description des paramètres :
inplace(bool) : Si défini àTrue, il modifiera directement le tenseur d'entrée sur place, ce qui économise de la mémoire. La valeur par défaut estFalse。
Principe mathématique
nn.ReLULa formule de calcul est la suivante :
f(x) = max(0, x)
C'est-à-dire que pour chaque élément de l'entrée, si la valeur est supérieure à 0, elle reste inchangée ; si la valeur est inférieure ou égale à 0, la sortie est 0.
Cette simple transformation non linéaire permet au réseau d'apprendre des motifs complexes tout en maintenant la circulation du gradient.
Exemples d'utilisation
Exemple 1 : Utilisation de base
Créer une couche d'activation ReLU et appliquer l'activation à l'entrée :
Exemple
import torch.nn as nn
# Créer une couche d'activation ReLU
relu = nn.ReLU()
# Créer un tenseur d'entrée contenant des valeurs négatives
input_tensor = torch.tensor([[-1.0, 2.0, -3.0], [4.0, -5.0, 6.0]])
# Propagation avant
output = relu(input_tensor)
print("Input:\n", input_tensor)
print("Sortie :\n", output)
Le résultat de sortie est:
输入:
tensor([[-1., 2., -3.],
[ 4., -5., 6.]])
输出:
tensor([[0., 2., 0.],
[4., 0., 6.]])
Comme vous pouvez le voir, toutes les valeurs négatives sont mises à 0, et les valeurs positives restent inchangées.
Exemple 2 : Opération en place
L'utilisation du paramètre inplace peut économiser de la mémoire :
Exemple
import torch.nn as nn
# Créer une ReLU avec l'opération en place activée
relu_inplace = nn.ReLU(inplace=True)
# Créer un tenseur d'entrée
input_tensor = torch.randn(2, 4)
original_id = id(input_tensor)
# Modifier en place
output = relu_inplace(input_tensor)
# Vérifier si le tenseur d'origine a été modifié
print("Le tenseur d'origine a-t-il été modifié :", id(output) == original_id)
print("Entrée/Sortie :\n", input_tensor)
Le résultat de sortie est:
是否修改了原张量: True
输入/输出:
tensor([[0.0000, 0.0000, 1.2345, 0.0000],
[0.5432, 0.0000, 0.0000, 2.3456]])
Remarque : les opérations en place peuvent économiser de la mémoire, mais dans certains cas elles peuvent affecter le calcul du gradient. Aux premiers stades de l'entraînement ou lorsque les valeurs d'activation intermédiaires doivent être préservées, il est recommandé d'utiliser la valeur par défaut
inplace=False。
Exemple 3 : Utilisation dans les réseaux de neurones
Dans les réseaux de neurones convolutionnels, ReLU suit généralement la couche de convolution :
Exemple
import torch.nn as nn
# Définir un réseau de neurones convolutionnel simple
class SimpleCNN(nn.Module):
def __init__(self):
super(SimpleCNN, self).__init__()
# Couche de convolution : entrée 3 canaux, sortie 32 canaux, noyau 3x3
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, padding=1)
# activation ReLU
self.relu1 = nn.ReLU()
# Deuxième couche convolutionnelle
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.relu2 = nn.ReLU()
# Couche de pooling
self.pool = nn.MaxPool2d(2, 2)
def forward(self, x):
x = self.conv1(x)
x = self.relu1(x)
x = self.pool(x)
x = self.conv2(x)
x = self.relu2(x)
x = self.pool(x)
return x
# Créer le modèle
model = SimpleCNN()
# Afficher la structure du modèle
print("Structure du modèle:")
print(model)
# Tester la propagation avant
# Simuler une image couleur 3x32x32
input_image = torch.randn(1, 3, 32, 32)
output = model(input_image)
print("\nForme de l'entrée :", input_image.shape)
print("Forme de sortie :", output.shape)
Le résultat de sortie est:
模型结构: SimpleCNN( (conv1): Conv2d(3, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (relu1): ReLU() (conv2): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (relu2): ReLU() (pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) ) 输入形状: torch.Size([1, 3, 32, 32]) 输出形状: torch.Size([1, 64, 8, 8])
Exemple 4 : Utilisation de nn.functional.relu
PyTorch fournit également une interface fonctionnelletorch.nn.functional.relu:
Exemple
import torch.nn.functional as F
# Utilisation de l'interface fonctionnelle
input_tensor = torch.randn(1, 5, 5)
# Méthode 1 : Utilisation de l'interface fonctionnelle
output1 = F.relu(input_tensor)
# Méthode 2 : Utilisation de la version en place de la fonction
F.relu_(input_tensor)
print("Output:\n", output1)
Les différences entre les deux :
nn.ReLUEst une classe de module qui peut être utilisée dans les définitions de modèles et sauvegarde les paramètres.F.reluEst une interface fonctionnelle, couramment utilisée dans la méthode forward ou dans les cas où il n'y a pas de paramètres apprenables.F.relu_Est la fonction underscore de la version en place.
Comparaison avec d'autres fonctions d'activation
| Fonction d'activation | Formule | Caractéristiques | Scénarios applicables |
|---|---|---|---|
nn.ReLU |
max(0, x) | Calcul simple, activation parcimonieuse | Apprentissage profond général (choix par défaut) |
nn.LeakyReLU |
x > 0 ? x : 0.01x | Petit gradient sur l'axe négatif | Empêche les « neurones morts » | nn.GELU |
x * Φ(x) | Approximation lisse, choix par défaut pour Transformer | Transformer, BERT, etc. |
nn.Sigmoid |
1/(1+e^(-x)) | Sortie 0-1, saturation du gradient | Couche de sortie, classification binaire |
nn.Tanh |
(e^x - e^(-x))/(e^x + e^(-x)) | Sortie -1 à 1, centrée sur zéro | RNN, LSTM |
Questions fréquentes
Q1 : Pourquoi ReLU provoque-t-il le problème des « neurones morts » ?
Lorsque l'entrée reste négative, la sortie de ReLU est toujours 0, et le gradient est également 0, ce qui empêche ces neurones d'apprendre davantage.
Solutions :
- Utiliser
nn.LeakyReLUounn.ELUpour remplacer - Utiliser un taux d'apprentissage initial plus faible
- Adopter la normalisation par lots
Q2 : ReLU est-il adapté à la couche de sortie ?
Généralement non adapté. La couche de sortie utilise plus courammentSigmoid(pour la classification) ou la fonction identité (pour la régression), car la sortie de ReLU n'est pas bornée.
Cas d'utilisation
nn.ReLUC'est la fonction d'activation la plus couramment utilisée en apprentissage profond. Les principaux scénarios d'application incluent :
- Réseaux de neurones convolutifs: Introduire une non-linéarité après les couches de convolution ou les couches entièrement connectées.
- Perceptron multicouche: Comme fonction d'activation pour les couches cachées.
- Transformer: Comme fonction d'activation dans FFN (réseau feed-forward) (bien que GELU soit plus couramment utilisé aujourd'hui).
- Réseaux antagonistes génératifs: Comme fonction d'activation pour le générateur.
Astuce : Sauf exigences particulières, ReLU est le premier choix pour les fonctions d'activation des couches cachées lors de la conception de réseaux de neurones.
Autres extensions