Аргумент "Тензорный поток"
Я пытаюсь понять аргумент strides в tf.nn.avg_pool, tf.nn.max_pool, tf.nn.conv2d.
В документации говорится:
strides: Список целых чисел с длиной >= 4. Шаг раздвижного окна для каждого измерения входного тензора.
Мои вопросы:
- Что представляет собой каждый из целых чисел 4+?
- Почему у них есть шаги [0] = strides [3] = 1 для convnets?
- В в этом примере мы видим
tf.reshape(_X,shape=[-1, 28, 28, 1])
. Почему -1?
К сожалению, примеры в документах для изменения с использованием -1 не слишком хорошо переводятся в этот сценарий.
Ответы
Ответ 1
Объединение и сверточные операции сдвигают "окно" через входной тензор. Используя tf.nn.conv2d
в качестве примера: Если входной тензор имеет 4 измерения: [batch, height, width, channels]
, то свертка работает в 2D окне в измерениях height, width
.
strides
определяет, сколько окон сдвигается в каждом из измерений. Типичное использование задает первый (пакетный) и последний (глубину) шаг равным 1.
Позвольте использовать очень конкретный пример: Запуск 2-й свертки над входным изображением с серой шкалой 32x32. Я говорю оттенки серого, потому что тогда входное изображение имеет глубину = 1, что помогает сохранить его просто. Пусть это изображение выглядит так:
00 01 02 03 04 ...
10 11 12 13 14 ...
20 21 22 23 24 ...
30 31 32 33 34 ...
...
Запустите окно свертки 2x2 по одному примеру (размер партии = 1). Мы дадим свертку глубину выходного канала 8.
Ввод свертки имеет shape=[1, 32, 32, 1]
.
Если вы укажете strides=[1,1,1,1]
с padding=SAME
, то выход фильтра будет [1, 32, 32, 8].
Сначала фильтр создаст выход для:
F(00 01
10 11)
И затем для:
F(01 02
11 12)
и т.д. Затем он переместится во вторую строку, вычисляя:
F(10, 11
20, 21)
затем
F(11, 12
21, 22)
Если вы укажете шаг [1, 2, 2, 1], он не будет перекрывать окна. Он вычислит:
F(00, 01
10, 11)
а затем
F(02, 03
12, 13)
Шаг работает аналогично для операторов объединения.
Вопрос 2: Почему strides [1, x, y, 1] для convnets
Первая 1 - это партия: вы обычно не хотите пропускать примеры в своей партии или не должны были включать их в первую очередь.:)
Последняя 1 - это глубина свертки: по той же причине вы обычно не хотите пропускать входы.
Оператор conv2d более общий, поэтому вы можете создавать свертки, которые перемещают окно по другим измерениям, но это не типичное использование в convnets. Типичное использование - использовать их пространственно.
Зачем перерисовываться до -1 -1 является заполнителем, который говорит "при необходимости отрегулируйте, чтобы соответствовать размеру, необходимому для полного тензора". Это способ сделать код независимым от размера входной партии, так что вы можете изменить свой конвейер и не изменять размер партии в коде.
Ответ 2
Входы 4-мерные и имеют форму: [batch_size, image_rows, image_cols, number_of_colors]
Шаги в общем случае определяют совпадение между применяемыми операциями. В случае conv2d указывается, какое расстояние между последовательными приложениями сверточных фильтров. Значение 1 в определенном измерении означает, что мы применяем оператор в каждой строке /col, значение 2 означает каждую секунду и т.д.
Re 1) Значения, которые имеют значение для сверток, являются вторыми и третьими, и они представляют собой перекрытие при применении сверточных фильтров вдоль строк и столбцов. Значение [1, 2, 2, 1] говорит, что мы хотим применять фильтры для каждой второй строки и столбца.
Re 2) Я не знаю технических ограничений (может быть, требование CuDNN), но обычно люди используют шаги по размерам строк или столбцов. Не обязательно иметь смысл делать это по размеру партии. Не уверен в
последний размер.
Re 3) Установка -1 для одного из средств измерения: "установите значение для первого измерения так, чтобы общее количество элементов в тензоре не изменилось". В нашем случае -1 будет равен batch_size.
Ответ 3
Начнем с того, что делает шаг в одномерном случае.
Предположим, что ваш input = [1, 0, 2, 3, 0, 1, 1]
и kernel = [2, 1, 3]
результат свертки [8, 11, 7, 9, 4]
, который вычисляется путем сдвига вашего ядра над входом, выполнения умножения по элементам и суммирования всего. Как это:
- 8 = 1 * 2 + 0 * 1 + 2 * 3
- 11 = 0 * 2 + 2 * 1 + 3 * 3
- 7 = 2 * 2 + 3 * 1 + 0 * 3
- 9 = 3 * 2 + 0 * 1 + 1 * 3
- 4 = 0 * 2 + 1 * 1 + 1 * 3
Здесь мы перемещаемся по одному элементу, но ничто не останавливает вас, используя любое другое число. Этот номер - ваш шаг. Вы можете думать об этом как о снижении результатов 1-ступенчатой свертки, просто принимая каждый s-й результат.
Зная размер ввода i, размер ядра k, шаг s и дополнение p, вы можете легко вычислить выходной размер свертки как:
![введите описание изображения здесь]()
Здесь || оператор означает работу потолка. Для слоя объединения s = 1.
N-мерный случай.
Зная математику для 1-мерного случая, n-мерный случай прост, если вы увидите, что каждый dim независим. Таким образом, вы просто перемещаете каждый размер отдельно. Ниже приведен пример для 2-го. Обратите внимание, что вам не нужно иметь один и тот же шаг во всех измерениях. Таким образом, для N-dim ввода/ядра вы должны обеспечить N шагов.
Итак, теперь легко ответить на все ваши вопросы:
- Что представляет собой каждый из целых чисел 4+?. conv2d, pool сообщает вам, что этот список представляет собой шаг между каждым измерением. Обратите внимание, что длина списка шагов совпадает с рангом тензора ядра.
- Зачем им делать шаги [0] = strides 3= 1 для convnets?, Первое измерение - размер партии, последний - каналы. Нет смысла пропускать ни пакет, ни канал. Итак, вы делаете их 1. Для ширины/высоты вы можете пропустить что-то и почему они могут быть не 1.
- tf.reshape(_X, shape = [- 1, 28, 28, 1]). Почему -1? tf.reshape, он охватывает вас:
Если одним компонентом формы является специальное значение -1, размер этого измерения вычисляется так, чтобы общий размер оставался постоянным. В частности, форма [-1] выравнивается в 1-D. Не более одной составляющей формы может быть -1.