Зачем в нейронных сетях используется свертка с ядром 1x1
Что проверяют
Понимаете ли вы, что свёртка 1×1 работает не по пространству, а по каналам, и умеете ли посчитать, сколько она экономит. Следом обычно просят нарисовать bottleneck-блок ResNet или объяснить, из чего состоит depthwise separable свёртка.
Как отвечать
Свёртка 1×1 в каждой точке карты признаков берёт вектор из C_in каналов и умножает его на матрицу C_in × C_out. По сути это один полносвязный слой, применённый к каждому пикселю с общими весами. Пространственный размер не меняется (если не задан шаг), параметров C_in · C_out плюс смещения. В PyTorch это nn.Conv2d(c_in, c_out, kernel_size=1), что эквивалентно nn.Linear по оси каналов.
Зачем она нужна:
- сжатие каналов перед дорогой свёрткой: классический расчёт из Inception. Вход 28×28×192, выход 32 канала свёрткой 5×5: около 120 млн умножений. Если сначала сжать 1×1 до 16 каналов, выходит примерно 2,4 млн плюс 10 млн, почти в десять раз меньше;
- bottleneck в ResNet-50 и глубже: 1×1 сжимает, 3×3 работает на узком тензоре, 1×1 возвращает число каналов. Там же 1×1 с шагом 2 служит проекцией в shortcut, когда размеры не совпадают;
- pointwise в depthwise separable свёртке (MobileNet, Xception): depthwise обрабатывает каждый канал отдельно по пространству, а 1×1 смешивает каналы;
- дополнительная нелинейность: 1×1 с активацией после неё добавляет глубину почти бесплатно, идея из Network in Network;
- голова модели: последняя 1×1 в сегментации даёт в каждом пикселе вектор по числу классов, а замена полносвязных слоёв свёртками делает сеть независимой от размера входа.
Где спотыкаются
Говорят, что 1×1 «ничего не делает» или просто масштабирует. Это верно только для одного канала, при многих каналах это полноценное обучаемое смешивание.
Думают, что 1×1 уменьшает высоту и ширину. Пространство уменьшают шаг и пулинг, 1×1 меняет только глубину.
Приписывают нелинейность самой свёртке. Сама по себе она линейна, и две 1×1 подряд без активации схлопываются в одну.