Как работает адаптивный пул в pytorch? - PullRequest
0 голосов
/ 19 декабря 2018

Адаптивный пул - отличная функция, но как она работает?Кажется, что вставка пэдов или сжатие / расширение размеров ядра происходит, как кажется, неуклюже, но довольно произвольно.Документация по pytorch, которую я могу найти, не является более описательной, чем «поместите желаемый размер вывода здесь».Кто-нибудь знает, как это работает, или может указать, где это объясняется?

Какой-то тестовый код на тензоре 1x1x6 (1,2,3,4,5,6) с адаптивным выводом размера 8:

import torch
import torch.nn as nn

class TestNet(nn.Module):
    def __init__(self):
        super(TestNet, self).__init__()
        self.avgpool = nn.AdaptiveAvgPool1d(8)

    def forward(self,x):
        print(x)
        x = self.avgpool(x)
        print(x)
        return x

def test():
    x = torch.Tensor([[[1,2,3,4,5,6]]])
    net = TestNet()
    y = net(x)
    return y

test()

Вывод:

tensor([[[ 1.,  2.,  3.,  4.,  5.,  6.]]])
tensor([[[ 1.0000,  1.5000,  2.5000,  3.0000,  4.0000,  4.5000,  5.5000,
       6.0000]]])

Если зеркальное отображение слева и справа (работает (1,1,2,3,4,5,6,6)), и имеет ядро ​​2, тогда выходы для всех позиций, кроме 4 и 5, имеют смысл, за исключением, конечно, выходных данных неправильного размера.Это также заполнение 3 и 4 внутри?Если это так, он работает с (1,1,2,3,3,4,4,5,6,6), который при использовании ядра размера 2 выдает неправильный размер вывода и также пропускает выход 3,5.Меняется ли размер ядра?

Я что-то упускаю из виду, как это работает?

1 Ответ

0 голосов
/ 26 апреля 2019

Как правило, объединение уменьшает размеры.Если вы хотите увеличить размеры, вы можете посмотреть на интерполяцию .

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

  1. Stride = (input_size//output_size)
  2. Размер ядра = input_size - (output_size-1)*stride
  3. Заполнение = 0

Они работают в обратном порядке по формуле пула .Хотя они DO производят выходные данные нужного размера, их выходные данные не обязательно совпадают с выходными данными адаптивного пула.Вот тестовый фрагмент:

import torch
import torch.nn as nn

in_length = 5
out_length = 3

x = torch.arange(0, in_length).view(1, 1, -1).float()
print(x)

stride = (in_length//out_length)
avg_pool = nn.AvgPool1d(
        stride=stride,
        kernel_size=(in_length-(out_length-1)*stride),
        padding=0,
    )
adaptive_pool = nn.AdaptiveAvgPool1d(out_length)

print(avg_pool.stride, avg_pool.kernel_size)

y_avg = avg_pool(x)
y_ada = adaptive_pool(x)

print(y_avg)
print(y_ada)

Вывод:

tensor([[[0., 1., 2., 3., 4.]]])
(1,) (3,)
tensor([[[1., 2., 3.]]])
tensor([[[0.5000, 2.0000, 3.5000]]])
Error:  1.0

Средние пулы пулов из элементов (0, 1, 2), (1, 2, 3) и (2,3, 4).

Пулы адаптивного пула из элементов (0, 1), (1, 2, 3) и (3, 4).(Немного измените код, чтобы увидеть, что он не объединяется только с (2))

  • Вы можете сказать, что адаптивное объединение пытается уменьшить перекрытие в объединении.
  • Разницу можно уменьшить, используя отступ с count_include_pad=True, но в целом я не думаю, что они могут быть одинаковыми для 2D или выше для всех размеров ввода / вывода.Я хотел бы представить, используя разные отступы для левого / правого.На данный момент это не поддерживается в пулах.
  • С практической точки зрения это не должно иметь большого значения.
  • Проверьте код для фактической реализации.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...