Google Maps больше не является бесплатным. Вам необходимо связать кредитную карту, чтобы вы могли получать счет, если на вашем сайте есть запросы, которые превышают 200 долларов США, которые они дают вам ежемесячно бесплатно. Вот почему вы получаете карты с водяными знаками.
Для получения дополнительной информации см.: https://cloud.google.com/maps-platform/pricing/
Я приведу пример, чтобы сделать его более ясным:
x
: входное изображение формы [2, 3], 1 канал valid_pad
: max pool с ядром 2x2, шагом 2 и VALID. same_pad
: максимальный пул с ядром 2x2, шаг 2 и SAME padding (это классический способ пойти) Формы вывода:
valid_pad
: здесь нет прокладки, поэтому форма вывода [1, 1] same_pad
: здесь , мы вставляем изображение в форму [2, 4] (с помощью -inf
, а затем применяем максимальный пул), поэтому форма вывода [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.]
< ч> Основываясь на объяснении здесь и следуя ответам Тристана, я обычно использую эти быстрые функции для проверок работоспособности.
# 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')
Существует три варианта заполнения: действительный (без заполнения), тот же (или наполовину), полный. Вы можете найти объяснения (в 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. Длина вывода равна ((длина ввода) + (k-1)), если s = 1.
Следовательно, количество прокладок: (valid) & lt; = (same) & lt; = (полный)
VALID padding: это с нулевым заполнением. Надеюсь, нет путаницы.
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)
SAME padding: Это очень сложно понять в первую очередь, потому что мы должны рассмотреть два условия отдельно, как указано в официальных документах .
Возьмем ввод как [/g1], выведите его как [/g2], добавьте в качестве [/g3], шаг как [/g4] и ядро размер как [/g5]. (сингл dimentina считается)
Случай 01: [/g6]: [/g7]
Дело 02: [/g8]: [/g9]
[/g10] рассчитано su, что минимальное значение, которое можно принять для заполнения. Поскольку значение [/g11] известно, значение [/g12] можно найти, используя этот формуляр [/g13].
Давайте рассмотрим этот пример:
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):
[/g14]
Если выполняется вертикальное направление (4):
[/g15]
Надеюсь, это поможет понять, как на самом деле SAME работает в TF.
Включение / выключение. Определяет эффективный размер вашего ввода.
VALID:
Нет отступов. Операции свертки и т. Д. Выполняются только в местах, которые являются «действительными», то есть не слишком близки к границам вашего тензора. SAME:
Предусмотрено заполнение. Всякий раз, когда ваша операция ссылается на окрестности (независимо от того, насколько она велика), нулевые значения предоставляются, когда эта окрестность простирается за пределы исходного тензора, чтобы эта операция могла работать и на граничных значениях. С ядром 3x3 и изображением 10x10 вы выполняете свертку на всей области 10x10.
Если вам нравится искусство ascii:
"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
|________________|
|_________________|
|________________|
В этом примере:
Примечания:
"VALID"
только когда-либо удаляет самые правые столбцы (или нижние строки). "SAME"
пытается для равномерного выравнивания влево и вправо, но если количество столбцов, которые нужно добавить, нечетно, оно добавит лишний столбец вправо, как в случае в этом примере (одна и та же логика применяется по вертикали: может быть дополнительная строка нули внизу). Когда stride
равно 1 (более типичное с сверткой, чем объединение), мы можем думать о следующем различии:
"SAME"
: размер вывода совпадает с размером ввода. Для этого требуется, чтобы окно фильтра проскальзывало внешнюю карту ввода, следовательно, необходимо проложить. "VALID"
: окно фильтра остается в допустимой позиции внутри карты ввода, поэтому размер вывода уменьшается на filter_size - 1
. Не выполняется прокладка. Пример TensorFlow Convolution дает обзор различий между 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-мерную матрицу окружающего пространства с этими константами. В n-dim вы окружаете свой n-мерный гиперкуб с константой. В большинстве случаев эта константа равна нулю и называется нулевым дополнением.
Ниже приведен пример нулевого заполнения с p=1
, примененного к 2-му тензору:
Вы можете использовать произвольное заполнение для вашего ядра, но некоторые из дополнительных значений используются чаще, чем другие:
k
k
это дополнение равно k - 1
. Чтобы использовать произвольное дополнение в TF, вы можете использовать tf.pad()
Краткое пояснение
VALID
: не применяйте никаких дополнений, т. е. допускайте, чтобы все размеры были действительными, чтобы входное изображение полностью покрывалось фильтром и шагом, указанным вами.
SAME
: Применить заполнение для ввода (если необходимо), чтобы входное изображение полностью покрывалось фильтром и шагом, указанным вами. Для шага 1 это гарантирует, что размер выходного изображения будет таким же, как и вход.
Примечания
SAME
(т. Е. В режиме автонастройки) Tensorflow будет пытаться равномерно распределять отступы как слева, так и справа. VALID
(т. Е. Без дополнительного режима) Tensorflow будет падать вправо и / или нижние ячейки, если ваш фильтр и шаг не будут полностью заполнены. Я цитирую этот ответ из официальных документов тензорного потока https://www.tensorflow.org/api_guides/python/nn#Convolution . Для дополнения «SAME» выведены высота и ширина вывода как:
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
Для заполнения «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]))
, а значения заполнения всегда равны нулю.