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

Я использую Lasagne для создания 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 question, но ни один из них явно не обобщает расчет.

Если возможно, можно ли обобщить изучаемые параметры для каждого слоя?

Например, сверточный слой: количество фильтров x ширина фильтра x высота фильтра.

Ответ 1

Сначала рассмотрим, как рассчитывается количество обучаемых параметров для каждого отдельного типа вашего слоя, а затем вычисляем количество параметров в вашем примере.

  • Уровень ввода: весь входной слой считывает входное изображение, поэтому нет параметров, которые вы могли бы узнать здесь.
  • Сверточные слои. Рассмотрим сверточный слой, который берет на карте карты функций l и имеет в качестве вывода карты функций k. Размер фильтра n x m. Например, это будет выглядеть так:

    Визуализация сверточного слоя

    Здесь вход имеет l=32 карты функций в качестве входных данных, k=64 - карты функций в качестве вывода, а размер фильтра n=3 x m=3. Важно понимать, что мы не просто имеем фильтр 3x3, а фактически фильтр 3x3x32, так как наш вход имеет 32 измерения. И мы изучаем 64 различных фильтра 3x3x32. Таким образом, общее число весов n*m*k*l. Тогда для каждой карты признаков есть также смещение, поэтому мы имеем общее количество параметров (n*m*l+1)*k.

  • Объединение слоев. Уровни объединения, например. сделайте следующее: "замените 2x2-окрестность максимальным значением". Таким образом, нет никакого параметра, который вы могли бы изучить на уровне объединения.
  • Полностью подключенные слои. В полностью подключенном слое все модули ввода имеют отдельный вес для каждого блока вывода. Для входов n и выходов m количество весов n*m. Кроме того, у вас есть смещение для каждого выхода node, поэтому вы находитесь в параметрах (n+1)*m.
  • Выходной уровень: выходной уровень является нормальным полностью подключенным уровнем, поэтому (n+1)*m параметры, где n - количество входов, а m - количество выходов.

Последняя трудность - это первый полностью связанный слой: мы не знаем размерности ввода этого слоя, поскольку это сверточный слой. Чтобы вычислить его, мы должны начать с размера входного изображения и вычислить размер каждого сверточного слоя. В вашем случае Lasagne уже рассчитывает это для вас и сообщает размеры, которые облегчают нам задачу. Если вам нужно рассчитать размер каждого слоя самостоятельно, это немного сложнее:

  • В простейшем случае (например, ваш пример) размер вывода сверточного слоя равен input_size - (filter_size - 1), в вашем случае: 28 - 4 = 24. Это связано с природой свертки: мы используем, например, 5x5-окрестности для вычисления точки, но две внешние строки и столбцы не имеют 5x5-окрестности, поэтому мы не можем вычислить какой-либо результат для этих точек. Вот почему наш вывод 2 * 2 = 4 строки/столбцы меньше ввода.
  • Если вы не хотите, чтобы результат был меньше, чем вход, можно выполнить нулевое изображение (с параметром pad сверточного слоя в Лазанье). Например. если вы добавите 2 кадра/столбцы нулей вокруг изображения, размер вывода будет (28 + 4) -4 = 28. Поэтому в случае заполнения, размер вывода input_size + 2*padding - (filter_size -1).
  • Если вы явно хотите уменьшить размер изображения во время свертки, вы можете определить шаг, например. stride=2, что означает, что вы перемещаете фильтр с шагом в 2 пикселя. Затем выражение становится еще более сложным.

В вашем случае полные вычисления:

  #  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 обучаемых параметров, что и есть то, что сообщает Лазань.

Ответ 2

на вершине @hbaderts отличный ответ, просто придумал какую-то формулу для сети I-C-P-C-P-H-O (так как я работал над подобной проблемой), может быть полезно использовать ее на рисунке ниже.

введите описание изображения здесь

Кроме того, (1) слой свертки с шагом 2x2 и (2) уровень свертки 1x1 с шагом + (max/avg) с шагом 2x2, каждый из них вносит одинаковое количество параметров с "одинаковым" дополнением, как показано ниже:

введите описание изображения здесь