Fonction torch.nn.BatchNorm2d de PyTorch
Manuel de référence torch.nn de PyTorch
torch.nn.BatchNorm2dIl s'agit d'un module de PyTorch pour la normalisation par lots en deux dimensions.
La normalisation par lots accélère l'entraînement et stabilise la convergence en normalisant l'entrée d'une couche, et est l'une des techniques les plus couramment utilisées dans les réseaux de neurones profonds modernes.
Définition de fonction
torch.nn.BatchNorm2d(num_features, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
Description des paramètres :
num_features(int) : Nombre de canaux d'entrée C.eps(float) : Valeur ajoutée au dénominateur pour la stabilité numérique. La valeur par défaut est 1e-5.momentum(float) : Utilisé pour calculer la moyenne et la variance glissantes. La valeur par défaut est 0.1.affine(bool) : Indique s'il faut utiliser des paramètres affines apprenables (gamma et beta). La valeur par défaut est True.track_running_stats(bool) : Indique s'il faut suivre les statistiques glissantes. La valeur par défaut est True.
Attributs :
weight(Tensor) : Paramètre d'échelle apprenable gamma, de forme (num_features,).bias(Tensor) : Paramètre de décalage apprenable beta, de forme (num_features,).running_mean(Tensor) : Moyenne glissante, non mise à jour pendant l'entraînement.running_var(Tensor) : Variance glissante, non mise à jour pendant l'entraînement.
Principe mathématique
La normalisation par lots normalise chaque canal indépendamment :
y = (x - E[x]) / sqrt(Var[x] + eps) * gamma + beta
Ici, gamma et beta sont des paramètres apprenables qui permettent au réseau de restaurer sa capacité d'expression.
Exemples d'utilisation
Exemple 1 : Utilisation de base
Utilisation de la normalisation par lots après une couche de convolution :
Exemple
import torch.nn as nn
# Créer une couche de normalisation par lots : 32 canaux
bn = nn.BatchNorm2d(num_features=32)
# Afficher les paramètres
print("gamma (poids) :", bn.weight.shape)
print("beta (biais) :", bn.bias.shape)
print("running_mean:", bn.running_mean.shape)
print("running_var:", bn.running_var.shape)
# Créer l'entrée : batch=4, canaux=32, hauteur=16, largeur=16
input_tensor = torch.randn(4, 32, 16, 16)
# Passe avant
output = bn(input_tensor)
print("nMoyenne d'entrée (par canal) :", input_tensor.mean(dim=(0, 2, 3))[:5].tolist())
print("Moyenne de sortie (par canal) :", output.mean(dim=(0, 2, 3))[:5].tolist())
print("nForme de l'entrée :", input_tensor.shape)
print("Forme de sortie :", output.shape)
Le résultat de sortie est:
gamma (weight): torch.Size([32]) beta (bias): torch.Size([32]) running_mean: torch.Size([32]) running_var: torch.Size([32]) 输入均值 (按通道): tensor([ 0.0234, 0.0456, -0.0123, -0.0345, 0.0567]) 输出均值 (按通道): tensor([ 0., 0., 0., 0., 0.]) 输入形状: torch.Size([4, 32, 16, 16]) 输出形状: torch.Size([4, 32, 16, 16])
Pendant l'entraînement, la sortie est normalisée pour avoir une moyenne de 0 et une variance de 1 (suivie d'une transformation gamma et beta).
Exemple 2 : mode entraînement vs mode évaluation
La normalisation par lots se comporte différemment pendant l'entraînement et l'évaluation :
Exemple
import torch.nn as nn
bn = nn.BatchNorm2d(num_features=16)
# Mode entraînement
bn.train()
print("Mode entraînement - nécessite un gradient :", bn.weight.requires_grad)
# Simuler l'entraînement
for _ in range(10):
x = torch.randn(8, 16, 8, 8)
output = bn(x)
print("5 premiers running_mean après entraînement :", bn.running_mean[:5].tolist())
# Mode évaluation
bn.eval()
print("nMode évaluation - nécessite un gradient :", bn.weight.requires_grad)
# Utiliser les statistiques courantes lors de l’évaluation
x = torch.randn(4, 16, 8, 8)
output = bn(x)
print("Forme de la sortie lors de l’évaluation :", output.shape)
Exemple 3 : Exemple complet de CNN
Structure typique d’un CNN avec normalisation par lots :
Exemple
import torch.nn as nn
class BNConvNet(nn.Module):
def __init__(self, num_classes=10):
super(BNConvNet, self).__init__()
# Convolution + normalisation par lots + activation + pooling
self.block1 = nn.Sequential(
nn.Conv2d(3, 32, kernel_size=3, padding=1),
nn.BatchNorm2d(32),
nn.ReLU(),
nn.MaxPool2d(2, 2) # 32 -> 16
)
self.block2 = nn.Sequential(
nn.Conv2d(32, 64, kernel_size=3, padding=1),
nn.BatchNorm2d(64),
nn.ReLU(),
nn.MaxPool2d(2, 2) # 16 -> 8
)
# Pooling moyen global
self.gap = nn.AdaptiveAvgPool2d(1)
self.classifier = nn.Linear(64, num_classes)
def forward(self, x):
x = self.block1(x)
x = self.block2(x)
x = self.gap(x)
x = x.view(x.size(0), -1)
x = self.classifier(x)
return x
model = BNConvNet()
input_image = torch.randn(2, 3, 32, 32)
output = model(input_image)
print("Forme de l'entrée :", input_image.shape)
print("Forme de sortie :", output.shape)
# Afficher les paramètres de la première couche BN
print("Gamma de la première couche BN :", model.block1[1].weight[:5].tolist())
print("Bêta de la première couche BN :", model.block1[1].bias[:5].tolist())
Exemple 4 : Ne pas utiliser les paramètres affines
Désactiver les paramètres apprenables :
Exemple
import torch.nn as nn
# Normalisation par lots sans paramètres apprenables
bn_no_affine = nn.BatchNorm2d(16, affine=False)
print("A un poids :", bn_no_affine.weight is not Aucune)
print("A un biais :", bn_no_affine.bias is not Aucune)
# Il effectue toujours la normalisation
x = torch.randn(4, 16, 8, 8)
output = bn_no_affine(x)
print("nForme de sortie :", output.shape)
Questions courantes
Q1 : La normalisation par lots doit-elle être placée avant ou après ReLU ?
Les deux approches sont efficaces. L'article original le place après la convolution et avant l'activation ; en pratique, il est aussi souvent placé après l'activation.
Q2 : Que faire lorsqu'il ne fonctionne pas bien avec de petites tailles de lot ?
- Utiliser
GroupNormau lieu de - Utiliser
LayerNorm - Augmenter la taille du lot
- Ajuster le paramètre de momentum
Q3 : Pourquoi passer en mode eval lors de l'évaluation ?
Pendant l'entraînement, les statistiques de lot sont utilisées ; pendant l'évaluation, les statistiques courantes sont utilisées. Oublier de basculer entraînera des sorties incohérentes.
Cas d'utilisation
nn.BatchNorm2dLes principaux scénarios d'application incluent :
- Accélérer l'entraînement: Permet d'utiliser un taux d'apprentissage plus élevé
- Stabiliser la convergence: Réduit le décalage interne des covariables
- Régularisation: Fournit un léger effet de régularisation
- Classification d'images: Utilisée par presque tous les CNN modernes
Remarque : la normalisation par lots nécessite une taille de lot suffisante pendant l'entraînement ; les petits lots peuvent conduire à des statistiques instables.
Autres extensions