Что означает layer.get_weights() сверточного слоя Separable?

Я узнал, что мы можем использовать функцию layer.get_weights() для получения веса и смещения слоя. Это вернет список длины 2. Веса слоя хранятся в layer.get_weights()[0], а смещение сохраняется в layer.get_weights()[1] (если смещение не отключено во время определения слоя). Это верно для нормального сверточного слоя.

Недавно я использовал сверточный слой Separable в качестве одного из своих слоев в файле EfficientDet model.

layers.SeparableConv2D(num_channels, kernel_size=kernel_size, strides=strides, padding='same',
                            use_bias=True, name=str(name)+"/conv")

Когда я пытаюсь использовать ту же функцию layer.get_weights(), она вернула мне список length 3, где я ожидал, что это будет 2, который совпадает с приведенным выше. При этом я немного смущен тем, что представляют собой три значения в списке. Любая помощь и предложения будут оценены.


person Saurav Rai    schedule 14.10.2020    source источник


Ответы (1)


Слой 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
comment
Спасибо за подробное объяснение. Я уверен, что это будет очень полезно и для будущих пользователей. Ваше здоровье :) - person Saurav Rai; 15.10.2020