Quelle est la différence entre 'SAME' et 'VALID' padding dans tf.nn.piscine max de tensorflow?

Quelle est la différence entre' SAME 'et' VALID ' padding dans tf.nn.max_pool de tensorflow?

À mon avis, 'VALID' signifie qu'il n'y aura pas de remplissage zéro en dehors des bords lorsque nous faisons max pool.

Selon un guide de l'arithmétique de convolution pour l'apprentissage en profondeur , Il dit qu'il n'y aura pas de remplissage dans l'opérateur de pool, c'est-à-dire qu'il suffit d'utiliser 'VALID' de tensorflow. Mais quel est le 'même' remplissage de Max pool dans tensorflow?

170
demandé sur Kayathiri 2016-06-07 11:32:16

11 réponses

Je vais donner un exemple pour le rendre plus clair:

  • x: image d'entrée de la forme [2, 3], 1 canal
  • valid_pad: pool max avec noyau 2x2, foulée 2 et remplissage valide.
  • same_pad: pool max avec noyau 2x2, stride 2 et même rembourrage (c'est le classic way to go)

Les formes de sortie sont:

  • valid_pad: ici, pas de remplissage donc la forme de sortie est [1, 1]
  • same_pad: Ici, nous pad l'image à la forme [2, 4] (avec -inf et ensuite, appliquez max pool), de sorte que la forme de sortie est [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.]

98
répondu Olivier Moindrot 2016-06-07 09:22:30

Si vous aimez l'art ascii:

  • "VALID" = sans rembourrage:

       inputs:         1  2  3  4  5  6  7  8  9  10 11 (12 13)
                      |________________|                dropped
                                     |_________________|
    
  • "SAME" = avec zéro remplissage:

                   pad|                                      |pad
       inputs:      0 |1  2  3  4  5  6  7  8  9  10 11 12 13|0  0
                   |________________|
                                  |_________________|
                                                 |________________|
    

Dans cet exemple:

  • largeur d'Entrée = 13
  • Largeur du filtre = 6
  • foulée = 5

Notes:

  • "VALID" ne supprime que les colonnes les plus droites (ou les lignes les plus basses).
  • "SAME" essaie de pad uniformément à gauche et à droite, mais si le nombre de colonnes à ajouter est impair, il ajoutera le colonne supplémentaire à droite, comme c'est le cas dans cet exemple (la même logique s'applique verticalement: il peut y avoir une ligne supplémentaire de zéros en bas).
372
répondu MiniQuark 2016-09-07 13:29:37

Lorsque stride vaut 1 (plus typique de la convolution que de la mise en commun), on peut penser à la distinction suivante:

  • "SAME": la taille de sortie est la même que la taille d'entrée. Cela nécessite que la fenêtre de filtre glisse à l'extérieur de la carte d'entrée, d'où la nécessité de pad.
  • "VALID": la fenêtre de filtre reste à valide position à l'intérieur de la carte d'entrée, donc la taille de sortie diminue de filter_size - 1. Aucun rembourrage ne se produit.
68
répondu YvesgereY 2018-05-06 17:26:18

L'exemple TensorFlow Convolution donne un aperçu de la différence entre SAME et VALID:

  • pour le remplissage SAME, la hauteur et la largeur de sortie sont calculées comme suit:

Out_height = ceil(float(in_height) / float(foulées[1]))

Out_width = ceil(float(in_width) / float(foulées[2]))

Et

  • pour le remplissage VALID, la hauteur et la largeur de sortie sont calculées comme suit:

Out_height = ceil(float(in_height - filter_height + 1) / float(foulées[1]))

Out_width = ceil(float(in_width - filter_width + 1) / float(foulées[2]))

64
répondu RoyaumeIX 2017-12-04 16:45:28

Rembourrage est une opération pour augmenter la taille des données d'entrée. Dans le cas de données à 1 Dimension, il suffit d'ajouter / d'ajouter le tableau avec une constante, dans 2-dim, vous entourez la matrice avec ces constantes. Dans n-dim vous entourez votre hypercube n-dim avec la constante. Dans la plupart des cas, cette constante est nulle et elle s'appelle zero-padding.

Voici un exemple de remplissage zéro avec p=1 appliqué au tenseur 2-d: entrez la description de l'image ici


Vous pouvez utiliser un remplissage arbitraire pour votre noyau mais certaines des valeurs de remplissage sont utilisées plus fréquemment que d'autres:

  • remplissage valide . Le cas le plus simple, signifie pas de rembourrage du tout. Il suffit de laisser vos données les mêmes qu'il était.
  • même rembourrage parfois appelé demi-rembourrage . Il est appelé SAME car pour une convolution avec une foulée = 1, (ou pour la mise en commun), il doit produire une sortie de la même taille que l'entrée. Il est appelé HALF parce que pour un noyau de taille k entrez la description de l'image ici
  • remplissage complet est le remplissage maximum qui n'entraîne pas de convolution sur des éléments simplement rembourrés. Pour un noyau de taille k, ce remplissage est égal à k - 1.

Utiliser arbitraire rembourrage en TF, vous pouvez utiliser tf.pad()

29
répondu Salvador Dali 2017-05-21 22:28:27

Il y a trois choix de remplissage: valide (pas de remplissage), même (ou moitié), plein. Vous pouvez trouver des explications (dans Theano) ici: http://deeplearning.net/software/theano/tutorial/conv_arithmetic.html

  • valide ou pas de remplissage:

