[python] Quelle est la différence entre le remplissage 'SAME' et 'VALID' dans tf.nn.max_pool de tensorflow?


4 Answers

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 remplissage nul:

                   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

Remarques:

  • "VALID" ne supprime que les colonnes les plus à droite (ou les lignes les plus basses).
  • "SAME" essaye de faire un pad égal gauche et droite, mais si le nombre de colonnes à ajouter est impair, il ajoutera la colonne supplémentaire à droite, comme c'est le cas dans cet exemple (la même logique s'applique verticalement: il peut y avoir une rangée supplémentaire de zéros en bas).
Question

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

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

Selon un guide sur l'arithmétique par convolution pour l'apprentissage en profondeur , il est dit qu'il n'y aura pas de remplissage dans l'opérateur de la piscine, c'est-à-dire qu'il suffit d'utiliser 'VALID' de tensorflow . Mais qu'est-ce que "SAME" padding de max pool dans tensorflow ?




Rembourrage VALIDE : c'est avec un remplissage nul. J'espère qu'il n'y a 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 rembourrage: 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 l'entrée comme , sortie en tant que , rembourrage comme , fouler comme et la taille du noyau comme . (singal dimentina est considéré)

Cas 01: :

Cas 02: :

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

Mettons au point 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 vertiale est prise (4):

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




Basé sur l'explication here et le suivi de la réponse de Tristan, j'utilise habituellement 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')



Lorsque la stride est 1 (plus typique avec la convolution que 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 tamponner.
  • "VALID" : La fenêtre de filtre reste à une position valide dans la carte d'entrée, donc la taille de sortie rétrécit de filter_size - 1 . Aucun remplissage n'a lieu.



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

  • Rembourrage valide ou non:

Le remplissage valide n'implique aucun remplissage nul, de sorte qu'il ne couvre que l'entrée valide, à l'exclusion des zéros générés artificiellement. La longueur de sortie est ((la longueur de l'entrée) - (k-1)) pour la taille k du noyau si la foulée s = 1.

  • Moitié ou moitié rembourrage:

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

  • Rembourrage complet

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

Par conséquent, le nombre de paddings: (valide) <= (même) <= (complet)




Related