Глава 3. Частотный взгляд

Глава 3. Частотный взгляд на мир

Скольжение окна по картинке и умножение спектров — не две разные магии.
Это один и тот же факт, записанный на двух языках.

В главе 2 свёртка появилась как инженерный ответ на локальность.
Теперь посмотрим на неё глазами обработки сигналов. Не ради красоты формул — ради другого вопроса:

Что именно фильтр оставляет в изображении, а что выбрасывает?

Когда этот вопрос становится привычным, обучение CNN перестаёт быть чёрным ящиком «веса сами подстроились». Появляется язык, на котором можно спорить о гипотезах.


3.1. Изображение как сигнал

Любую картинку можно читать двумя способами.

Пространственный взгляд: сетка пикселей. Яркость в точке (x, y).

Частотный взгляд: сумма волн разной частоты и направления. Медленные волны — крупные пятна и фон. Быстрые — тонкие штрихи, шум, резкие границы.

Низкие и высокие частоты

Это не метафора «для гуманитариев». Преобразование Фурье буквально раскладывает изображение в такой базис. После него у вас не карта «где что нарисовано», а карта «какие частоты с какой силой присутствуют».

Зачем архитектору эта картинка в голове?

Потому что почти любой полезный локальный фильтр — это выбор частот:

Ручной фильтр Что делает по смыслу
Размытие (Gaussian) Режет высокие частоты
Выделение краёв (Sobel и друзья) Подчёркивает высокие
Полосовой фильтр Оставляет «средний» диапазон текстур

До глубокого обучения инженер рисовал эти фильтры руками.
CNN делает то же самое — только коэффициенты подбирает обучение.


3.2. Теорема о свёртке: два языка одной операции

Здесь как раз тот факт, который часто всплывает в разговорах и так же часто путается.

Есть три «мира»:

  1. Пространственный — пиксели и скользящее окно.
  2. Частотный — спектры после Фурье.
  3. Мир обучения — градиенты, которые крутят коэффициенты фильтра.

Теорема о свёртке связывает первые два:

Свёртка двух сигналов в пространстве

поэлементное произведение их спектров в частотной области.

Схематично:

Теорема о свёртке

Практический смысл для инженера:

  • «Прогнать картинку через фильтр» = «усилитить одни частоты и подавить другие».
  • Форма ядра g в пространстве задаёт маску G в частотах.
  • Обучение свёрточного слоя — это, среди прочего, поиск полезных частотных масок под задачу.

Важная оговорка, чтобы не словить ложную интуицию:

Произведение спектров — это про свёртку.
Не путать с тем, что «нейросеть всегда считает через FFT».

На практике Conv2d на GPU чаще считают прямыми алгоритмами по окнам (или Winograd и т.п.). Теорема объясняет смысл операции, а не обязательно путь в CUDA-ядре. Для архитектора важнее смысл: фильтр = частотный селектор.

Ещё одна тонкость из главы 2: в DL часто считают кросс-корреляцию без отражения ядра. Для теоремы это нюанс фазы/отражения; обучаемые веса снова делают спор почти академическим. Идея «фильтр режет спектр» остаётся рабочей.


3.3. Эволюция фильтров: как сеть переоткрывает классику

Поставьте мысленный эксперимент.

Берём простой стек свёрток. Задача — классификация. Смотрим на первые слои после нескольких эпох.

Очень часто (не всегда буквально, но узнаваемо) всплывают паттерны, которые человек рисовал десятилетиями:

Банк ранних фильтров

Это не доказательство, что CNN «изобрела Собеля».
Это доказательство более сильного тезиса:

Если архитектура умеет выражать частотные селекторы,
а задача требует границ и текстур,
оптимизатор сам нащупает семейство решений,
близкое к классической обработке сигналов.

Ручной путь: инженер знает, что краям нужны высокие частоты → рисует Sobel.
Обучаемый путь: инженер знает, что миру нужна локальность → ставит Conv → данные дорисовывают коэффициенты.

Второй путь победил не потому, что Фурье устарел.
Он победил потому, что вручную не масштабируется сборка иерархии таких фильтров под каждый датасет.

