Архитектура VGG: как устроена сеть из блоков 3x3

Архитектура VGG (Visual Geometry Group, Оксфорд, 2014) стала каноническим примером того, как из предельно простых элементов собирается глубокая свёрточная сеть. Вся идея - заменить большие фильтры на стопку маленьких свёрток и наращивать глубину. На ImageNet-2014 VGG взяла второе место в классификации, но именно её прямолинейность сделала сеть стандартным учебным примером и удобным backbone. Ниже разберём, как считать параметры и размеры карт признаков, чтобы вы могли воспроизвести расчёт для любого слоя.
Из чего собрана сеть VGG
Архитектура VGG - это последовательность одинаковых строительных блоков. Каждый блок состоит из нескольких свёрточных слоёв с шагом 1 и паддингом 1 (поэтому пространственный размер внутри блока не меняется), за которыми идёт max-pooling со страйдом 2, уменьшающий сторону карты вдвое. После пяти таких блоков идут три полносвязных слоя и softmax на 1000 классов ImageNet.
Принципиальное решение авторов - отказаться от крупных рецептивных ядер или , которые использовали в AlexNet, в пользу стопки . Это и отличает VGG от более ранней архитектуры свёрточной сети CNN, где размеры фильтров подбирались разнородно.

Почему именно свёртки 3x3
Два последовательных слоя дают такое же рецептивное поле, как один слой , а три слоя - как один . Но выигрыш двойной. Во-первых, между свёртками вставляется нелинейность (ReLU), поэтому стопка из трёх - это более выразительная функция, чем одна с единственной нелинейностью.
Во-вторых, это экономия параметров. Для входных и выходных каналов один слой требует весов, а три слоя - только . Формально число весов одного свёрточного слоя:
где - размер ядра, и - число входных и выходных каналов, а - смещение (bias) на каждый фильтр. Например, слой с , 64 входными и 64 выходными каналами содержит параметров.
Размер карты признаков на выходе слоя считается как floor((W - k + 2p)/s) + 1. Для VGG с k=3, p=1, s=1 он сохраняется; пулинг 2x2 со страйдом 2 делит сторону пополам.
Как меняется карта признаков по слоям
Чтобы понимать архитектуру VGG не на словах, а в числах, полезно проследить, что происходит с тензором от входа к выходу. Изображение приходит размером . Внутри каждого блока свёртки с паддингом 1 не трогают пространственный размер - меняется только глубина (число каналов), которую задают фильтры. А вот max-pooling в конце блока уменьшает сторону вдвое.
Получается такая цепочка пространственных размеров после каждого блока: . Число каналов растёт зеркально: . Закономерность не случайна - по мере того как карта становится мельче, сеть может позволить себе больше каналов, удерживая вычислительную стоимость блока примерно постоянной. На выходе пятого блока остаётся тензор , который и разворачивается в вектор для полносвязной части.
Эта инвариантность размера внутри блока - следствие выбора для ядра . Если бы паддинг был нулевым, каждая свёртка съедала бы по два пикселя со стороны, и после трёх слоёв блока карта заметно усыхала бы ещё до пулинга. Симметричный паддинг 1 - это то, что делает блоки VGG взаимозаменяемыми кирпичиками.
Конфигурации A-E из оригинальной статьи
В работе Симоняна и Зиссермана VGG описана не как одна сеть, а как семейство конфигураций от A до E, отличающихся глубиной. Конфигурация A - самая мелкая (11 весовых слоёв, VGG-11), E - самая глубокая (19 слоёв, VGG-19). Между ними A-LRN (с локальной нормализацией откликов, которая в итоге не помогла), B (13 слоёв) и D (16 слоёв, та самая VGG-16).
Авторы обучали сети инкрементально: сначала неглубокую A со случайной инициализацией, а более глубокие - уже подхватывая часть весов от обученной A. Это сглаживало проблему плохой сходимости глубоких сетей до появления продуманных схем инициализации. Промышленным стандартом стали именно конфигурации D и E как лучший компромисс точности и стоимости.
VGG-16 и VGG-19: в чём разница
Цифра в названии - это число обучаемых слоёв с весами (свёрточные плюс полносвязные), пулинг не считается. В VGG-16 их шестнадцать: 13 свёрточных и 3 полносвязных. В VGG-19 добавлены ещё три свёртки (по одной в трёх последних блоках), итого 16 свёрточных и 3 полносвязных.
Разбивка VGG-16 по блокам выглядит так: блок 1 - два слоя по 64 канала, блок 2 - два по 128, блок 3 - три по 256, блоки 4 и 5 - по три слоя по 512 каналов. Затем два полносвязных слоя по 4096 нейронов и выходной на 1000 классов.

