Convolution
Свёртка — это перемещение небольшого ядра весов по входным данным для получения карты признаков; она лежит в основе CNN. Разбираем шаг свёртки, дополнение и варианты.
Свёртка — это операция, при которой небольшую сетку весов, называемую ядром или фильтром, перемещают по входным данным и в каждой позиции вычисляют взвешенную сумму. В компьютерном зрении (CV) входными данными служит изображение или набор карт признаков, а каждое ядро формирует выходную карту, значения которой велики там, где встречается соответствующий шаблон: вертикальный край, участок текстуры или, на более глубоких уровнях сети, часть колеса или лица. Ядра, спроектированные вручную, давно используются в обработке изображений для размытия, повышения резкости и обнаружения границ. В свёрточной нейронной сети (CNN) значения ядер — это веса модели, которые изучаются во время обучения, поэтому сеть сама находит свои детекторы признаков.
Как работает свёртка#
В каждой позиции ядро накладывается на участок входных данных, каждый вес ядра умножается на соответствующее значение входных данных, а произведения суммируются с добавлением смещения, образуя одно выходное значение. Перемещение ядра по всей высоте и ширине формирует двумерную выходную карту. Реальные входные данные имеют несколько каналов, например красный, зелёный и синий каналы изображения, поэтому каждое ядро охватывает все входные каналы: ядро 3×3 для входных данных с 64 каналами содержит 3 × 3 × 64 = 576 весов и по-прежнему формирует один выходной канал. Свёрточный слой применяет множество таких ядер, а их количество задаёт число выходных каналов. Поэтому слой, преобразующий 64 канала в 128 с помощью ядер 3×3, содержит 3 × 3 × 64 × 128 = 73,728 весов.
Одно и то же ядро повторно используется в каждой позиции. Поэтому свёрточным слоям нужно намного меньше параметров, чем полносвязным, а шаблон, изученный в одном углу изображения, распознаётся и в остальных местах. При сдвиге входных данных выход сдвигается на такое же расстояние — это свойство называется эквивариантностью относительно сдвига. Каждое выходное значение зависит лишь от небольшой окрестности входных данных, а последовательное наложение слоёв расширяет рецептивное поле, которое суммирует значение глубокого слоя: от нескольких пикселей до большей части изображения.
На деле библиотеки глубокого обучения вычисляют взаимную корреляцию: при математической свёртке ядро переворачивается перед перемещением, а функция Conv2d в PyTorch этого не делает. Поскольку ядро обучается, сеть просто изучает перевёрнутые веса, и на практике эти операции взаимозаменяемы. Библиотеки GPU, например cuDNN, обычно преобразуют свёртку в большое матричное умножение или используют алгоритмы Винограда либо на основе FFT, вычисляющие тот же результат быстрее, чем при буквальном перемещении ядра.
Шаг, паддинг, дилатация и группы#
Форму выходных данных свёртки и вычислительные затраты на её выполнение определяют четыре гиперпараметра:
- Шаг: расстояние между позициями ядра. При шаге 2 пропускается каждая вторая позиция, а высота и ширина выходных данных уменьшаются вдвое. Так многие современные CNN уменьшают пространственное разрешение.
- Паддинг: дополнительные значения, обычно нули, добавляемые по краям входных данных. Паддинг 1 сохраняет размер выходных данных свёртки 3×3 таким же, как у входных данных, при шаге 1.
- Дилатация: увеличивает расстояние между элементами ядра, поэтому ядро 3×3 с дилатацией 2 охватывает область 5×5, сохраняя те же девять весов. Так рецептивное поле увеличивается без дополнительных затрат.
- Группы: разделяют каналы на независимые группы. Если выделить по одной группе на каждый канал, глубинная свёртка фильтрует каждый канал отдельно, а следующая поточечная свёртка 1×1 смешивает каналы. Эта пара называется глубинно-разделимой свёрткой; её популяризовали MobileNets для мобильных устройств.
Для входного размера n, размера ядра k, паддинга p, шага s и дилатации d размер выходных данных вычисляется по формуле ⌊(n + 2p − d(k − 1) − 1) / s⌋ + 1. Приведённый ниже фрагмент кода применяет четыре слоя, каждый из которых преобразует карту признаков с 64 каналами размером 80×80 в 128 каналов:
import torch
from torch import nn
x = torch.randn(1, 64, 80, 80) # a 64-channel, 80x80 feature map
# Four ways to map 64 input channels to 128 output channels
layers = {
"standard 3x3": nn.Conv2d(64, 128, kernel_size=3, padding=1, bias=False),
"stride 2": nn.Conv2d(64, 128, kernel_size=3, stride=2, padding=1, bias=False),
"dilation 2": nn.Conv2d(64, 128, kernel_size=3, padding=2, dilation=2, bias=False),
"depthwise separable": nn.Sequential(
nn.Conv2d(64, 64, kernel_size=3, padding=1, groups=64, bias=False), # one 3x3 filter per channel
nn.Conv2d(64, 128, kernel_size=1, bias=False), # 1x1 convolution mixes channels
),
}
for name, layer in layers.items():
params = sum(p.numel() for p in layer.parameters())
print(f"{name}: output {tuple(layer(x).shape)}, {params:,} weights")Стандартный слой выдаёт (1, 128, 80, 80) и содержит 73,728 весов. Шаг 2 уменьшает выходные данные вдвое — до (1, 128, 40, 40), сохраняя то же количество весов, а дилатация 2 сохраняет размер 80×80 и 73,728 весов, при этом каждое выходное значение охватывает область 5×5. Пара глубинно-разделимых свёрток формирует те же выходные данные (1, 128, 80, 80), используя всего 8,768 весов, то есть примерно в 8,4 раза меньше. В YOLO26 используются оба подхода: пять свёрток 3×3 с шагом 2 уменьшают изображение 640×640 до сетки 20×20 на самой глубокой карте признаков базовой сети, а классификационная ветвь головы детектора объединяет глубинную свёртку 3×3 и поточечную 1×1, чтобы сократить вычисления.
Свёртки в других измерениях#
- Свёртка 1D: перемещается вдоль одной оси и применяется к звуковым волнам, сигналам датчиков и временным рядам.
- Свёртка 3D: добавляет ось глубины или времени и применяется к видеоклипам и объёмным снимкам, например КТ и МРТ, в анализе медицинских изображений.
- Транспонированная свёртка: распределяет каждое входное значение по большей выходной области, увеличивая карты признаков в моделях сегментации, например U-Net. Она восстанавливает пространственный размер, уменьшенный свёрткой с шагом, используя собственные обучаемые веса.
Свёртка и связанные операции#
- Полносвязный слой: соединяет каждый вход с каждым выходом с помощью собственного веса. Свёртка — это полносвязный слой, ограниченный локальными окрестностями и использующий общие для разных позиций веса.
- Пулинг: перемещает окно, как при свёртке, но применяет фиксированное правило, например выбирает максимум, без обучаемых весов.
- Самовнимание: вычисляет зависящие от данных веса между каждой парой позиций, поэтому связывает удалённые части изображения уже в одном слое. Свёртка применяет одно и то же фиксированное ядро повсюду и видит только локальное окно, поэтому её вычислительная сложность растёт линейно с количеством пикселей.
- Фильтрация изображений: классические фильтры, например гауссово размытие и детектор границ Собеля, — это свёртки с фиксированными ядрами, спроектированными вручную. Функция
filter2Dв OpenCV также вычисляет корреляцию, как и библиотеки глубокого обучения; переворот ядра превращает её в настоящую свёртку.










