Свёрточные сети (CNN) для изображений
Урок объясняет, как свёрточные сети экономно и осмысленно работают с изображениями.
Свёртка — это операция, при которой маленькое окно весов (ядро, фильтр) скользит по входу и в каждой позиции считает взвешенную сумму, выделяя локальный признак.
Ключевая идея: общий детектор
Вместо отдельного веса на каждый пиксель CNN использует маленькое ядро (например, 3×3) и прогоняет его по всей картинке. Один и тот же набор из девяти весов ищет, скажем, вертикальный край в каждой точке изображения. Это решает сразу две проблемы MLP: параметров мало (девять вместо миллионов) и детектор работает в любой позиции (инвариантность к сдвигу).
Свёртка на одномерном примере
Чтобы увидеть суть без матриц, возьмём одномерный сигнал и ядро-детектор перепада [-1, 1]. Там, где сигнал меняется, свёртка даст ненулевой отклик — это и есть «найденный край».
def conv1d(signal, kernel):
k = len(kernel)
out = []
for i in range(len(signal) - k + 1):
window = signal[i:i+k]
out.append(sum(w * x for w, x in zip(window, kernel)))
return out
signal = [0, 0, 0, 5, 5, 5, 0, 0]
edges = conv1d(signal, [-1, 1]) # детектор перепада
print("Сигнал: ", signal)
print("После свёртки: ", edges)
def maxpool(xs, size=2):
return [max(xs[i:i+size]) for i in range(0, len(xs), size)]
print("После max-пулинга:", maxpool([abs(v) for v in edges]))
Вывод:
Сигнал: [0, 0, 0, 5, 5, 5, 0, 0] После свёртки: [0, 0, 5, 0, 0, -5, 0] После max-пулинга: [0, 5, 5, 0]
Свёртка выдала всплески ровно там, где сигнал скакнул вверх (+5) и вниз (-5) — детектор нашёл границы блока. Внутри ровных участков отклик нулевой. Так фильтр «подсвечивает» нужный признак.
Пулинг: сжимаем и обобщаем
Пулинг уменьшает размер карты признаков, оставляя в каждом окне максимум (max-pooling) или среднее. Это сокращает вычисления и даёт устойчивость к мелким сдвигам: даже если признак чуть сместился, максимум в окне сохранится. В примере четыре значения схлопнулись в более компактное представление.
Из чего собрана типичная CNN
| Слой | Что делает |
| свёрточный | находит локальные признаки фильтрами |
| активация (ReLU) | добавляет нелинейность |
| пулинг | уменьшает размер, обобщает |
| полносвязный (в конце) | по найденным признакам выдаёт ответ |
Слои чередуются: ранние свёртки ловят края, последующие — текстуры и части объектов, а финальные полносвязные слои собирают из них решение. Так устроены классические сети вроде LeNet, AlexNet, ResNet — фундамент компьютерного зрения.
Каналы и фильтры
В реальной CNN на каждом свёрточном слое не один фильтр, а десятки и сотни — и каждый ищет свой признак (один — горизонтальные края, другой — пятна определённого цвета, третий — диагонали). Их отклики складываются в стопку карт признаков (по карте на фильтр), которая становится входом следующего слоя. Так глубина сети наращивает богатство признаков: из простых краёв собираются текстуры, из текстур — части объектов, из частей — объекты целиком. Цветная картинка и на входе имеет три канала (R, G, B), поэтому фильтр первого слоя тоже трёхмерный — он смотрит сразу на все каналы в своём окне.
Важно, что обучаются именно веса фильтров — теми же backprop и градиентным спуском, что мы прошли. Никто не задаёт ядро [-1, 1] вручную: сеть сама выясняет, какие фильтры полезны для задачи. Наш ручной пример с детектором перепада — лишь иллюстрация того, что фильтр в принципе умеет находить; в обученной сети таких выученных детекторов тысячи.
Итог
- Свёртка — скользящее ядро, ищущее локальный признак во всех позициях.
- Общие веса дают мало параметров и инвариантность к сдвигу.
- Пулинг сжимает карту признаков и добавляет устойчивость к мелким сдвигам.