Fonction torch.nn.ReLU de PyTorch

PyTorch torch.nn 参考手册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
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
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éfautinplace=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
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
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 :

  • Utilisernn.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.


PyTorch torch.nn 参考手册Manuel de référence torch.nn de PyTorch

Autres extensions