В прошлой статье мы разбирали классическое машинное обучение — алгоритмы, которые подбирают функцию под табличные данные. Но у таблиц есть предел: они не описывают изображения. Картинка 224×224 — это 150 тысяч чисел (пикселей), и связывать каждый пиксель с каждым, как делает полносвязная сеть, бессмысленно: слишком много параметров, слишком мало сигнала, слишком сильное переобучение.
И всё же нейросети научились видеть — распознавать лица, диагностировать по снимкам, управлять беспилотниками. Прорыв случился не из-за большего количества слоёв, а из-за одной элегантной идеи: свёртки. Эта статья — про то, почему свёртка оказалась тем приёмом, который сделал компьютерное зрение возможным, и как слои свёрточной сети от краёв доходят до целых объектов.
1. Проблема: пиксели не живут по одному
Представьте, что вы хотите научить нейросеть распознавать кошек. Самый наивный подход — flatten: развернуть картинку в длинный вектор и подать в многослойный перцептрон (MLP). Каждый пиксель связывается с каждым нейроном следующего слоя. Для картинки 224×224 и скромного скрытого слоя из 1000 нейронов это уже 150 миллионов параметров — и почти все бесполезны.
Почему бесполезны? Потому что смысл изображения — не в отдельных пикселях, а в их локальных сочетаниях. Край уха кошки — это не пиксель (310, 420), а узор из десятка соседних пикселей, образующих тёмную линию на светлом фоне. Глаз — это сочетание краёв в форме круга с тёмным зрачком посередине. Информация о кошке размазана по локальным окрестностям, и полносвязная сеть, привязанная к абсолютным позициям пикселей, эту структуру не использует.
К тому же кошка может сидеть в левом верхнем углу или в правом нижнем — ухо от этого не перестаёт быть ухом. Полносвязной сети пришлось бы заново учиться распознавать ухо в каждой позиции кадра. Это безнадёжно.
Нужен механизм, который: (1) смотрит на локальные окрестности, а не на весь кадр сразу; (2) делится знаниями между позициями — узор «край», выученный в одном углу, работает везде. И именно это делает свёртка.
2. Главная метафора: лупа, скользящая по картинке
Представьте лаборанта с лупой, который водит маленьким окошком по фотографии — квадратик 3×3 пикселя за раз, слева направо, сверху вниз. В каждой позиции лабратор смотрит: «похоже ли то, что в окошке, на вертикальную линию? на горизонтальную? на уголок?». И в каждой позиции записывает ответ: да/нет и насколько сильно.
Это и есть свёртка. «Лупа» — это фильтр (или ядро, kernel), маленькая матрица чисел 3×3. Скользя ею по картинке, мы перемножаем значения фильтра с пикселями под ним и суммируем — получается одно число «насколько этот участок похож на узор фильтра». Результат — новая матрица, карта активаций, где яркие точки означают «здесь фильтр сработал».
Картинка 5×5: Фильтр 3×3 («вертикальный край»):
1 1 1 0 0 1 0 -1
1 1 1 0 0 1 0 -1
1 1 1 0 0 1 0 -1
1 1 1 0 0
1 1 1 0 0
Свёртка фильтром → карта активаций 3×3:
0 4 0 (яркая полоса там, где вертикальный край)
0 4 0
0 4 0
Ключевой момент: веса фильтра — одни и те же для каждой позиции. Это называется весовым разделением (weight sharing). Один фильтр «вертикальный край», выученный сетью, применяется ко всей картинке, а не переучивается для каждой позиции. Это даёт сразу два выигрыша: параметров на порядки меньше, и знание «край» переносится между позициями.
3. Несколько фильтров: палитра узоров
Один фильтр находит один тип узора. Но картина богаче: нужны и вертикальные края, и горизонтальные, и диагонали, и цветовые пятна, и текстуры. Поэтому свёрточный слой — это много фильтров, скажем 32 или 64, каждый со своими весами.
Каждый фильтр скользит по картинке и порождает свою карту активаций. На выходе слоя получается не одна матрица, а стопка карт активаций — по одной на фильтр. Если было 64 фильтра, то стопка имеет глубину 64. Эта стопка становится «новой картинкой» для следующего слоя.
Важно: веса фильтров не задаются вручную. Они инициализируются случайно и учатся через обратное распространение ошибки, точно как веса в любой нейросети. Сеть сама выучивает, какие фильтры ей нужны — экспериментально обнаружено, что на первых слоях обученных CNN фильтры похожи на края и цвета, на средних — на текстуры и части объектов, на последних — на целые формы (глаза, колёса, лица).
4. Pooling: сжатие и инвариантность
Между свёрточными слоями обычно стоит операция пулинга (pooling), чаще всего max-pooling. Она берёт маленькое окно 2×2 в карте активаций и оставляет только максимальное значение, отбрасывая три остальных. Размер карты уменьшается вдвое.
Зачем? Две причины. Первая — вычислительная: чем дальше, тем меньше данных, тем дешевле следующие слои. Вторая — семантическая, и она важнее: пулинг даёт инвариантность к небольшим сдвигам. Если край уха в карте активаций чуть сместился (кошка дёрнула головой), max-pooling всё равно «поймает» его — ведь максимум в окне почти не меняется при сдвиге на пиксель. Сеть учится реагировать на «есть край где-то в этой области», а не «есть край точно в (12, 7)».
Карта 4×4: Max-pool 2×2 → Карта 2×2:
1 3 2 1 3 2
4 2 0 1 4 1
2 5 3 2
1 0 2 4
5. Иерархия: от краёв к объектам
Теперь сложим всё вместе. Типичная CNN — это чередование свёрточных слоёв и пулингов, после которых идёт один-два полносвязных слоя для финальной классификации. И вот здесь происходит самое интересное: глубина порождает иерархию абстракций.
- Слой 1 видит маленькие окрестности (3×3 пикселя). Фильтры выучиваются реагировать на простейшие элементы: вертикальные и горизонтальные края, цветовые переходы, пятна.
- Слой 2 получает на вход карты активаций слоя 1. Его фильтры, скользя по уже обработанным данным, комбинируют края в чуть более сложные узоры: уголки, пересечения, простые текстуры, маленькие паттерны.
- Слои 3–4 комбинируют узоры в «части»: круг с тёмным центром (глаз), треугольник (ухо), решётчатая текстура (шерсть).
- Последние свёрточные слои собирают части в целые формы: «глаз + ухо + нос в такой конфигурации = кошачья морда».
- Полносвязные слои в конце смотрят на всю эту иерархию и принимают финальное решение: кошка или собака.
Это иерархия абстракций, и она же — главная аналогия с биологическим зрением. Зрительная кора млекопитающих устроена схожим образом: первые зоны реагируют на простые стимулы (линии, движения), более глубокие — на сложные формы и лица. Это не совпадение: и биологическая, и искусственная эволюция пришли к одному принципу — строить сложное из простого по слоям.
6. Почему это революция: три ключевых свойства
Свёртка работает не потому, что она «умнее», а потому, что она встроила в архитектуру три правильных допущения о том, как устроены изображения.
Локальность. Соседние пиксели связаны сильнее, чем далёкие. Свёртка смотрит только на окрестность, и это соответствует реальности: край, текстура, деталь — локальные явления.
Весовое разделение. Один и тот же узор (край, глаз) может появиться в любой позиции кадра. Фильтр, разделяемый между позициями, ловит это без переобучения под каждый угол.
Иерархия. Сложные концепции строятся из простых. Кошка = (глаз + ухо + нос), каждый из которых = (края + текстуры), каждый из которых = (пиксели). Слои отражают эту композицию.
Вместе эти три свойства дают архитектуру, которая извлекает признаки сама, без ручного feature engineering (как в классическом ML). До CNN инженер должен был придумывать признаки: «посчитаем гистограмму цветов, найдём контуры через Canny, вычислим HOG-дескрипторы». CNN делает это сама, и лучше. Именно поэтому AlexNet в 2012 году — первая глубокая CNN на ImageNet — разом снизила ошибку классификации с 25% до 15% и открыла эру глубокого обучения.
7. Сёмейство архитектур: от LeNet до ResNet
За 30 лет CNN прошли несколько волн, и каждая решала конкретную проблему предыдущей.
LeNet (Yann LeCun, 1998). Первая успешная CNN — распознавание почтовых индексов и чеков. 7 слоёв, маленькая. Доказала, что идея работает, но для больших картинок не хватало вычислений и данных.
AlexNet (2012). Прорыв на ImageNet: глубокая CNN на GPU, с ReLU-активациями и dropout. Обучалась неделю на двух видеокартах, разнесла конкурентов и запустила бум глубокого обучения.
VGG, GoogLeNet (2014). Эксперименты с глубиной (16–22 слоя) и архитектурой блоков. Стало понятно: глубина помогает, но обучать глубокие сети тяжело — градиент затухает.
ResNet (2015). Решение проблемы глубины через остаточные связи (residual connections): каждый слой учится не всему ответу, а поправке к ответу предыдущего слоя (звучит знакомо? — да, это та же идея, что в бустинге, только в нейросетях). ResNet с 152 слоями снова снизила ошибку и позволила строить действительно глубокие сети. Остаточные связи стали стандартом не только в CNN — они же лежат в основе Transformer-блоков.
8. Куда делись CNN: эпоха Vision Transformer
История не стоит на месте. В 2020 году статья «An Image is Worth 16x16 Words» показала, что трансформеры — та же архитектура, что и в LLM — могут работать с картинками напрямую, если нарезать их на «патчи» (квадратики 16×16) и подать как последовательность токенов. Vision Transformer (ViT) на больших данных обходит CNN.
Значит ли это, что CNN умирают? Нет. ViT требуют огромных данных для обучения с нуля, а CNN эффективнее при transfer learning и на небольших датасетах. Современные state-of-the-art архитектуры часто гибридные: свёрточные слои для извлечения локальных признаков + transformer-блоки для глобального контекста. Та же история, что с RNN и трансформерами в NLP: новые не убили старые, а заняли свою нишу.
9. Почему это важно для self-hosting и инженеров
Даже если вы не обучаете CV-модели сами, понимание CNN помогает принимать инженерные решения.
Выбор модели под задачу. Нужно распознать документы на сканах? Детектировать дефекты на конвейере? Модерировать изображения в вашем сервисе? Готовые CNN-модели (ResNet, EfficientNet, YOLO) запускаются локально через ONNX Runtime илиTensorRT, без облака. YOLO детектирует объекты в реальном времени на CPU — это уровень self-hosted сервиса.
Transfer learning. Не нужно обучать CNN с нуля (это дорого). Берёте предобученную ResNet на ImageNet, замораживаете большую часть слоёв и дообучаете только последние на свои данные. Мы разбирали похожий принцип fine-tuning в контексте LLM — в CV он ещё эффективнее, потому что низкоуровневые признаки (края, текстуры) универсальны. 100 картинок вашего класса часто достаточно.
Embeddings для поиска по картинкам. Предпоследний слой CNN выдаёт вектор признаков изображения — это эмбеддинг картинки, ровно та же концепция, что эмбеддинги слов в NLP. Похожие картинки (по содержанию) дают близкие векторы. На этом работает обратный поиск по картинке, рекомендательные системы, векторные базы. Если вы делаете свой RAG по изображениям — именно CNN даст вам эмбеддинги.
Заключение
Свёрточные сети стали возможными не потому, что кто-то «добавил слоёв», а потому, что встроил в архитектуру три правильных предположения о природе изображений: локальность, разделение весов и иерархию. Свёртка — это «лупа, которая скользит», и её гениальность в простоте: мы не объясняем сети, что такое край, мы даём ей фильтр и говорим «выучи сама». И она выучивает — сначала края, потом части, потом объекты.
В следующей статье серии мы разберём другой прорыв — генеративные модели. Если CNN анализируют изображения, то GAN, VAE и диффузионные модели их создают. И там нас ждёт знакомый паттерн: итеративное улучшение, которое мы уже видели и в бустинге, и в остаточных связях ResNet.