flowchart TD
    A[Задача на изображениях] --> B[Нужны края / текстуры / формы]
    B --> C{Как получить фильтры?}
    C --> D[Руками: Sobel, Gabor, SIFT…]
    C --> E[Обучением: стек Conv]
    D --> F[Хорошо на узкой задаче]
    D --> G[Плохо масштабируется на новые классы]
    E --> H[Те же частотные идеи внутри]
    E --> I[Иерархия и адаптация под данные]

3.4. Что частотный взгляд даёт архитектору

Частотный язык полезен не для того, чтобы на каждой планёрке рисовать спектры. Он полезен как набор быстрых гипотез.

1. Размытие и stride — это не только «уменьшили тензор».
MaxPool / stride-2 выбрасывают часть высоких частот и огрубляют координаты. Для классификации часто терпимо. Для детекции мелких объектов — уже статья расходов.

2. Глубокий стек маленьких 3×3 — это не только экономия параметров.
Несколько маленьких ядер подряд могут набрать поле зрения большого ядра и при этом выразить более богатый набор частотных ответов (плюс нелинейности между ними). Отсюда исторический ход VGG: лучше стек 3×3, чем одно огромное окно.

3. «Сеть не видит объект» иногда значит «нужная частота умерла по дороге».
Слишком агрессивный downsampling, слишком ранний сильный low-pass — и от спички на горизонте не остаётся носителя признака.

4. Augmentations тоже имеют частотную тень.
Сильный blur режет верх спектра. JPEG-артефакты добавляют свои частоты. Если валидация «чистая», а прод — сжатый видеопоток, вы сравниваете модели на разных спектральных мирах.

Пространственный язык Частотный язык
ядро 3×3 локальный частотный селектор
много фильтров набор разных масок спектра
stride / pool огрубление + потеря highs
глубокий стек иерархия от highs к структуре
feature map где выбранные частоты сильны

3.5. Где частотный взгляд врёт или упрощает

Честность важнее красивой аналогии.

Нелинейности ломают чистую картину.
Теорема о свёртке — про линейные системы. Между свёртками у нас ReLU и компания. После нелинейности «просто умножить спектры» уже нельзя в лоб. Частотный язык остаётся интуицией для локального линейного куска, а не полной теорией сети.

Глобальный смысл ≠ низкие частоты.
«Это кошка» — не то же самое, что «в кадре много низких частот». Семантика живёт в комбинациях признаков по пространству и по слоям. Спектр — инструмент, не замена представлениям.

Attention и глобальные связи говорят на другом диалекте.
Когда позже появятся трансформеры, чистой локальной частотной интуиции станет мало: модель сможет связывать далёкие патчи напрямую. Это не отменяет главу — это ограничивает её юрисдикцию.

Итоговая рамка:

Частотный взгляд объясняет, почему свёртка вообще имеет право на жизнь
и что она делает с сигналом.
Он не объясняет всю современную архитектуру целиком.

Для Части I этого достаточно как рамка.
Ниже — углубление: когда FFT-путь реально выгоднее, как downsampling врёт про частоты, и зачем архитектору антиалиасинг.


3.6. FFT-свёртка vs прямое окно: когда какой путь

Теорема говорит: можно посчитать свёртку через частоты.
Железо спрашивает: нужно ли?

Грубая инженерная развилка:

прямое окно выгодно, когда:
  • ядро маленькое (3×3, 5×5)
  • карта не гигантская
  • есть хорошие GPU-kernels (Winograd / implicit GEMM)

FFT-путь начинает блестеть, когда:
  • ядро большое или «полный» фильтр по карте
  • нужно много больших корреляций
  • накладные FFT/IFFT окупаются
стоимость (очень схематично)

прямой Conv:  ~ H·W·K²·C_in·C_out
FFT-путь:     ~ C · (H·W log(H·W))  + поточечные произведения
               (плюс память на спектры, плюс padding до удобных размеров)

Практический вывод для читателя книги:

Теорема объясняет смысл.
Выбор алгоритма объясняет счёт на вашем размере задачи.

Именно поэтому nn.Conv2d(3×3) почти никогда не «идёт в FFT внутри» на обучении классических CNN — не потому что математика врёт, а потому что для малых K прямой путь быстрее и проще.


