Las operaciones de agrupación y convolución deslizan una "ventana" a través del tensor de entrada. Usando tf.nn.conv2d
como ejemplo: Si el tensor de entrada tiene 4 dimensiones:, [batch, height, width, channels]
entonces la convolución opera en una ventana 2D en las height, width
dimensiones.
strides
determina cuánto se desplaza la ventana en cada una de las dimensiones. El uso típico establece el primer (el lote) y el último (la profundidad) zancada en 1.
Usemos un ejemplo muy concreto: ejecutar una convolución 2-d sobre una imagen de entrada en escala de grises de 32x32. Digo escala de grises porque entonces la imagen de entrada tiene profundidad = 1, lo que ayuda a que sea simple. Deja que esa imagen se vea así:
00 01 02 03 04 ...
10 11 12 13 14 ...
20 21 22 23 24 ...
30 31 32 33 34 ...
...
Ejecutemos una ventana de convolución de 2x2 sobre un solo ejemplo (tamaño de lote = 1). Le daremos a la convolución una profundidad de canal de salida de 8.
La entrada a la convolución tiene shape=[1, 32, 32, 1]
.
Si especifica strides=[1,1,1,1]
con padding=SAME
, la salida del filtro será [1, 32, 32, 8].
El filtro primero creará una salida para:
F(00 01
10 11)
Y luego para:
F(01 02
11 12)
y así. Luego pasará a la segunda fila, calculando:
F(10, 11
20, 21)
luego
F(11, 12
21, 22)
Si especifica un paso de [1, 2, 2, 1], no se superpondrán ventanas. Calculará:
F(00, 01
10, 11)
y entonces
F(02, 03
12, 13)
El paso funciona de manera similar para los operadores de agrupación.
Pregunta 2: Por qué los pasos [1, x, y, 1] para convnets
El primero es el lote: por lo general, no desea omitir ejemplos en su lote, o no debería haberlos incluido en primer lugar. :)
El último 1 es la profundidad de la convolución: por lo general, no desea omitir las entradas, por la misma razón.
El operador conv2d es más general, por lo que podría crear convoluciones que deslizan la ventana a lo largo de otras dimensiones, pero ese no es un uso típico en convnets. El uso típico es utilizarlos espacialmente.
Por qué remodelar a -1 -1 es un marcador de posición que dice "ajustar según sea necesario para que coincida con el tamaño necesario para el tensor completo". Es una forma de hacer que el código sea independiente del tamaño del lote de entrada, de modo que pueda cambiar su canalización y no tener que ajustar el tamaño del lote en todas partes del código.