– Batch Normalization вычитает среднее и делит на стандартное отклонение для каждого батча, обеспечивая равномерное распределение значений. После этого применяются параметры смещения и масштабирования, которые обучаются вместе с остальными параметрами сети.

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

Инициализация весов с использованием методов Xavier и He помогает улучшить процесс обучения нейронных сетей, особенно глубоких, за счет предотвращения проблем с затуханием или взрывом градиентов. В PyTorch это можно сделать с помощью функций из модуля `torch.nn.init`.

– Инициализация Xavier (также известная как Glorot) работает лучше всего с активациями, которые сохраняют значения в пределах (-1, 1), как, например, сигмоид или гиперболический тангенс.

– Инициализация He (также известная как Kaiming) лучше подходит для активаций ReLU и производных от нее функций, так как она помогает компенсировать тенденцию ReLU обнулять градиенты.

Ниже приведен пример нейронной сети, где используется оба подхода к инициализации:

```python

import torch

import torch.nn as nn

import torch.optim as optim

# Определяем класс нейронной сети

class SimpleNet(nn.Module):

def __init__(self):

super(SimpleNet, self).__init__()

# Определяем слои сети

self.layer1 = nn.Linear(784, 256) # Первый полносвязный слой

self.layer2 = nn.Linear(256, 128) # Второй полносвязный слой

self.layer3 = nn.Linear(128, 10) # Выходной слой (например, для 10 классов)

# Применяем инициализацию весов

self._initialize_weights()

def _initialize_weights(self):

# Инициализация первого и второго слоя методом He для ReLU активации

nn.init.kaiming_normal_(self.layer1.weight, nonlinearity='relu')

nn.init.kaiming_normal_(self.layer2.weight, nonlinearity='relu')

# Инициализация выходного слоя методом Xavier, подходящим для softmax или других линейных активаций

nn.init.xavier_normal_(self.layer3.weight)

def forward(self, x):

x = torch.relu(self.layer1(x)) # Применение ReLU после первого слоя

x = torch.relu(self.layer2(x)) # Применение ReLU после второго слоя

x = self.layer3(x) # Прямой выход для классификации (например, softmax на последнем слое)

return x

# Пример данных и оптимизации

model = SimpleNet()

criterion = nn.CrossEntropyLoss() # Функция потерь для классификации

optimizer = optim.Adam(model.parameters(), lr=0.001) # Оптимизатор Adam

# Пример одного шага обучения

inputs = torch.randn(64, 784) # Входной батч из 64 изображений размером 28x28

labels = torch.randint(0, 10, (64,)) # Случайные метки классов для примера

# Обнуление градиентов

optimizer.zero_grad()

# Прямой проход

outputs = model(inputs)

loss = criterion(outputs, labels)

# Обратное распространение и обновление весов

loss.backward()

optimizer.step()

print("Значение функции потерь:", loss.item())

```

Объяснение кода:

1. Метод He (`nn.init.kaiming_normal_`): Применяется к `layer1` и `layer2`, которые используют активацию ReLU. Эта инициализация выбирает веса из нормального распределения, масштабируя их так, чтобы среднее значение градиентов оставалось примерно постоянным по всей глубине сети.

2. Метод Xavier (`nn.init.xavier_normal_`): Применяется к `layer3`, который может завершать сеть и чаще всего используется с линейной активацией или softmax. Эта инициализация помогает сохранить градиенты в пределах разумных значений для функций с симметричным распределением вокруг нуля, таких как сигмоид или tanh.

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