3.7. Downsampling как частотная ловушка

Stride-2 и pooling — не только «сделали тензор меньше».
Это дискретизация заново.

Если в сигнале были высокие частоты, а вы проредили сетку без предварительного сглаживания, получаете алиасинг: высокие частоты притворяются низкими.

до /2                     после наивного /2

высокая частота           «ложный» низкочастотный узор
▓▓░░▓▓░░▓▓░░              ▓░░▓░░▓░░

Почему это важно архитектору детекции/сегментации:

  • мелкие периодические текстуры «ломаются» в странные паттерны;
  • сдвиговая устойчивость ухудшается: объект на чётном/нечётном пикселе ведёт себя по-разному;
  • часть «магии» современных stem/anti-alias блоков — просто признание этой ловушки.

Связь с главой 2:

Padding/stride крутили как ручки размера.
Частотный взгляд добавляет: ручка stride ещё и врёт спектру, если её крутить грубо.

Отсюда гипотезы, которые стоит проверять абляциями:

  1. AvgPool / blur перед subsample вместо голого stride-2 MaxPool.
  2. Более плавный stem в начале сети.
  3. Аккуратный upsample в FPN (не только «ближайший сосед», если важны края).

3.8. Обучение как подбор банка фильтров

Сложите три уровня языка в одну схему:

уровень 1: пиксели и окна          (гл. 2)
уровень 2: частоты и маски         (гл. 3)
уровень 3: оптимизация коэффициентов под loss задачи

Ручной путь классики:

инженер → выбирает Sobel/Gabor/… → фиксированный банк → классификатор сверху

CNN-путь:

архитектор → фиксирует форму (локальность, K, число каналов, stride)
оптимизатор → подбирает коэффициенты банка под данные
глубокий стек → строит иерархию ответов банка

Что остаётся за архитектором, даже когда «фильтры сами»:

  • сколько частотных селекторов (ширина);
  • как быстро мы выбрасываем highs (stride/pool);
  • где ставим нелинейность (после каких смесителей);
  • какой prior важнее данных (чисто CNN vs позже ViT).
flowchart TD
    A[Сигнал/изображение] --> B[Банк локальных фильтров]
    B --> C{Кто задаёт коэффициенты?}
    C --> D[Руками: классический CV]
    C --> E[Обучением: CNN]
    B --> F{Кто задаёт downsampling?}
    F --> G[Архитектор: stride/pool/anti-alias]
    G --> H[Какие частоты доживут до головы]

3.9. Закрываем Часть I

Три главы — один сюжет:

Глава 1  Brute force умер
           ↓
Глава 2  Локальность + sharing → свёртка
           ↓
Глава 3  Свёртка = частотный селектор;
         обучение подбирает маски;
         stride/pool решают, какие частоты выживут

Мы встроили в архитектуру знание о мире: соседние пиксели связаны, паттерны повторяются, полезное часто лежит в структуре спектра — и легко убивается грубым прореживанием.

Следующий кризис будет другим.
Мы научимся делать сети глубже — и обнаружим, что «больше слоёв» внезапно означает «хуже обучается».


Если бы вы были автором статьи…

  1. Если свёртка в пространстве = произведение спектров, зачем считать окна, а не FFT → multiply → IFFT?
    Для каких K и H×W FFT-путь выгоднее на вашем GPU? Где побеждает прямой алгоритм / Winograd?

  2. Модель отлично работает на PNG и проваливается на сильно сжатом JPEG.
    Сформулируйте частотную гипотезу. Какой эксперимент её подтвердит или убьёт?

  3. Спроектируйте антиалиас-downsample (blur + stride) и сравните с голым MaxPool stride-2.
    На какой метрике ждёте выигрыш: сдвиговая стабильность, мелкие объекты, шумные текстуры?

  4. Можно ли сознательно запретить диапазон частот слоем?
    Когда это робастность, а когда вы просто выкололи полезный сигнал?

В Части II мы разберём, почему глубокий стек таких фильтров начинает задыхаться — и какое простое на вид архитектурное решение вернуло градиентам дорогу назад.