Операции объединения и свертки перемещают «окно» по входному тензору. Использование tf.nn.conv2d
в качестве примера: Если входной тензор имеет 4 измерения:, [batch, height, width, channels]
то свертка работает с 2D-окном в height, width
измерениях.
strides
определяет, насколько окно сдвигается в каждом из измерений. При обычном использовании первый (партия) и последний (глубина) шаг устанавливаются равными 1.
Давайте возьмем очень конкретный пример: выполнение двумерной свертки над входным изображением в оттенках серого 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: почему шаги [1, x, y, 1] для сверток
Первый 1 - это пакет: обычно вы не хотите пропускать примеры в своем пакете, иначе вы не должны были включать их в первую очередь. :)
Последний 1 - это глубина свертки: обычно вы не хотите пропускать ввод по той же причине.
Оператор conv2d является более общим, поэтому вы можете создавать свертки, которые перемещают окно по другим измерениям, но это не типичное использование в свертках. Типичное использование - использовать их в пространстве.
Зачем менять форму на -1 -1 - это заполнитель, который говорит: «При необходимости отрегулируйте, чтобы соответствовать размеру, необходимому для полного тензора». Это способ сделать код независимым от размера входного пакета, чтобы вы могли изменить свой конвейер и не настраивать размер пакета повсюду в коде.
Входы четырехмерные и имеют форму:
[batch_size, image_rows, image_cols, number_of_colors]
Шаги, как правило, определяют перекрытие между операциями применения. В случае conv2d он указывает, каково расстояние между последовательными применениями сверточных фильтров. Значение 1 в определенном измерении означает, что мы применяем оператор к каждой строке / столбцу, значение 2 означает каждую секунду и так далее.
Касательно 1) Значения, которые имеют значение для сверток, - это 2-й и 3-й, и они представляют собой перекрытие при применении сверточных фильтров по строкам и столбцам. Значение [1, 2, 2, 1] говорит, что мы хотим применить фильтры к каждой второй строке и столбцу.
К вопросу 2) Я не знаю технических ограничений (возможно, это требование CuDNN), но обычно люди используют шаги по размерам строк или столбцов. Необязательно делать это сверх размера партии. Не уверен в последнем измерении.
К вопросу 3) Установка -1 для одного из измерений означает «установить значение для первого измерения так, чтобы общее количество элементов в тензоре не изменилось». В нашем случае -1 будет равно batch_size.
источник
Начнем с того, что делает шаг в случае 1-dim.
Предположим, что вы
input = [1, 0, 2, 3, 0, 1, 1]
иkernel = [2, 1, 3]
результат свертки[8, 11, 7, 9, 4]
, который вычисляется путем перемещения вашего ядра по входу, выполнения поэлементного умножения и суммирования всего. Как это :Здесь мы скользим по одному элементу, но ничто не останавливает вас при использовании любого другого числа. Это число - ваш шаг. Вы можете думать об этом как о понижающей дискретизации результата одностадийной свертки, просто взяв каждый s-й результат.
Зная размер ввода i , размер ядра k , шаг s и отступ p, вы можете легко вычислить размер вывода свертки как:
Здесь || Оператор означает работу на потолке. Для слоя объединения s = 1.
N-тусклый корпус.
Знать математику для случая 1-dim, n-dim будет легко, если вы увидите, что каждый dim независим. Таким образом, вы просто сдвигаете каждое измерение отдельно. Вот пример для 2-го . Обратите внимание, что вам не обязательно иметь одинаковый шаг во всех измерениях. Итак, для N-dim input / kernel вы должны предоставить N шагов.
Так что теперь легко ответить на все ваши вопросы:
источник
@dga проделал замечательную работу по объяснению, и я не могу быть достаточно благодарен, насколько это было полезно. Таким же образом я хотел бы поделиться своими выводами о том, как
stride
работает свертка 3D.Согласно документации TensorFlow по conv3d, форма ввода должна быть в следующем порядке:
[batch, in_depth, in_height, in_width, in_channels]
Давайте объясним переменные справа налево на примере. Предполагая, что входная форма
input_shape = [1000,16,112,112,3]
Ниже приводится сводная документация по использованию шага.
Как указано во многих работах, шаги просто означают, на сколько шагов отходит окно или ядро от ближайшего элемента, будь то фрейм данных или пиксель (это, кстати, перефразировано).
Из приведенной выше документации шаг в 3D будет выглядеть так: strides = (1, X , Y , Z , 1).
В документации это подчеркивается
strides[0] = strides[4] = 1
.strides [X] означает, сколько пропусков мы должны сделать в сосредоточенных кадрах. Так, например, если у нас есть 16 кадров, X = 1 означает использовать каждый кадр. X = 2 означает использование каждого второго кадра, и это продолжается и продолжается
strides [y] и strides [z] следуют объяснениям @dga, поэтому я не буду повторять эту часть.
Однако в keras вам нужно только указать кортеж / список из 3 целых чисел, указав шаги свертки по каждому пространственному измерению, где пространственное измерение - это stride [x], strides [y] и strides [z]. strides [0] и strides [4] уже по умолчанию равен 1.
Надеюсь, кому-то это поможет!
источник