web-dev-qa-db-fra.com

Tensorflow Strides Argument

J'essaie de comprendre l'argument strides dans tf.nn.avg_pool, tf.nn.max_pool, tf.nn.conv2d.

Le documentation dit à plusieurs reprises

foulées: liste des longueurs dont la longueur est> = 4. La foulée de la fenêtre glissante pour chaque dimension du tenseur en entrée.

Mes questions sont:

  1. Que représente chacun des 4+ nombres entiers?
  2. Pourquoi doivent-ils avoir des progrès [0] = des progrès [3] = 1 pour les convnets?
  3. Dans cet exemple nous voyons tf.reshape(_X,shape=[-1, 28, 28, 1]). Pourquoi -1?

Malheureusement, les exemples de la documentation relatifs à la modification de la forme en utilisant -1 ne traduisent pas très bien ce scénario.

110
jfbeltran

Les opérations de mise en commun et de convolution font glisser une "fenêtre" sur le tenseur en entrée. Utilisation de tf.nn.conv2d à titre d'exemple: Si le tenseur d'entrée a 4 dimensions: _[batch, height, width, channels]_, la convolution agit sur une fenêtre 2D des dimensions _height, width_.

strides détermine le décalage de la fenêtre dans chacune des dimensions. L'utilisation typique définit le premier (le lot) et le dernier (la profondeur) foulée à 1.

Prenons un exemple très concret: Exécution d’une convolution 2-D sur une image d’entrée en niveaux de gris 32x32. Je dis niveaux de gris, car alors l'image d'entrée a une profondeur = 1, ce qui permet de rester simple. Laissez cette image ressembler à ceci:

_00 01 02 03 04 ...
10 11 12 13 14 ...
20 21 22 23 24 ...
30 31 32 33 34 ...
...
_

Lançons une fenêtre de convolution 2x2 sur un seul exemple (taille du lot = 1). Nous donnerons à la convolution une profondeur de canal de sortie de 8.

L'entrée dans la convolution a _shape=[1, 32, 32, 1]_.

Si vous spécifiez _strides=[1,1,1,1]_ avec _padding=SAME_, le résultat du filtre sera [1, 32, 32, 8].

Le filtre va d'abord créer une sortie pour:

_F(00 01
  10 11)
_

Et ensuite pour:

_F(01 02
  11 12)
_

etc. Ensuite, il passera à la deuxième ligne en calculant:

_F(10, 11
  20, 21)
_

ensuite

_F(11, 12
  21, 22)
_

Si vous spécifiez une foulée de [1, 2, 2, 1], les fenêtres qui se chevauchent ne sont pas superposées. Il va calculer:

_F(00, 01
  10, 11)
_

puis

_F(02, 03
  12, 13)
_

La foulée fonctionne de la même manière pour les opérateurs de pooling.

Question 2: Pourquoi progresser [1, x, y, 1] pour convnets

Le premier est le lot: vous ne voulez généralement pas ignorer les exemples de votre lot, ou vous n'auriez pas dû les inclure en premier lieu. :)

Le dernier 1 correspond à la profondeur de la convolution: vous ne voulez généralement pas ignorer les entrées, pour la même raison.

L'opérateur conv2d étant plus général, vous pouvez créer des convolutions qui font glisser la fenêtre sur d'autres dimensions, mais ce n'est pas une utilisation typique dans convnets. L'utilisation typique est de les utiliser spatialement.

Pourquoi changer de forme en -1 -1 est un espace réservé qui indique "ajustez si nécessaire pour correspondre à la taille requise pour le tenseur complet". C'est une façon de rendre le code indépendant de la taille du lot en entrée, de sorte que vous puissiez modifier votre pipeline sans avoir à ajuster la taille du lot partout dans le code.

217
dga

Les entrées sont 4 dimensions et sont de forme: [batch_size, image_rows, image_cols, number_of_colors]

En général, Strides définit un chevauchement entre les opérations d’application. Dans le cas de conv2d, il spécifie quelle est la distance entre les applications consécutives de filtres de convolution. La valeur 1 dans une dimension spécifique signifie que nous appliquons l'opérateur à chaque ligne/col, la valeur 2 signifie toutes les secondes, etc.

Re 1) Les valeurs qui importent pour les convolutions sont 2e et 3e et elles représentent le chevauchement dans l'application des filtres de convolution le long des lignes et des colonnes. La valeur de [1, 2, 2, 1] indique que nous voulons appliquer les filtres sur chaque deuxième ligne et chaque colonne.

Re 2) Je ne connais pas les limitations techniques (il peut s'agir d'une exigence de CuDNN), mais en général, les gens utilisent des enjambées le long des dimensions des lignes ou des colonnes. Cela n'a pas nécessairement de sens de le faire sur la taille du lot. Pas sûr de la dernière dimension.

Re 3) Régler -1 pour l'une des dimensions signifie ", définissez la valeur de la première dimension de sorte que le nombre total d'éléments dans le tenseur reste inchangé". Dans notre cas, le -1 sera égal au batch_size.

16
Rafał Józefowicz

Commençons par ce que fait la foulée dans un cas à une dim.

