Как рассчитать количество параметров для сверточной нейронной сети?

Я использую лазанью для создания 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 x m. Например, это будет выглядеть так:

    Visualization of a convolutional layer

    здесь вход l=32 feature maps в качестве ввода,k=64 feature maps в качестве вывода, а размер фильтра -n=3 x m=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 (так как я работал над аналогичной проблемой), разделяя его на рисунке ниже, может быть полезно.

enter image description here

кроме того, (1) сверточный слой с шагом 2x2 и (2) сверточный слой 1x1 stride + (max/avg) объединяются с шагом 2x2, каждый вносит одинаковое количество параметров с "одинаковым" заполнением, как видно ниже:

enter image description here