Ответ
Глубина сети (количество скрытых слоев) — это ключевой параметр, который определяет ее способность к обучению сложным иерархическим представлениям, но требует тщательного баланса.
Преимущества увеличения глубины:
- Иерархия признаков: Каждый последующий слой комбинирует признаки предыдущего, выявляя все более абстрактные закономерности. В CNN первый слой может детектировать края, второй — текстуры и простые формы, а более глубокие — целые объекты (глаза, уши, колеса).
- Выразительная мощность: Теорема универсальной аппроксимации гласит, что даже неглубокая сеть может аппроксимировать любую функцию, но глубокая сеть сделает это с экспоненциально меньшим числом параметров и более эффективно для многих реальных задач.
Проблемы и вызовы глубоких сетей:
- Исчезающие/взрывающиеся градиенты: При обратном распространении ошибки через множество слоев градиенты могут стать либо астрономически большими, либо невероятно малыми, что останавливает обучение. Решение: Использование функций активации с неисчезающими градиентами (ReLU, Leaky ReLU), техник инициализации весов (He, Xavier) и архитектур с skip-connections (ResNet).
- Переобучение: Глубокая сеть с большим числом параметров легко запоминает шум в тренировочных данных. Решение: Регуляризация (Dropout, L2), аугментация данных и использование больших датасетов.
- Вычислительная сложность и время обучения: Увеличение глубины напрямую влияет на потребление памяти и время обучения.
Пример сравнения архитектур в PyTorch:
import torch.nn as nn
# Мелкая сеть (3 линейных слоя)
class ShallowNet(nn.Module):
def __init__(self, input_size=784, num_classes=10):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_size, 256),
nn.ReLU(),
nn.Linear(256, num_classes)
)
def forward(self, x):
return self.layers(x)
# Глубокая сеть с Residual Connection (6 слоев, как в ResNet блоке)
class DeepResidualBlock(nn.Module):
def __init__(self, in_features, out_features):
super().__init__()
self.linear1 = nn.Linear(in_features, out_features)
self.relu = nn.ReLU()
self.linear2 = nn.Linear(out_features, out_features)
# Skip-connection: если размерности не совпадают, нужен проекционный слой
self.shortcut = nn.Linear(in_features, out_features) if in_features != out_features else nn.Identity()
def forward(self, x):
residual = self.shortcut(x)
out = self.linear1(x)
out = self.relu(out)
out = self.linear2(out)
out += residual # Ключевой элемент: добавление входа к выходу
out = self.relu(out)
return out
Вывод: Современные глубокие архитектуры (ResNet, Transformer, DenseNet) стали возможны именно благодаря методам, которые решают проблемы обучения глубоких сетей, таким как residual connections и layer normalization.