Принцип Spatial Pyramid Pooling (SPP) и реализация кода (Pytorch)

машинное обучение Python PyTorch Нейронные сети

Если вы хотите увидеть формулу напрямую, вы можете перейти кРаздел III 3. Изменение формулы

1. Зачем нужен СПП

Сначала вам нужно знать, зачем вам нужен SPP.

Мы все знаем, что сверточная нейронная сеть (CNN) состоит из сверточный слой и полносвязный слой, Сверточный слой не требует размера входных данных, и единственное, что требует размер данных,Первый полносвязный слой, поэтому в основном все CNN требуют фиксированного размера входных данных, таких как знаменитыйVGGМодель требует, чтобы размер входных данных был(224*224).

Есть две проблемы с фиксированным размером входных данных:

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

2. Вы можете сказать, что можете вырезать картинку, но если вы ее вырежете, то можете потерять важную информацию.

Таким образом, предложение SPP состоит в том, чтобы решить проблему, заключающуюся в том, что размер входного изображения CNN должен быть фиксированным, так что соотношение сторон и размер входного изображения могут быть произвольными.

Во-вторых, принцип SPP

Более конкретные принципы можно найти в оригинальной статье:Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition



Вышеприведенная картинка представляет собой схематическую схему, приведенную в исходном тексте, которую нужно рассматривать снизу вверх:

  • Первый — входной слой (входное изображение), размер которого может быть произвольным
  • Выполните операцию свертки до последнего слоя свертки (рис.conv_5) выход для получения карт признаков слоя, размер которых также произволен
  • Войдите в слой SPP ниже
    • Давайте сначала посмотрим на картинку с 16 маленькими синими сетками слева.conv_5Полученная карта признаков разбита на 16 частей, кроме16X256Цифра 256 указывает на канал, то есть SPP разбит на 16 частей для каждого слоя (не обязательно равный балл, причину можно понять из следующего содержания).
    • То же самое верно для 4 маленьких зеленых сеток посередине и 1 большой фиолетовой сетки справа, то есть карты объектов разделены на4X256и1X256Поделиться

Итак, для чего же нужно разделить карту объектов на несколько равных частей? Мы видим, что имя SPP здесь, это операция объединения, и общий выборMAX Pooling, то есть максимальное объединение выполняется для каждой копии.

Смотрим на картинку выше, через слой SPP карта признаков преобразуется в16X256+4X256+1X256 = 21X256Матрица , может быть разложена в одномерную матрицу, когда она введена в полную связность, т.е.1X10752, поэтому параметры первого полносвязного слоя можно установить равными 10752, что также решает проблему произвольного размера входных данных.

Обратите внимание, что количество частей, разделенных на вышеперечисленные, можно установить самостоятельно, например, мы также можем установить его как3X3и т. д., но общая рекомендация — делить согласно тому, что сказано в статье.

3. Формула СПП

Теория должна быть понята, так как же ее реализовать? Формула расчета, приведенная в статье, будет представлена ​​ниже, но перед этим следует ввести два символа расчета и формулу расчета размера объединенной матрицы:

1. Предварительные знания

Символы округления:

  • ⌊⌋: символ округления вниз ⌊59/60⌋=0, иногда используетсяfloor()выражать

  • ⌈⌉: символ округления вверх ⌈59/60⌉=1, иногда используетсяceil()выражать

Формула расчета размера матрицы после объединения:

  • Без шага:(h+2p-f+1)*(w+2p-f+1)
  • Шаг: ⌊\frac{h+2p-f}{s}+1⌋*⌊\frac{w+2p-f}{s}+1⌋

2. Формула

Предположение

  • Размер входных данных(c, h_{in}, w_{in}), соответственно указать количество каналов, высоту, ширину
  • Количество бассейнов:(n,n)

тогда есть

  • Размер ядра:⌈\frac{h_{in}}{n},\frac{w_{in}}{n}⌉=ceil(\frac{h_{in}}{n},\frac{w_{in}}{n})
  • Размер шага:⌊\frac{h_{in}}{n},\frac{w_{in}}{n}⌋=floor(\frac{h_{in}}{n},\frac{w_{in}}{n})

Мы можем проверить это, предположив, что размер входных данных равен(10, 7, 11), количество бассейнов(2, 2):

Тогда размер ядра(4,6), размер шага(3,5), размер матрицы после объединения действительно2*2.

