Как рассчитать количество параметров для сверточной нейронной сети?
Я использую лазанью для создания CNN для набора данных MNIST. Я внимательно следую этому примеру:сверточные нейронные сети и извлечение функций с помощью Python.
архитектура CNN, которую я имею на данный момент, которая не включает в себя какие-либо выпадающие слои, является:
NeuralNet(
layers=[('input', layers.InputLayer), # Input Layer
('conv2d1', layers.Conv2DLayer), # Convolutional Layer
('maxpool1', layers.MaxPool2DLayer), # 2D Max Pooling Layer
('conv2d2', layers.Conv2DLayer), # Convolutional Layer
('maxpool2', layers.MaxPool2DLayer), # 2D Max Pooling Layer
('dense', layers.DenseLayer), # Fully connected layer
('output', layers.DenseLayer), # Output Layer
],
# input layer
input_shape=(None, 1, 28, 28),
# layer conv2d1
conv2d1_num_filters=32,
conv2d1_filter_size=(5, 5),
conv2d1_nonlinearity=lasagne.nonlinearities.rectify,
# layer maxpool1
maxpool1_pool_size=(2, 2),
# layer conv2d2
conv2d2_num_filters=32,
conv2d2_filter_size=(3, 3),
conv2d2_nonlinearity=lasagne.nonlinearities.rectify,
# layer maxpool2
maxpool2_pool_size=(2, 2),
# Fully Connected Layer
dense_num_units=256,
dense_nonlinearity=lasagne.nonlinearities.rectify,
# output Layer
output_nonlinearity=lasagne.nonlinearities.softmax,
output_num_units=10,
# optimization method params
update= momentum,
update_learning_rate=0.01,
update_momentum=0.9,
max_epochs=10,
verbose=1,
)
это выводит следующую информацию о слое:
# name size
--- -------- --------
0 input 1x28x28
1 conv2d1 32x24x24
2 maxpool1 32x12x12
3 conv2d2 32x10x10
4 maxpool2 32x5x5
5 dense 256
6 output 10
и выводит количество изучаемых параметров как 217,706
Я интересно, как рассчитывается это число? Я читал немало ресурсов, в том числе в этом сайте StackOverflow-это вопрос, но ни один явно не обобщает расчет.
Если возможно, можно ли обобщить расчет изучаемых параметров на слой?
например, сверточный слой: количество фильтров x Ширина фильтра x высота фильтра.
2 ответов
давайте сначала посмотрим, как вычисляется количество обучаемых параметров для каждого отдельного типа слоя, который у вас есть, а затем вычислить количество параметров в вашем примере.
- входного слоя: все, что делает входной слой, это считывает входное изображение, поэтому здесь нет параметров,которые вы могли бы узнать.
-
слои сверточных: рассмотрим сверточный слой, который принимает
l
карты объектов на входе, иk
feature maps в качестве вывода. Размер фильтраn
xm
. Например, это будет выглядеть так:здесь вход
l=32
feature maps в качестве ввода,k=64
feature maps в качестве вывода, а размер фильтра -n=3
xm=3
. Важно понимать, что у нас не просто есть фильтр 3x3, но на самом деле фильтр 3x3x32, так как наш вход имеет 32 измерения. И мы изучаем 64 различных фильтра 3x3x32. Таким образом, общее количество весов -n*m*k*l
. Тогда есть также термин смещения для каждой карты объектов, поэтому у нас есть общее количество параметров(n*m*l+1)*k
. - объединение слоев: слои объединения, например, делают следующее:"замените окрестности 2x2 на его максимальное значение". Поэтому нет параметр можно узнать в слое объединения.
-
полносвязные слои: в полн-Соединенном слое, все блоки входного сигнала имеют отдельный вес к каждый выходной блок. Для
n
входы иm
выходы, количество весов -n*m
. Кроме того, у вас есть смещение для каждого выходного узла, поэтому вы находитесь в(n+1)*m
параметры. -
выходной слой: выходной слой является нормальным полностью подключенным слоем, поэтому
(n+1)*m
параметры, гдеn
- количество входов иm
- количество выходов.
заключительная трудность-это первый полностью подключенный слой: мы не знаем размерность входа в этот слой, так как он является сверточным слоем. Чтобы вычислить его, мы должны начать с размера входного изображения и вычислить размер каждого сверточного слоя. В вашем случае, лазанья уже вычисляет это для вас и передает размеры, что делает его легким для нас. Если вам нужно вычислить размер каждого слоя самостоятельно, это немного сложнее:
- в простейшем случае (например, в вашем примере) размер вывода сверточный слой
input_size - (filter_size - 1)
в вашем случае: 28 - 4 = 24. Это связано с характером свертки: мы используем, например, окрестности 5x5 для вычисления точки, но две крайние строки и столбцы не имеют окрестности 5x5, поэтому мы не можем вычислить какой - либо выход для этих точек. Вот почему наш выход 2*2=4 строки / столбца меньше, чем вход. - если вы не хотите, чтобы выход был меньше, чем вход, можно обнулить изображение (с помощью из сверточный слой в лазанье). Е. Г. если вы добавите 2 строк/столбцов из нулей вокруг изображения, размер выхода будет (28+4)-4=28. Таким образом, в случае заполнения размер вывода
input_size + 2*padding - (filter_size -1)
. - если вы явно хотите уменьшить изображение во время свертки, вы можете определить шаг, например
stride=2
, что означает, что вы перемещаете фильтр с шагом в 2 пикселя. Тогда выражение становится((input_size + 2*padding - filter_size)/stride) +1
.
в вашем случае полные вычисления:
# name size parameters
--- -------- ------------------------- ------------------------
0 input 1x28x28 0
1 conv2d1 (28-(5-1))=24 -> 32x24x24 (5*5*1+1)*32 = 832
2 maxpool1 32x12x12 0
3 conv2d2 (12-(3-1))=10 -> 32x10x10 (3*3*32+1)*32 = 9'248
4 maxpool2 32x5x5 0
5 dense 256 (32*5*5+1)*256 = 205'056
6 output 10 (256+1)*10 = 2'570
таким образом, в вашей сети у вас есть в общей сложности 832 + 9'248 + 205'056 + 2'570 = 217'706 изучаемые параметры, о которых сообщает Lasagne.
построение поверх превосходного ответа @hbaderts, просто придумал некоторую формулу для Сети I-C-P-C-P-H-O (так как я работал над аналогичной проблемой), разделяя его на рисунке ниже, может быть полезно.
кроме того, (1) сверточный слой с шагом 2x2 и (2) сверточный слой 1x1 stride + (max/avg) объединяются с шагом 2x2, каждый вносит одинаковое количество параметров с "одинаковым" заполнением, как видно ниже: