Вы можете узнать количество (не) обучаемых параметров модели в Керасе, используя функцию summary
:
from keras import models, layers
model = models.Sequential()
model.add(layers.Conv2D(10, (4,4), input_shape=(32, 32, 3)))
model.summary()
Вот результат:
Layer (type) Output Shape Param #
=================================================================
conv2d_1 (Conv2D) (None, 29, 29, 10) 490
=================================================================
Total params: 490
Trainable params: 490
Non-trainable params: 0
В общем случае для слоя 2D-свертки с фильтрами k
размером w*w
, применяемыми к входу с каналами c
, число обучаемых параметров (с учетом одного параметра смещения для каждого фильтра в случае по умолчанию) равноравно k*w*w*c+k
или k*(w*w*c+1)
.В приведенном выше примере мы имеем: k=10, w=4, c=3
поэтому у нас есть 10*(4*4*3+1) = 490
обучаемые параметры.Как вы можете сделать вывод, для каждого канала существуют отдельные веса, и они не являются общими.Кроме того, количество параметров слоя 2D-свертки не зависит от ширины или высоты предыдущего слоя.
Обновление:
Сверточный слой с глубинойобщие весовые коэффициенты: я не знаю о таком слое и не смог найти встроенную реализацию этого в Keras или Tensorflow.Но подумав об этом, вы понимаете, что это по сути эквивалентно суммированию всех каналов вместе, а затем применяет двумерную свертку к результату.Например, в случае изображения 32*32*3
сначала все три канала суммируются, в результате чего получается тензор 32*32*1
, а затем к нему можно применить двумерную свертку.Поэтому, по крайней мере, один способ достижения 2D-свертки с общими весами по каналам может быть таким в Керасе (который может или не может быть эффективным):
from keras import models, layers
from keras import backend as K
model = models.Sequential()
model.add(layers.Lambda(lambda x: K.expand_dims(K.sum(x, axis=-1)), input_shape=(32, 32, 3)))
model.add(layers.Conv2D(10, (4,4)))
model.summary()
Вывод:
Layer (type) Output Shape Param #
=================================================================
lambda_1 (Lambda) (None, 32, 32, 1) 0
_________________________________________________________________
conv2d_1 (Conv2D) (None, 29, 29, 10) 170
=================================================================
Total params: 170
Trainable params: 170
Non-trainable params: 0
Одна хорошая вещь в этом лямбда-слое состоит в том, что он может быть добавлен в любом месте (например, после свертки).Но я думаю, что самый важный вопрос, который нужно здесь задать, это: «Почему было бы полезно использовать слой 2D-conv с распределенными весами по глубине?»Один очевидный ответ заключается в том, что размер сети (т. Е. Общее число обучаемых параметров) уменьшается, и, следовательно, может быть сокращение времени обучения, которое, я подозреваю, будет незначительным.Кроме того, использование общих весов по каналам подразумевает, что шаблоны, присутствующие в разных каналах, более или менее похожи.Но это не всегда так, например, в изображениях RGB, и поэтому, используя общие веса по каналам, я думаю, вы могли бы наблюдать (заметное) снижение точности сети.Так что, по крайней мере, вы должны иметь в виду этот компромисс и поэкспериментировать с ним.
Однако есть еще один вид сверточного слоя, который вас может заинтересовать, называемый «Разделяемая свертка с глубиной»который был реализован в Tensorflow, и Keras также поддерживает его .Идея состоит в том, что на каждом канале применяется отдельный фильтр 2D-свёртки, а затем полученные карты характеристик агрегируются с использованием k
1*1
сверток (k
здесь - количество выходных каналов).Он в основном разделяет изучение пространственных и глубинных элементов.В своей статье «Xception: глубокое обучение с отделимыми по глубине извилинами» Франсуа Шоле (создатель Keras) показывает, что использование отделимых по глубине извилистых извилин повышает как производительность, так и точность сети.И здесь вы можете прочитать больше о различных видах слоев свертки, используемых в глубоком обучении.