Определение результата операции свертки - PullRequest
1 голос
/ 21 марта 2019

Следуя инструкциям из https://medium.com/mlreview/a-guide-to-receptive-field-arithmetic-for-convolutional-neural-networks-e0f514068807 Я пытаюсь рассчитать количество выходных объектов, используя следующий код:

Вывод:

%reset -f

import torch
import torch.nn as nn

my_tensor = torch.randn((1, 16, 12, 12), requires_grad=False)
print(my_tensor.shape)

update_1 = nn.Conv2d(16, 16, kernel_size=3, stride=2, padding=1)
print(update_1(my_tensor).shape)

:

torch.Size([1, 16, 12, 12])
torch.Size([1, 16, 6, 6])

Как рассчитывается torch.Size([1, 16, 6, 6]) в контексте применения формулы:

enter image description here

(взято из https://medium.com/mlreview/a-guide-to-receptive-field-arithmetic-for-convolutional-neural-networks-e0f514068807)

Попытка вычислить количество выходных объектов вручную по формуле:

stride = 2
padding = 1
kernel_size = 3

# 2304 as n_in = 1 * 16 * 16 * 12

n_out = ((2304 + (2 * padding) - kernel_size) / stride) + 1

print(n_out)

отпечатков: 1152.5

Но полученное количество выходных объектов составляет print(1 * 16 * 6 *6) = 576. IЯ взял продукт 1,16,6,6, так как это форма результата print(update_1(my_tensor).shape)

Обновление:

На основе приведенных ниже вопросов я обновил код для:

%reset -f

import torch
import torch.nn as nn
from math import floor

stride_value = 2
padding_value = 1
kernel_size_value = 3

number_channels = 3
width = 10
height = 12

my_tensor = torch.randn((1, number_channels, width, height), requires_grad=False)
print(my_tensor.shape)

update_1 = nn.Conv2d(in_channels=number_channels, 
                     out_channels=16, 
                     kernel_size=kernel_size_value, 
                     stride=stride_value, 
                     padding=padding_value)

print(update_1(my_tensor).shape)

n_out = floor((number_channels + (2 * padding_value) - kernel_size_value) / stride_value) + 1
print(n_out)

print(my_tensor.shape) производит: torch.Size ([1, 3, 10, 12])

print(update_1(my_tensor).shape) производит: torch.Size ([1, 16, 5,6])

print(update_1(n_out).shape) производит: 2

2 не соответствует количеству выходных объектов в каждом измерении. Правильно ли я выполнил вычисление?

Как числогоризонтВсе производимые объекты равны 5, а количество производимых вертикальных элементов равно 6. Эта формула не применима, если число признаков отличается, поскольку для изображения не имеет смысла иметь различные значения длины оси x и y?

Ответы [ 2 ]

1 голос
/ 21 марта 2019

Я понимаю, откуда вы пришли в замешательство. Формула вычисляет линейное число выходов, в то время как вы предполагаете, что она действует на весь тензор.

Итак, правильный код:

from math import floor

stride = 2
padding = 1
kernel_size = 3

n_out = floor((12 + (2 * padding) - kernel_size) / stride) + 1

print(n_out)

Таким образом, он выводит 6 «горизонтальных» функций. Поскольку входной тензор имеет одинаковый «вертикальный» размер (12), формула также будет производить 6 «вертикальных» признаков. Наконец, 16 - это количество выходных каналов, которые вы указали в Conv2d.

Сложив все вместе, получим

1 image in a batch,
16 channels,
6 horizontal features, and
6 vertical features,

, что в сумме 576 функций.

UPDATE

По соглашению количество выходных каналов не , рассчитанное по формуле, но предоставленное вручную в качестве второго параметра для nn.Conv2d.

Поэтому для исправления второго кода выше:

import torch
import torch.nn as nn
from math import floor

stride_value = 2
padding_value = 1
kernel_size_value = 3

number_channels = 3
width = 10
height = 12

my_tensor = torch.randn((1, number_channels, width, height), requires_grad=False)
print(my_tensor.shape)

update_1 = nn.Conv2d(in_channels=number_channels, 
                     out_channels=16, 
                     kernel_size=kernel_size_value, 
                     stride=stride_value, 
                     padding=padding_value)

print(update_1(my_tensor).shape)

n_out1 = floor((width + (2 * padding_value) - kernel_size_value) / stride_value) + 1
n_out2 = floor((height + (2 * padding_value) - kernel_size_value) / stride_value) + 1
print("(Expected: 5, 6)", n_out1, n_out2)
0 голосов
/ 21 марта 2019

В этой статье есть очень странный, нестандартный способ использования термина «функции». Они действительно относятся к «пикселям» или, в более общем смысле, к размеру карт объектов в каждом измерении.
Ограничивая себя изображениями, формула затем просто вычисляет количество пикселей на размер изображения. Таким образом, в этом случае у нас есть n_in = 12 и n_out = 6 в каждом измерении (таким образом, ввод шириной 12 пикселей дает вывод шириной 6 пикселей), и формула соответствует.

Если мы хотим, чтобы фактическое количество функций в выводе, мы получили бы 16 * 6 * 6.

...