Почему полносвязные сети плохи для картинок
Прежде чем понять, чем хороши CNN, разберёмся, почему обычная нейросеть на картинках проваливается.
Полносвязный слой (fully connected) — слой, где каждый нейрон связан с каждым входным значением. Отлично для табличных данных, но для картинок катастрофичен.
Проблема 1: взрыв числа параметров
Чтобы подать картинку в полносвязную сеть, её «разворачивают» в один длинный вектор пикселей. Посчитаем, сколько связей (весов) понадобится только для первого слоя из 1000 нейронов на цветной картинке 224×224.
width, height, channels = 224, 224, 3
inputs = width * height * channels
hidden = 1000
params = inputs * hidden # веса первого полносвязного слоя
print("Входных значений (пикселей*каналов):", inputs)
print("Нейронов в скрытом слое:", hidden)
print("Весов в одном слое:", params)
print("В миллионах:", round(params / 1_000_000, 1))
Вывод:
Входных значений (пикселей*каналов): 150528 Нейронов в скрытом слое: 1000 Весов в одном слое: 150528000 В миллионах: 150.5
150 миллионов весов — и это только первый слой для скромной картинки 224×224! Такую сеть невозможно обучить: ей нужны астрономические данные и память, и она мгновенно переобучится.
Проблема 2: потеря пространственной структуры
Разворачивая картинку в вектор, мы теряем геометрию. Для полносвязной сети пиксель в углу и его сосед справа — просто два далёких числа в длинном векторе; сеть не знает, что они рядом. А ведь именно соседство несёт смысл: глаз — это узор из близких пикселей. Полносвязная сеть вынуждена заново учить, какие пиксели «рядом», теряя на это огромный ресурс.
Проблема 3: нет переноса знаний по картинке
Кошка может оказаться в любом углу кадра. Полносвязная сеть, выучив распознавать кошку слева, заново учится распознавать её справа — для неё это разные входы. Это неэффективно: одно и то же знание не переиспользуется.
Что нужно вместо этого
Хорошая «зрительная» архитектура должна:
- Учитывать локальность: смотреть на маленькие окрестности, а не на всю картинку сразу.
- Переиспользовать веса: один и тот же детектор признака применять по всей картинке (это резко сокращает параметры).
- Сохранять геометрию: понимать, какие пиксели рядом.
Всё это даёт свёрточный слой: маленькое ядро (локальность) скользит по всей картинке с одними и теми же весами (переиспользование), сохраняя пространственное расположение. Ровно та свёртка, которую мы делали руками во втором разделе. О ней — следующий урок.
Итог
- Полносвязный слой на картинке даёт сотни миллионов весов — необучаемо.
- Разворачивание в вектор теряет геометрию: сеть не знает, какие пиксели рядом.
- Знание не переносится по картинке: кошку слева и справа учат отдельно.
- Решение — свёртка: локальность + переиспользование весов + сохранение структуры.