Название | Нейросети: создание и оптимизация будущего |
---|---|
Автор произведения | Джеймс Девис |
Жанр | |
Серия | |
Издательство | |
Год выпуска | 2025 |
isbn |
x = self.bn1(x) # Применение Batch Normalization
x = torch.relu(x) # Активация ReLU
x = self.layer2(x)
x = self.bn2(x) # Применение Batch Normalization
x = torch.relu(x) # Активация ReLU
x = self.layer3(x) # Применение финального линейного слоя
return x
# Пример данных и оптимизации
model = SimpleNet()
criterion = nn.CrossEntropyLoss() # Функция потерь для классификации
optimizer = optim.Adam(model.parameters(), lr=0.001) # Оптимизатор Adam
# Пример одного шага обучения
inputs = torch.randn(64, 784) # Входной батч из 64 изображений размером 28x28 (784 = 28*28)
labels = torch.randint(0, 10, (64,)) # Случайные метки классов для примера
# Обнуление градиентов
optimizer.zero_grad()
# Прямой проход
outputs = model(inputs)
loss = criterion(outputs, labels)
# Обратное распространение и обновление весов
loss.backward()
optimizer.step()
print("Значение функции потерь:", loss.item())
```
Объяснение работы Batch Normalization в коде
– `nn.BatchNorm1d(256)` и `nn.BatchNorm1d(128)` добавлены после каждого линейного слоя. Они нормализуют выходы, уменьшая разброс значений и стабилизируя обратное распространение.
– 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