3. Коррекция формулы

Да, в формулах, приведенных в статье, есть некоторые упущения, мы по-прежнему используем примеры для иллюстрации.

Предполагая, что размер входных данных такой же, как указано выше(10, 7, 11), но сумма объединения изменяется на(4,4):

На данный момент размер ядра(2,3), размер шага(1,2), размер матрицы после объединения действительно6*5←[Простой способ расчета размера матрицы: (7=2+1*5, 11=3+2*4)] вместо4*4.

Так в чем проблема?

Мы игнорируем наличие заполнения (Я не видел формулы для расчета отступов в оригинальной статье, если она была. . . То есть я не прав, напомните пожалуйста, где я это писал, спасибо).

Внимательно посмотрев на предыдущую формулу расчета, мы легко обнаружим, что формула заполнения не указана.После N раз использования SPP полученные результаты не совпадают с ожидаемыми иНайдите разнообразные онлайн-материалы(Хоть это и жалко), формула расчета после добавления отступов сводится к следующему.

K_h = ⌈\frac{h_{in}}{n}⌉=ceil(\frac{h_{in}}{n})
S_h = ⌈\frac{h_{in}}{n}⌉=ceil(\frac{h_{in}}{n})
p_h = ⌊\frac{k_h*n-h_{in}+1}{2}⌋=floor(\frac{k_h*n-h_{in}+1}{2})
h_{new} = 2*p_h +h_{in}


K_w = ⌈\frac{w_{in}}{n}⌉=ceil(\frac{w_{in}}{n})
S_w = ⌈\frac{w_{in}}{n}⌉=ceil(\frac{w_{in}}{n})
p_w = ⌊\frac{k_w*n-w_{in}+1}{2}⌋=floor(\frac{k_w*n-w_{in}+1}{2})
w_{new} = 2*p_w +w_{in}

  • k_h: Указывает высоту ядра
  • S_h: Указывает размер шага в направлении высоты
  • p_h: указывает величину отступа в направлении высоты, которую необходимо умножить на 2.

Обратите внимание, что в расчетных формулах для ядра и размера шага используютсяceil(), то есть округление вверх, в то время как заполнение используетfloor(), который округляется в меньшую сторону.

Теперь проверьте еще раз:
Предполагая, что размер входных данных такой же, как указано выше(10, 7, 11), номер пула(4,4):

Размер ядра(2,3), Размер шага(2,3), поэтому заполнение(1,1).

Используйте формулу для расчета размера матрицы: ⌊\frac{h+2p-f}{s}+1⌋*⌊\frac{w+2p-f}{s}+1⌋, чтобы получить объединенный размер матрицы как:4*4.

В-четвертых, реализация кода (Python)

Здесь я использую среду глубокого обучения PyTorch для создания уровня SPP со следующим кодом:

#coding=utf-8

import math
import torch
import torch.nn.functional as F

# 构建SPP层(空间金字塔池化层)
class SPPLayer(torch.nn.Module):

    def __init__(self, num_levels, pool_type='max_pool'):
        super(SPPLayer, self).__init__()

        self.num_levels = num_levels
        self.pool_type = pool_type

    def forward(self, x):
        num, c, h, w = x.size() # num:样本数量 c:通道数 h:高 w:宽
        for i in range(self.num_levels):
            level = i+1
            kernel_size = (math.ceil(h / level), math.ceil(w / level))
            stride = (math.ceil(h / level), math.ceil(w / level))
            pooling = (math.floor((kernel_size[0]*level-h+1)/2), math.floor((kernel_size[1]*level-w+1)/2))

            # 选择池化方式 
            if self.pool_type == 'max_pool':
                tensor = F.max_pool2d(x, kernel_size=kernel_size, stride=stride, padding=pooling).view(num, -1)
            else:
                tensor = F.avg_pool2d(x, kernel_size=kernel_size, stride=stride, padding=pooling).view(num, -1)

            # 展开、拼接
            if (i == 0):
                x_flatten = tensor.view(num, -1)
            else:
                x_flatten = torch.cat((x_flatten, tensor.view(num, -1)), 1)
        return x_flattenскопировать код

Приведенная выше ссылка на код:sppnet-pytorch

Чтобы исходный автор не удалил код, у меня есть Fork, и доступ к коду также можно получить по следующему адресу:
marsggbo/sppnet-pytorch



MARSGGBO♥Оригинал





2018-3-15