Класс InstanceNorm2d
Класс InstanceNorm2d применяет нормализацию по экземплярам для четырёхмерных входных данных (мини-пакет, каналы, высота, ширина). Нормализация выполняется для каждого экземпляра и каждого канала отдельно, используя среднее и дисперсию, вычисленные по пространственным размерностям (высота и ширина). Первым параметром конструктор принимает количество входных каналов num_features. Также можно задать параметры eps для численной стабильности, momentum для вычисления скользящего среднего и аффинные параметры affine. В отличие от BatchNorm2d, этот слой не зависит от размера батча и часто используется в задачах генерации изображений.
Синтаксис
torch.nn.InstanceNorm2d(
num_features,
eps=1e-05,
momentum=0.1,
affine=False,
track_running_stats=False
)
Параметры слоя
Конструктор InstanceNorm2d имеет следующие параметры:
• num_features (int) – количество каналов на входе.
• eps (float) – значение, добавляемое к дисперсии для численной стабильности, по умолчанию 1e-05.
• momentum (float) – коэффициент для обновления скользящего среднего и дисперсии, по умолчанию 0.1.
• affine (bool) – если True, слой имеет обучаемые параметры scale и shift, по умолчанию False.
• track_running_stats (bool) – если True, отслеживаются скользящие средние, по умолчанию False.
Пример использования в сети
Создадим простой свёрточный слой с нормализацией по экземплярам:
import torch
import torch.nn as nn
# Определяем блок с InstanceNorm2d
class ConvBlock(nn.Module):
def __init__(self, in_channels, out_channels):
super().__init__()
self.conv = nn.Conv2d(in_channels, out_channels, 3, padding=1)
self.norm = nn.InstanceNorm2d(out_channels, affine=True)
self.act = nn.ReLU()
def forward(self, x):
x = self.conv(x)
x = self.norm(x)
x = self.act(x)
return x
# Создаём экземпляр блока и тестовый тензор
torch.manual_seed(0)
block = ConvBlock(3, 16)
t = torch.randn(2, 3, 32, 32) # [batch, channels, height, width]
res = block(t)
print(res.shape)
Результат выполнения кода:
torch.Size([2, 16, 32, 32])
Пример
Давайте сравним выходы слоя с аффинным преобразованием и без него:
import torch
import torch.nn as nn
torch.manual_seed(0)
# Слой без аффинных параметров
norm1 = nn.InstanceNorm2d(3, affine=False)
# Слой с аффинными параметрами
norm2 = nn.InstanceNorm2d(3, affine=True)
t = torch.randn(1, 3, 4, 4)
# Применяем нормализацию
out1 = norm1(t)
out2 = norm2(t)
# Выводим статистику
print("Mean without affine:", out1.mean().item())
print("Std without affine:", out1.std().item())
print("Mean with affine:", out2.mean().item())
print("Std with affine:", out2.std().item())
Результат выполнения кода:
Mean without affine: -1.4148521460275254e-08
Std without affine: 1.000000238418579
Mean with affine: 5.160839316658199e-09
Std with affine: 1.000000238418579
Пример
Посмотрим, как работает отслеживание статистики во время обучения:
import torch
import torch.nn as nn
torch.manual_seed(0)
# Слой с отслеживанием статистики
norm = nn.InstanceNorm2d(3, affine=True, track_running_stats=True)
t = torch.randn(2, 3, 8, 8)
# В режиме обучения статистика обновляется
norm.train()
out_train = norm(t)
# В режиме оценки используются накопленные статистики
norm.eval()
out_eval = norm(t)
print("Running mean shape:", norm.running_mean.shape)
print("Running var shape:", norm.running_var.shape)
print("Train output mean:", out_train.mean().item())
print("Eval output mean:", out_eval.mean().item())
Результат выполнения кода:
Running mean shape: torch.Size([3])
Running var shape: torch.Size([3])
Train output mean: 1.080369640417055e-10
Eval output mean: 3.826838309797482e-08
Смотрите также
-
слой
InstanceNorm1d,
который выполняет нормализацию для трёхмерных данных -
слой
BatchNorm2d,
который выполняет нормализацию по батчу для изображений -
слой
LayerNorm,
который выполняет нормализацию по признаковому пространству -
слой
GroupNorm,
который выполняет нормализацию по группам каналов