Где «живут» параметры
Главный сюрприз для тех, кто впервые считает VGG: подавляющая часть из примерно 138 миллионов параметров VGG-16 сосредоточена не в свёртках, а в полносвязных слоях. Первый полносвязный слой принимает развёрнутую карту значений и связывает её с 4096 нейронами:
Это около 102 миллионов весов - больше двух третей всей сети. Все тринадцать свёрточных слоёв вместе содержат лишь порядка 14,7 миллиона параметров. Именно поэтому в современных backbone полносвязную «голову» часто заменяют global average pooling - это резко уменьшает размер модели.
VGG как backbone и transfer learning
Несмотря на тяжесть, свёрточная часть VGG (без полносвязной головы) долго оставалась рабочим feature extractor. Её активации с промежуточных слоёв используют в задачах сегментации, детекции, а особенно - в переносе стиля (style transfer), где perceptual loss считается именно по картам признаков VGG. В transfer learning веса предобученной на ImageNet сети замораживают, а обучают только новый классификатор под свою задачу.
Причина, по которой признаки VGG так хорошо переносятся, - в иерархичности. Ранние блоки реагируют на простые градиенты и углы, средние собирают из них текстуры и части объектов, а глубокие кодируют уже целостные паттерны. Эта лестница абстракции универсальна: распознаёте вы кошек или дефекты на снимках, низкоуровневые признаки нужны те же. Поэтому достаточно взять предобученную свёрточную часть, заменить голову и дообучить её на небольшой выборке - это и есть основной сценарий fine-tuning, который экономит и данные, и время вычислений.
На практике VGG берут как backbone, когда важна понятная, легко интерпретируемая иерархия признаков, а не минимальный размер модели. В perceptual loss свёрточный слой определённой глубины буквально задаёт, на каком уровне абстракции сравниваются изображения: мелкие слои дают пиксельную близость, глубокие - семантическую.
VGG не имеет skip-соединений, поэтому глубже 19 слоёв обучается плохо из-за затухающих градиентов. Эту проблему решили остаточные блоки в ResNet - если задача требует большой глубины, VGG уже не лучший выбор.
Частые ошибки
- Считать число в названии за общее количество слоёв. В VGG-16 шестнадцать - это только слои с весами; пять pooling-слоёв и ReLU не входят в счёт.
- Забывать про bias при подсчёте параметров. На каждый из фильтров приходится одно смещение - для точного числа его нужно прибавлять.
- Путать паддинг и страйд. В свёртках VGG паддинг 1 сохраняет размер, а уменьшение вдвое даёт только pooling - а не сама свёртка.
- Думать, что параметры в основном в свёртках. Наоборот: ~73% весов VGG-16 - в полносвязных слоях, и именно они раздувают модель до полугигабайта.
- Применять VGG там, где нужна глубина 50+ слоёв. Без skip-соединений она не дотягивает; для глубоких задач берут ResNet или EfficientNet.
FAQ
Чем VGG отличается от AlexNet? VGG глубже (16-19 слоёв против 8) и использует только маленькие фильтры , тогда как AlexNet применял крупные ядра и в первых слоях. За счёт стопок VGG достигает того же рецептивного поля при меньшем числе параметров на слой и большем числе нелинейностей.
Сколько параметров в VGG-16? Около 138 миллионов. Из них примерно 123 миллиона приходятся на три полносвязных слоя (особенно на первый - около 102 млн), и лишь около 14,7 миллиона - на все свёрточные слои.
Почему VGG считается устаревшей? Из-за отсутствия остаточных связей сеть плохо масштабируется в глубину и очень тяжёлая по памяти. ResNet при сопоставимой или большей точности использует на порядок меньше параметров, поэтому VGG сегодня применяют в основном как feature extractor и в учебных целях.
Коротко
Архитектура VGG строится из однотипных блоков свёрток с паддингом 1 и max-pooling : глубина растёт, а правила просты. Стопка маленьких ядер заменяет крупные фильтры с экономией весов и большим числом нелинейностей. Версии VGG-16 и VGG-19 различаются числом весовых слоёв, а основная масса из ~138 млн параметров сидит в полносвязной голове. Сегодня VGG - это эталонный учебный пример и удобный backbone для transfer learning.
Читайте также

Автоэнкодер (autoencoder): как сеть сжимает данные
Автоэнкодер (autoencoder) простыми словами: энкодер, латентное пространство и декодер, функция потерь реконструкции, виды сетей и где их применяют для сжатия и поиска аномалий.

Перенос обучения (transfer learning): как дообучить модель
Перенос обучения (transfer learning): зачем брать готовую сеть, чем отличается feature extraction от fine-tuning, как заморозить слои и не переобучиться на малой выборке.

CNN: архитектура свёрточной нейронной сети
Как устроена свёрточная нейронная сеть CNN: свёртка, пулинг, карты признаков. Формула размера выхода, подсчёт параметров, типичные ошибки при проектировании архитектуры.