Свёрточные нейронные сети

Глубокое обучение на PyTorch: средний уровень

Michal Oleszak

Machine Learning Engineer

Почему не использовать линейные слои?

Чёрный квадрат — изображение в оттенках серого размером 256×256.

Глубокое обучение на PyTorch: средний уровень

Почему не использовать линейные слои?

Полутоновое изображение 256×256 содержит около 65 тыс. значений пикселей.

Глубокое обучение на PyTorch: средний уровень

Почему не использовать линейные слои?

Линейный слой из 1000 нейронов обрабатывает 65 тыс. значений пикселей.

Глубокое обучение на PyTorch: средний уровень

Почему не использовать линейные слои?

Между изображением и слоем 65 млн связей.

Глубокое обучение на PyTorch: средний уровень

Почему не использовать линейные слои?

Для цветного RGB-изображения число связей достигает 200 млн.

Глубокое обучение на PyTorch: средний уровень

Почему не использовать линейные слои?

  • Линейные слои:
    • Медленное обучение
    • Переобучение
    • Не распознают пространственные паттерны
  • Лучшая альтернатива: свёрточные слои!

Изображение с котом в углу и нейроны, считывающие эту часть изображения

Глубокое обучение на PyTorch: средний уровень

Свёрточный слой

Фильтр размером 3×3 скользит по входу размером 5×5 и формирует карту признаков размером 3×3.

  • Фильтр(ы) параметров скользят по входу
  • В каждой позиции выполняется свёртка
  • Результирующая карта признаков:
    • Сохраняет пространственные паттерны входа
    • Требует меньше параметров, чем линейный слой
  • Один фильтр = одна карта признаков
  • К картам признаков применяются активации
  • Все карты признаков объединяются в выход
  • nn.Conv2d(3, 32, kernel_size=3)
Глубокое обучение на PyTorch: средний уровень

Свёртка

Две матрицы 3×3 перемножаются поэлементно, затем все числа результирующей матрицы суммируются.

  1. Вычислите скалярное произведение патча входа и фильтра
    • Верхний левый элемент: 2 × 1 = 2
  2. Просуммируйте результат
Глубокое обучение на PyTorch: средний уровень

Заполнение нулями

Изображение 4×4, окружённое рамкой из пикселей со значением ноль.

  • Добавьте рамку из нулей к входу свёрточного слоя
nn.Conv2d(
  3, 32, kernel_size=3, padding=1
)
  • Сохраняет пространственные размеры входного и выходного тензоров
  • Граничные пиксели обрабатываются наравне с остальными
Глубокое обучение на PyTorch: средний уровень

Макс-пулинг

Матрица 4×4, каждый квадрант 2×2 выделен своим цветом, после макс-пулинга превращается в матрицу 2×2.

  • Непересекающееся окно скользит по входу
  • В каждой позиции сохраняется максимальное значение
  • Применяется после свёрточных слоёв для уменьшения пространственных размеров
  • nn.MaxPool2d(kernel_size=2)
Глубокое обучение на PyTorch: средний уровень

Свёрточная нейронная сеть

class Net(nn.Module):
    def __init__(self, num_classes):
        super().__init__()

self.feature_extractor = nn.Sequential( nn.Conv2d(3, 32, kernel_size=3, padding=1), nn.ELU(), nn.MaxPool2d(kernel_size=2), nn.Conv2d(32, 64, kernel_size=3, padding=1), nn.ELU(), nn.MaxPool2d(kernel_size=2), nn.Flatten(), )
self.classifier = nn.Linear(64*16*16, num_classes)
def forward(self, x): x = self.feature_extractor(x) x = self.classifier(x) return x
  • feature_extractor: (свёртка, активация, пулинг), повторяется дважды и разворачивается в вектор
  • classifier: один линейный слой
  • forward(): пропускает входное изображение через экстрактор признаков и классификатор
Глубокое обучение на PyTorch: средний уровень

Размер выхода экстрактора признаков

self.feature_extractor = nn.Sequential(
  nn.Conv2d(3, 32, kernel_size=3, padding=1),
  nn.ELU(),
  nn.MaxPool2d(kernel_size=2),
  nn.Conv2d(32, 64, kernel_size=3, padding=1),
  nn.ELU(),
  nn.MaxPool2d(kernel_size=2),
  nn.Flatten(),
)
self.classifier = nn.Linear(64*16*16, num_classes)
`

Схема: входные изображения формы 3×64×64 проходят через свёрточный слой, слой пулинга, второй свёрточный слой и второй слой пулинга.

Глубокое обучение на PyTorch: средний уровень

Размер выхода экстрактора признаков

self.feature_extractor = nn.Sequential(
  nn.Conv2d(3, 32, kernel_size=3, padding=1),
  nn.ELU(),
  nn.MaxPool2d(kernel_size=2),
  nn.Conv2d(32, 64, kernel_size=3, padding=1),
  nn.ELU(),
  nn.MaxPool2d(kernel_size=2),
  nn.Flatten(),
)
self.classifier = nn.Linear(64*16*16, num_classes)
`

Схема: входные изображения формы 3×64×64 проходят через свёрточный слой, слой пулинга, второй свёрточный слой и второй слой пулинга.

Глубокое обучение на PyTorch: средний уровень

Размер выхода экстрактора признаков

self.feature_extractor = nn.Sequential(
  nn.Conv2d(3, 32, kernel_size=3, padding=1),
  nn.ELU(),
  nn.MaxPool2d(kernel_size=2),
  nn.Conv2d(32, 64, kernel_size=3, padding=1),
  nn.ELU(),
  nn.MaxPool2d(kernel_size=2),
  nn.Flatten(),
)
self.classifier = nn.Linear(64*16*16, num_classes)
`

Схема: входные изображения формы 3×64×64 проходят через свёрточный слой, слой пулинга, второй свёрточный слой и второй слой пулинга.

Глубокое обучение на PyTorch: средний уровень

Размер выхода экстрактора признаков

self.feature_extractor = nn.Sequential(
  nn.Conv2d(3, 32, kernel_size=3, padding=1),
  nn.ELU(),
  nn.MaxPool2d(kernel_size=2),
  nn.Conv2d(32, 64, kernel_size=3, padding=1),
  nn.ELU(),
  nn.MaxPool2d(kernel_size=2),
  nn.Flatten(),
)
self.classifier = nn.Linear(64*16*16, num_classes)
`

Схема: входные изображения формы 3×64×64 проходят через свёрточный слой, слой пулинга, второй свёрточный слой и второй слой пулинга.

Глубокое обучение на PyTorch: средний уровень

Размер выхода экстрактора признаков

self.feature_extractor = nn.Sequential(
  nn.Conv2d(3, 32, kernel_size=3, padding=1),
  nn.ELU(),
  nn.MaxPool2d(kernel_size=2),
  nn.Conv2d(32, 64, kernel_size=3, padding=1),
  nn.ELU(),
  nn.MaxPool2d(kernel_size=2),
  nn.Flatten(),
)
self.classifier = nn.Linear(64*16*16, num_classes)
`

Схема: входные изображения формы 3×64×64 проходят через свёрточный слой, слой пулинга, второй свёрточный слой и второй слой пулинга.

Глубокое обучение на PyTorch: средний уровень

Давайте потренируемся!

Глубокое обучение на PyTorch: средний уровень

Preparing Video For Download...