В чем разница между "одинаковым" и "действительным" заполнением в tf.НН.максимальный пул тензорного потока?
В чем разница между "одинаковым" и "действительным" заполнением в tf.nn.max_pool на tensorflow?
на мой взгляд, "действительный" означает, что не будет нулевого заполнения за пределами краев, когда мы делаем максимальный пул.
по данным руководство по арифметике свертки для глубокого обучения, он говорит, что в операторе пула не будет заполнения, т. е. просто используйте 'VALID' of tensorflow.
Но что такое "то же самое" заполнение максимального пула в tensorflow?
11 ответов:
я приведу пример, чтобы было понятнее:
x: входное изображение формы [2, 3], 1 каналvalid_pad: максимальный пул с ядром 2x2, шагом 2 и допустимым заполнением.same_pad: максимальный пул с ядром 2x2, stride 2 и тем же заполнением (это классический путь)выходные формы:
valid_pad: здесь нет заполнения, поэтому выходная форма [1, 1]same_pad: здесь мы помещаем изображение в форму [2, 4] (с-infа затем применить max pool), так что выходная форма [1, 2]
x = tf.constant([[1., 2., 3.], [4., 5., 6.]]) x = tf.reshape(x, [1, 2, 3, 1]) # give a shape accepted by tf.nn.max_pool valid_pad = tf.nn.max_pool(x, [1, 2, 2, 1], [1, 2, 2, 1], padding='VALID') same_pad = tf.nn.max_pool(x, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME') valid_pad.get_shape() == [1, 1, 1, 1] # valid_pad is [5.] same_pad.get_shape() == [1, 1, 2, 1] # same_pad is [5., 6.]
Если вам нравится ascii art:
"VALID"= без подклада:inputs: 1 2 3 4 5 6 7 8 9 10 11 (12 13) |________________| dropped |_________________|
"SAME"= С нулевым заполнением:pad| |pad inputs: 0 |1 2 3 4 5 6 7 8 9 10 11 12 13|0 0 |________________| |_________________| |________________|в этом примере:
- ширина входного сигнала = 13
- ширина фильтра = 6
- Stride = 5
Примечания:
"VALID"только когда-либо отбрасывает самые правые столбцы (или самые нижние строки)."SAME"пытается равномерно расположить слева и справа, но если количество добавляемых столбцов нечетное, он добавит дополнительный столбец справа, как и в этом примере (та же логика применяется вертикально: внизу может быть дополнительная строка нулей).
, когда
strideравно 1 (более типично для свертки, чем для объединения), мы можем думать о следующем различии:
"SAME": выходной размер то же самое как размер входных данных. Это требует, чтобы окно фильтра выскользнуло за пределы входной карты,следовательно, необходимо заполнить."VALID": окно фильтра остается на действительный положение внутри входной карты, поэтому размер вывода уменьшается наfilter_size - 1. Обивка не происходит.
The Свертка Тензорного Потока пример дает обзор о разнице между
SAMEиVALID:
- на
SAMEзаполнение, выходная высота и ширина вычисляются как:out_height = ceil (float (in_height) / float (strides[1]))
out_width = ceil (float (in_width) / float (strides[2]))
и
- на
VALIDзаполнение, вычисляются выходная высота и ширина как:out_height = ceil (float(in_height-filter_height + 1) / float(strides[1]))
out_width = ceil (float (in_width-filter_width + 1) / float(strides[2]))
обивка-это операция по увеличению размера входных данных. В случае одномерных данных вы просто добавляете/добавляете массив с константой, в 2-dim вы окружаете матрицу этими константами. В n-dim вы окружаете свой N-dim гиперкуб константой. В большинстве случаев эта константа равна нулю и называется нулевым заполнением.
вот пример нулевого заполнения с
p=1применяется к 2-d тензору:
вы можете использовать произвольное заполнение для вашего ядра, но некоторые из значений заполнения используются чаще, чем другие:
- допустимое заполнение. Самый простой случай, означает отсутствие обивки вообще. Просто оставьте ваши данные такими же, какими они были.
- та же обивка иногда называют половина обивка. Она называется то же самое потому что для свертки с шагом=1, (или для объединения) он должен производить выход того же размера, что и вход. Она называется пол потому что для ядра размере
k![]()
- полная обивка - это максимальное заполнение, которое не приводит к свертке над просто дополненными элементами. Для ядра размером
k, это дополнение равноk - 1.
чтобы использовать произвольное заполнение в TF, вы можете использовать
tf.pad()
есть три варианта заполнения: действительный (без заполнения), тот же (или половина), полный. Вы можете найти объяснения (в Theano) здесь: http://deeplearning.net/software/theano/tutorial/conv_arithmetic.html
- допустимо или нет заполнение:
допустимое заполнение не включает в себя нулевое заполнение, поэтому оно охватывает только допустимые входные данные, не включая искусственно созданные нули. Длина вывода равна ((длина ввода) - (k-1)) для размера ядра k, если шаг s=1.
- такая же или половинная прокладка:
то же самое заполнение делает размер выходов одинаковым с размером входов, когда s=1. Если s=1, то число дополненных нулей равно (k-1).
- полная обивка:
полное заполнение означает, что ядро работает по всем входам, поэтому на концах ядро может встретить только один вход и нули. Число дополненных нулей равно 2 (k-1), Если s=1. Длина выхода ((the длина входного сигнала) + (k-1)) Если s=1.
таким образом, количество отступов: (действительный)
Краткое Описание
VALID: Не применяйте никаких прокладок, т. е. предположим, что все размеры действительный так что входное изображение полностью покрывается фильтром и шагом, который вы указали.
SAME: примените заполнение к входу (если необходимо), чтобы входное изображение было полностью покрыто фильтром и шагом, который вы указали. Для шага 1 это гарантирует, что размер выходного изображения то же самое как вход.Примечания
- это относится к слоям conv, а также к максимальным слоям пула таким же образом
- термин " действительный "является немного неправильным, потому что вещи не становятся" недействительными", если вы отбрасываете часть изображения. Когда-нибудь ты даже захочешь этого. Это должно было, вероятно, называться
NO_PADDINGвместо.- термин "то же самое" также является неправильным, потому что он имеет смысл только для шага 1, когда выходное измерение совпадает с входным измерение. Например, для шага 2 выходные размеры будут равны половине. Это должно было, вероятно, называться .
- на
SAME(т. е. режим auto-pad), Tensorflow будет пытаться равномерно распределить заполнение как слева, так и справа.- на
VALID(т. е. без режима заполнения), Tensorflow будет падать вправо и/или нижние ячейки, если ваш фильтр и шаг не полностью покрывают входное изображение.
я цитирую этот ответ из официальных документов tensorflow https://www.tensorflow.org/api_guides/python/nn#Convolution Для "того же" заполнения выходные высота и ширина вычисляются как:
out_height = ceil(float(in_height) / float(strides[1])) out_width = ceil(float(in_width) / float(strides[2]))и отступы сверху и слева вычисляются как:
pad_along_height = max((out_height - 1) * strides[1] + filter_height - in_height, 0) pad_along_width = max((out_width - 1) * strides[2] + filter_width - in_width, 0) pad_top = pad_along_height // 2 pad_bottom = pad_along_height - pad_top pad_left = pad_along_width // 2 pad_right = pad_along_width - pad_leftдля "допустимого" заполнения выходные высота и ширина вычисляются как:
out_height = ceil(float(in_height - filter_height + 1) / float(strides[1])) out_width = ceil(float(in_width - filter_width + 1) / float(strides[2]))и значения заполнения всегда равны нулю.
на основе объяснения здесь и после ответа Тристана, я обычно использую эти функции для проверки.
# a function to help us stay clean def getPaddings(pad_along_height,pad_along_width): # if even.. easy.. if pad_along_height%2 == 0: pad_top = pad_along_height / 2 pad_bottom = pad_top # if odd else: pad_top = np.floor( pad_along_height / 2 ) pad_bottom = np.floor( pad_along_height / 2 ) +1 # check if width padding is odd or even # if even.. easy.. if pad_along_width%2 == 0: pad_left = pad_along_width / 2 pad_right= pad_left # if odd else: pad_left = np.floor( pad_along_width / 2 ) pad_right = np.floor( pad_along_width / 2 ) +1 # return pad_top,pad_bottom,pad_left,pad_right # strides [image index, y, x, depth] # padding 'SAME' or 'VALID' # bottom and right sides always get the one additional padded pixel (if padding is odd) def getOutputDim (inputWidth,inputHeight,filterWidth,filterHeight,strides,padding): if padding == 'SAME': out_height = np.ceil(float(inputHeight) / float(strides[1])) out_width = np.ceil(float(inputWidth) / float(strides[2])) # pad_along_height = ((out_height - 1) * strides[1] + filterHeight - inputHeight) pad_along_width = ((out_width - 1) * strides[2] + filterWidth - inputWidth) # # now get padding pad_top,pad_bottom,pad_left,pad_right = getPaddings(pad_along_height,pad_along_width) # print 'output height', out_height print 'output width' , out_width print 'total pad along height' , pad_along_height print 'total pad along width' , pad_along_width print 'pad at top' , pad_top print 'pad at bottom' ,pad_bottom print 'pad at left' , pad_left print 'pad at right' ,pad_right elif padding == 'VALID': out_height = np.ceil(float(inputHeight - filterHeight + 1) / float(strides[1])) out_width = np.ceil(float(inputWidth - filterWidth + 1) / float(strides[2])) # print 'output height', out_height print 'output width' , out_width print 'no padding' # use like so getOutputDim (80,80,4,4,[1,1,1,1],'SAME')
действительный заполнение: это с нулевым заполнением. Надеюсь, что нет никакой путаницы.
x = tf.constant([[1., 2., 3.], [4., 5., 6.],[ 7., 8., 9.], [ 7., 8., 9.]]) x = tf.reshape(x, [1, 4, 3, 1]) valid_pad = tf.nn.max_pool(x, [1, 2, 2, 1], [1, 2, 2, 1], padding='VALID') print (valid_pad.get_shape()) # output-->(1, 2, 1, 1)то же самое дополнение: это довольно сложно понять в первую очередь, потому что мы должны рассмотреть 2 условия отдельно, как указано в официальные документы.
давайте возьмем ввод как
, выход а
, обивка как
, Stride, как
и размер ядра как
. (singal dimentina is считается)
01 случае:
:
корпус 02:
:
рассчитывается su, что минимальное значение, которое может быть принято для заполнения. Так как значение
известно, стоимостью
можно найти с помощью этого формульного
.
давайте рассмотрим этот пример:
x = tf.constant([[1., 2., 3.], [4., 5., 6.],[ 7., 8., 9.], [ 7., 8., 9.]]) x = tf.reshape(x, [1, 4, 3, 1]) same_pad = tf.nn.max_pool(x, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME') print (same_pad.get_shape()) # --> output (1, 2, 2, 1)здесь размерность x равна (3,4). Затем, если принято горизонтальное направление (3):
Если берется вертикальное направление (4):
надеюсь, что это поможет понять, как на самом деле то же самое обивка работает в TF.
прокладка вкл/выкл. Определяет эффективный размер входных данных.
VALID:нет подклада. Свертки и т. д. ОПС проводятся только в местах, которые являются "действительными", т. е. не слишком близко к границам вашего тензора.
С ядром 3x3 и изображением 10x10, вы будете выполнять свертку на области 8x8 внутри границ.
SAME:заполнение осуществляется. Всякий раз, когда ваша операция ссылается на окрестности (независимо от того, насколько большой), нулевые значения предоставляются, когда эта окрестность выходит за пределы исходного тензора, чтобы позволить этой операции работать также на граничных значениях.
С ядром 3x3 и изображением 10x10, вы будете выполнять свертку на всю область 10x10.


Comments