Le remplissage valide n'implique pas de remplissage de zéro, donc il ne couvre que l'entrée valide, sans compter les zéros générés artificiellement. La longueur de sortie est ((la longueur d'entrée)-(k-1)) pour la taille du noyau k si la foulée s = 1.

  • même rembourrage ou demi-rembourrage:

Le même remplissage rend la taille des sorties identique à celle des entrées lorsque s = 1. Si s = 1, le nombre de zéros rembourrés est (k-1).

  • plein rembourrage:

Le remplissage complet signifie que le noyau s'exécute sur toutes les entrées, donc aux extrémités, le noyau peut rencontrer la seule entrée et les zéros d'autre. Le nombre de zéros rembourrés est 2 (k-1) si s = 1. La longueur de sortie est ((la longueur de l'entrée) + (k-1)) si s = 1.

Par conséquent, le nombre de remplissages: (valide)

10
répondu Change-the-world 2017-06-13 15:48:49

Explication Rapide

VALID: n'appliquez aucun remplissage, c'est-à-dire, supposons que toutes les dimensions sont valides afin que l'image d'entrée soit entièrement couverte par le filtre et la foulée que vous avez spécifiés.

SAME: Appliquez un remplissage à l'entrée (si nécessaire) afin que l'image d'entrée soit entièrement couverte par le filtre et la foulée que vous avez spécifiés. Pour stride 1, cela garantira que la taille de l'image de sortie est même {[8] } que l'entrée.

Notes

  • cela s'applique également aux couches conv comme couches de piscine max de la même manière
  • le terme " valide "est un peu impropre parce que les choses ne deviennent pas" invalides " si vous laissez tomber une partie de l'image. Parfois, vous pourriez même vouloir cela. Cela aurait probablement dû être appelé NO_PADDING à la place.
  • le terme "même" est également impropre car il n'a de sens que pour la foulée de 1 lorsque la dimension de sortie est la même que la dimension d'entrée. Pour la foulée de 2, Les dimensions de sortie seront la moitié, par exemple. Cela aurait probablement dû être appelé AUTO_PADDING plutôt.
  • dans SAME (c'est-à-dire le mode Auto-pad), Tensorflow va essayer de répartir le rembourrage uniformément à gauche et à droite.
  • dans VALID (c'est-à-dire pas de mode de remplissage), Tensorflow laissera tomber les cellules droite et/ou inférieure si votre filtre et votre foulée ne couvrent pas complètement l'image d'entrée.
9
répondu ShitalShah 2018-09-28 23:27:03

Je cite cette réponse des documents officiels tensorflow https://www.tensorflow.org/api_guides/python/nn#Convolution Pour le' même ' remplissage, la hauteur et la largeur de sortie sont calculées comme suit:

out_height = ceil(float(in_height) / float(strides[1]))
out_width  = ceil(float(in_width) / float(strides[2]))

Et le remplissage en haut et à gauche sont calculés comme:

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

Pour le remplissage 'valide' , la hauteur et la largeur de sortie sont calculées comme suit:

out_height = ceil(float(in_height - filter_height + 1) / float(strides[1]))
out_width  = ceil(float(in_width - filter_width + 1) / float(strides[2]))

Et les valeurs de remplissage sont toujours nulles.

6
répondu Vaibhav Dixit 2017-05-29 12:15:39

Sur la base de l'explication ici {[3] } et en suivant la réponse de Tristan, j'utilise généralement ces fonctions rapides pour les contrôles de santé mentale.

# 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')
4
répondu ahmedhosny 2016-11-11 16:17:14

padding valide: c'est avec un remplissage nul. Espérons qu'il y est pas de confusion.

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: c'est un peu difficile à comprendre en premier lieu parce que nous devons considérer 2 conditions séparément comme mentionné dans les documents officiels.

Prenons entrée , sortie , rembourrage en , la foulée, comme et la taille du noyau comme . (singal dimentina est considéré)

Cas 01: :

Cas 02: :

Est calculé su que le valeur minimale qui peut être prise pour le rembourrage. Puisque la valeur de est connue, la valeur de peut être trouvée en utilisant ce formulaire .

Travaillons sur cet exemple:

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)

Ici la dimension de x est (3,4). Ensuite, si la direction horizontale est prise (3):

Si la direction vertial est prise (4):

J'espère que cela aidera à comprendre comment fonctionne réellement SAME padding dans TF.

1
répondu GPrathap 2018-04-22 07:08:20

Remplissage activé / désactivé. Détermine la taille effective de votre entrée.

VALID: Pas de rembourrage. La Convolution etc. les opérations ne sont effectuées qu'à des endroits "valides", c'est-à-dire pas trop près des frontières de votre tenseur.
avec un noyau de 3x3 et une image de 10x10, vous effectueriez une convolution sur la zone 8x8 à l'intérieur des frontières.

SAME: le Rembourrage est fourni. Chaque fois que votre opération fait référence à un voisinage (quelle que soit sa taille), des valeurs nulles sont fournies lorsque ce voisinage s'étend en dehors du tenseur d'origine pour permettre à cette opération de fonctionner également sur les valeurs de bordure.
avec un noyau de 3x3 et une image de 10x10, vous effectueriez une convolution sur la zone complète de 10x10.

1
répondu Laine Mikael 2018-07-17 14:32:19