Как рассчитываются размеры питчера для линейных слоев? - PullRequest
0 голосов
/ 14 декабря 2018

В учебнике PyTorch построенная сеть имеет вид

Net(
  (conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1))
  (conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
  (fc1): Linear(in_features=400, out_features=120, bias=True)
  (fc2): Linear(in_features=120, out_features=84, bias=True)
  (fc3): Linear(in_features=84, out_features=10, bias=True)
)

и используется для обработки изображений с размерами 1x32x32.Они упоминают, что сеть нельзя использовать с изображениями другого размера.

Два сверточных слоя, кажется, допускают произвольное количество функций, поэтому линейные слои, похоже, связаны с получением 32x32в 10 конечные элементы.

Я не очень понимаю, как там выбираются числа 120 и 84 и почему результат совпадает с входными измерениями.

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

Когда я, например, использую более простую сеть:

Net(
  (conv1): Conv2d(3, 8, kernel_size=(5, 5), stride=(1, 1))
  (conv2): Conv2d(8, 16, kernel_size=(5, 5), stride=(1, 1))
  (fc1): Linear(in_features=400, out_features=3, bias=True)
)

для вводаразмер 3x1200x800, я получаю сообщение об ошибке:

RuntimeError: size mismatch, m1: [1 x 936144], m2: [400 x 3] at /pytorch/aten/src/TH/generic/THTensorMath.cpp:940

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

1 Ответ

0 голосов
/ 15 декабря 2018

Ключевой шаг - между последней сверткой и первым Linear блоком.Conv2d выводит тензор формы [batch_size, n_features_conv, height, width], тогда как Linear ожидает [batch_size, n_features_lin].Чтобы выровнять два, вам нужно «сложить» 3 измерения [n_features_conv, height, width] в одно [n_features_lin].Как следует, должно быть, что n_features_lin == n_features_conv * height * width.В исходном коде эта «укладка» достигается с помощью

x = x.view(-1, self.num_flat_features(x))

, и если вы проверяете num_flat_features, он просто вычисляет этот n_features_conv * height * width продукт.Другими словами, ваш первый конв должен иметь num_flat_features(x) входные функции, где x - тензор, извлеченный из предыдущей свертки.Но нам нужно рассчитать это значение заранее, чтобы мы могли инициализировать сеть в первую очередь ...

Расчет следует из проверки операций по одной.

  1. ввод 32x32
  2. мы делаем свертку 5x5 без заполнения, поэтому мы теряем 2 пикселя с каждой стороны, мы опускаемся до 28x28
  3. мы делаем maxpooling с рецептивным полем 2x2, мы режем каждоеразмер вдвое, вплоть до 14x14
  4. мы делаем еще одну свертку 5x5 без заполнения, мы опускаемся до 10x10
  5. мы делаем еще одну макспуллинг, мы опускаемся до 5x5

и это 5x5, поэтому в уроке вы видите self.fc1 = nn.Linear(16 * 5 * 5, 120).Это n_features_conv * height * width, при запуске с изображения 32x32.Если вы хотите иметь другой размер ввода, вы должны повторить приведенный выше расчет и соответствующим образом настроить свой первый Linear слой.

Для дальнейших операций это просто цепочка умножений матриц (вот что Linear делает).Таким образом, единственное правило состоит в том, что n_features_out предыдущего Linear соответствует n_features_in следующего.Значения 120 и 84 являются совершенно произвольными, хотя они, вероятно, были выбраны автором таким образом, что получающаяся сеть работает хорошо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...