Функция torch.nn.BatchNorm2d в PyTorch

PyTorch torch.nn 参考手册Справочное руководство PyTorch torch.nn


torch.nn.BatchNorm2dЭто модуль в PyTorch для двумерной пакетной нормализации.

Пакетная нормализация ускоряет обучение и стабилизирует сходимость, нормализуя вход слоя, и является одной из наиболее часто используемых техник в современных глубоких нейронных сетях.

Определение функции

torch.nn.BatchNorm2d(num_features, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)

Описание параметров:

  • num_features(int): Количество входных каналов C.
  • eps(float): Значение, добавляемое к знаменателю для численной устойчивости. По умолчанию 1e-5.
  • momentum(float): Используется для вычисления скользящего среднего и дисперсии. По умолчанию 0.1.
  • affine(bool): Использовать ли обучаемые аффинные параметры (gamma и beta). По умолчанию True.
  • track_running_stats(bool): Отслеживать ли скользящую статистику. По умолчанию True.

Атрибуты:

  • weight(Tensor): Обучаемый параметр масштабирования gamma, форма (num_features,).
  • bias(Tensor): Обучаемый параметр сдвига beta, форма (num_features,).
  • running_mean(Tensor): Скользящее среднее, не обновляется во время обучения.
  • running_var(Tensor): Скользящая дисперсия, не обновляется во время обучения.

Математический принцип

Пакетная нормализация нормализует каждый канал независимо:

y = (x - E[x]) / sqrt(Var[x] + eps) * gamma + beta

Здесь gamma и beta — обучаемые параметры, которые позволяют сети восстановить свою выразительную способность.


Примеры использования

Пример 1: Базовое использование

Использование пакетной нормализации после свёрточного слоя:

Пример

import torch
import torch.nn as nn

# Создать слой пакетной нормализации: 32 канала
bn = nn.BatchNorm2d(num_features=32)

# Вывести параметры
print("гамма (weight):", bn.weight.shape)
print("бета (bias):", bn.bias.shape)
print("running_mean:", bn.running_mean.shape)
print("running_var:", bn.running_var.shape)

# Создать входные данные: batch=4, channels=32, height=16, width=16
input_tensor = torch.randn(4, 32, 16, 16)

# Прямой проход
output = bn(input_tensor)

print("nСреднее входа (по каналам):", input_tensor.mean(dim=(0, 2, 3))[:5].tolist())
print("Среднее выхода (по каналам):", output.mean(dim=(0, 2, 3))[:5].tolist())
print("nФорма входа:", input_tensor.shape)
print("Форма выхода:", output.shape)

Результат вывода:

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])

Во время обучения выход нормализуется к среднему 0 и дисперсии 1 (затем следует преобразование с gamma и beta).

Пример 2: режим обучения против режима оценки

Батч-нормализация ведёт себя по-разному при обучении и оценке:

Пример

import torch
import torch.nn as nn

bn = nn.BatchNorm2d(num_features=16)

# Режим обучения
bn.train()
print("Режим обучения - требуется градиент:", bn.weight.requires_grad)

# Имитация обучения
for _ in range(10):
    x = torch.randn(8, 16, 8, 8)
    output = bn(x)

print("Первые 5 running_mean после обучения:", bn.running_mean[:5].tolist())

# Режим оценки
bn.eval()
print("nРежим оценки - требуется градиент:", bn.weight.requires_grad)

# Использовать скользящие статистики во время оценки
x = torch.randn(4, 16, 8, 8)
output = bn(x)
print("Форма выходных данных во время оценки:", output.shape)

Пример 3: Полный пример CNN

Типичная структура CNN с пакетной нормализацией:

Пример

import torch
import torch.nn as nn

class BNConvNet(nn.Module):
    def __init__(self, num_classes=10):
        super(BNConvNet, self).__init__()
        # Свёртка + пакетная нормализация + активация + пулинг
        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
        )
        # Глобальное усредняющее объединение
        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("Размер входных данных:", input_image.shape)
print("Форма выхода:", output.shape)

# Вывод параметров первого BN-слоя
print("Гамма первого BN-слоя:", model.block1[1].weight[:5].tolist())
print("Бета первого BN-слоя:", model.block1[1].bias[:5].tolist())

Пример 4: Без использования affine-параметров

Отключить обучаемые параметры:

Пример

import torch
import torch.nn as nn

# Пакетная нормализация без обучаемых параметров
bn_no_affine = nn.BatchNorm2d(16, affine=False)

print("Есть вес:", bn_no_affine.weight is not Отсутствует)
print("Есть смещение:", bn_no_affine.bias is not Отсутствует)

# Он всё ещё выполняет нормализацию
x = torch.randn(4, 16, 8, 8)
output = bn_no_affine(x)
print("nРазмер выхода:", output.shape)

Часто задаваемые вопросы

Вопрос 1: Следует ли размещать пакетную нормализацию до или после ReLU?

Оба подхода эффективны. В оригинальной статье она размещается после свёртки и перед активацией; на практике её также часто размещают после активации.

Вопрос 2: Что делать, если она плохо работает с маленькими размерами батча?

  • ИспользуйтеGroupNormвместо
  • ИспользуйтеLayerNorm
  • Увеличьте размер батча
  • Настройте параметр момента

Вопрос 3: Почему нужно переключаться в режим eval при оценке?

Во время обучения используются статистики батча; при оценке используются скользящие статистики. Если забыть переключиться, это приведёт к несогласованным выходным данным.


Сценарии использования

nn.BatchNorm2dОсновные сценарии применения включают:

  • Ускорение обучения: позволяет использовать более высокую скорость обучения
  • Стабилизация сходимости: уменьшает внутренний ковариационный сдвиг
  • Регуляризация: обеспечивает небольшой эффект регуляризации
  • Классификация изображений: используется почти во всех современных CNN

Примечание: пакетная нормализация требует достаточно большого размера пакета во время обучения; маленькие пакеты могут привести к нестабильной статистике.


PyTorch torch.nn 参考手册Справочное руководство PyTorch torch.nn

Другие расширения