Supposons que vos input = [1, 0, 2, 3, 0, 1, 1] et kernel = [2, 1, 3] le résultat de la convolution est [8, 11, 7, 9, 4], qui est calculé en faisant glisser votre noyau sur l'entrée, en effectuant une multiplication par élément et en sommant tout. comme ça :

  • 8 = 1 * 2 + 0 * 1 + 2 * 3
  • 11 = 0 * 2 + 2 * 1 + 3 * 3
  • 7 = 2 * 2 + 3 * 1 + 0 * 3
  • 9 = 3 * 2 + 0 * 1 + 1 * 3
  • 4 = 0 * 2 + 1 * 1 + 1 * 3

Ici, nous glissons d’un élément à l’autre, mais rien ne vous empêche d’utiliser un autre nombre. Ce nombre est votre foulée. Vous pouvez penser que cela revient à sous-échantillonner le résultat de la convolution à un seul pas en prenant chaque s-ème résultat.

Connaître la taille d'entrée i , taille du noyau k , stride s et le remplissage p vous permet de calculer facilement la taille de sortie de la convolution sous la forme suivante:

enter image description here

Ici || opérateur signifie fonctionnement au plafond. Pour une couche de regroupement, s = 1.


N-dim cas.

Connaissant le calcul pour un cas à 1 dim, le cas n-dim est facile une fois que vous voyez que chaque dim est indépendant. Donc, il vous suffit de faire glisser chaque dimension séparément. Voici un exemple pour 2-d . Notez que vous n'avez pas besoin d'avoir la même foulée à toutes les dimensions. Donc, pour une entrée/noyau N-dim, vous devez fournir N pas.


Alors maintenant, il est facile de répondre à toutes vos questions:

  1. Que représente chacun des 4+ nombres entiers? . conv2d , pool vous indique que cette liste représente les progrès réalisés dans chaque dimension. Notez que la liste des longueurs de pas est la même que celle du rang du tenseur du noyau.
  2. Pourquoi doivent-ils avoir des foulées [0] = foulées = 1 pour les convnets? . La première dimension est la taille du lot, la dernière est celle des canaux. Il ne sert à rien de sauter ni batch ni channel. Donc vous les faites 1. Pour la largeur/hauteur, vous pouvez sauter quelque chose et c'est pourquoi ils pourraient ne pas être 1.
  3. tf.reshape (_X, forme = [- 1, 28, 28, 1]). Pourquoi -1? tf.reshape l’a couvert pour vous:

    Si l'une des composantes de la forme est la valeur spéciale -1, la taille de cette dimension est calculée de sorte que la taille totale reste constante. En particulier, une forme de [-1] s'aplatit en 1-D. Au plus un composant de la forme peut être -1.

10
Salvador Dali

@dga a fait un excellent travail en expliquant et je ne saurais être assez reconnaissant à quel point cela a été utile. De la même manière, j'aimerais partager mes découvertes sur le fonctionnement de stride dans la convolution 3D.

Selon le documentation TensorFlow sur conv3d, la forme de l'entrée doit être dans cet ordre:

[batch, in_depth, in_height, in_width, in_channels]

Expliquons les variables de l'extrême droite à la gauche en utilisant un exemple. En supposant que la forme en entrée est input_shape = [1000,16,112,112,3]

input_shape[4] is the number of colour channels (RGB or whichever format it is extracted in)
input_shape[3] is the width of the image
input_shape[2] is the height of the image
input_shape[1] is the number of frames that have been lumped into 1 complete data
input_shape[0] is the number of lumped frames of images we have.

Vous trouverez ci-dessous une documentation récapitulant l'utilisation de stride.

strides: liste des ints dont la longueur est> = 5. Tenseur 1D de longueur 5. La foulée de la fenêtre glissante pour chaque dimension de l'entrée. Doit avoir strides[0] = strides[4] = 1

Comme indiqué dans de nombreux travaux, les enjambées indiquent simplement le nombre de pas d’une fenêtre ou d’un noyau à l’écart de l’élément le plus proche, qu’il s’agisse d’un bloc de données ou d’un pixel (comme cela a été paraphrasé).

Dans la documentation ci-dessus, une foulée en 3D ressemblera à ceci foulées = (1, X, Y, Z, 1).

La documentation souligne que strides[0] = strides[4] = 1.

strides[0]=1 means that we do not want to skip any data in the batch 
strides[4]=1 means that we do not want to skip in the channel 

strides [X] signifie combien de sauts nous devons faire dans les images groupées. Ainsi, par exemple, si nous avons 16 images, X = 1 signifie utiliser chaque image. X = 2 signifie utiliser chaque seconde et continue encore

strides [y] et strides [z] suivent l'explication de @ dga donc je ne vais pas refaire cette partie.

Toutefois, dans les keras, il vous suffit de spécifier un tuple/liste de 3 entiers, en spécifiant les pas de la convolution le long de chaque dimension spatiale, la dimension spatiale étant stride [x], strides [y] et strides [z]. strides [0] et strides [4] est déjà réglé par défaut sur 1.

J'espère que quelqu'un trouve cela utile!

2
rocksyne