Слой SeparableConv2D
вычисляет свертку с разделением по глубине, которая, в отличие от обычной свертки, требует 2 ядра (2 весовых тензора). Не вдаваясь в подробности, он использует первое ядро для вычисления глубинной свертки, после применения этой операции оно использует второе ядро для вычисления точечной свертки. Основная идея заключается в том, чтобы уменьшить количество параметров и, следовательно, количество вычислений.
Вот простой пример. Предположим, что у нас есть входное изображение 28x28x3 (ширина, высота, количество каналов) и мы применяем обычную 2D-свертку (скажем, 16 фильтров и ядро 5x5, без шага/отступа).
Если мы проведем вычисления, то получим 5x5x3x16 (размер фильтра 5x5, 3 входных канала и 16 фильтров) = 1200 параметров ядра + 16 параметров смещения (по одному на каждый фильтр) = 1216. Мы можем это проверить.
model = tf.keras.models.Sequential([
tf.keras.layers.Input(shape=(28, 28, 3)),
tf.keras.layers.Conv2D(16, (5, 5)),
])
model.summary()
дает нам
Layer (type) Output Shape Param #
=================================================================
conv2d_4 (Conv2D) (None, 24, 24, 16) 1216
и если мы извлечем параметры ядра.
print(model.layers[0].get_weights()[0].shape)
Это дает нам
(5, 5, 3, 16)
Теперь давайте рассмотрим отделимую 2D-свертку, которая имеет 2 ядра, ядро по глубине, которое состоит из отдельных весовых матриц 5x5x1 для каждого входного канала, в нашем случае - 5x5x3 (5x5x3x1 - для согласования с тензорами 4D keras). Это дает нам 75 параметров.
Поточечное ядро представляет собой простую свертку 1x1 (она работает с каждой входной точкой) и используется для увеличения глубины результата до числа указанных фильтров. В нашем случае — 1х1х3х16, что дает нам 48 параметров.
Всего у нас есть 75 параметров для первого ядра и 48 параметров для второго ядра, что дает нам 123 параметра плюс, опять же, 16 параметров смещения. То есть 139 параметров.
В Керасе,
model = tf.keras.models.Sequential([
tf.keras.layers.Input(shape=(28, 28, 3)),
tf.keras.layers.SeparableConv2D(16, (5, 5)),
])
model.summary()
дает нам
Layer (type) Output Shape Param #
=================================================================
separable_conv2d_7 (Separabl (None, 24, 24, 16) 139
Как мы видим, выходная форма этих слоев точно такая же, как и у обычного сверточного слоя, но теперь у нас есть 2 ядра с гораздо меньшими параметрами. И снова мы можем извлечь параметры для этих двух ядер,
print(model.layers[0].get_weights()[0].shape)
print(model.layers[0].get_weights()[1].shape)
что дает нам
(5, 5, 3, 1)
(1, 1, 3, 16)
Если вам нужна более подробная информация о как работает отделимая свертка.
person
Matus Dubrava
schedule
14.10.2020