Buscar..


Introducción

La convolución 2D se calcula de una manera similar a la que se calcularía la convolución 1D : desliza el núcleo sobre la entrada, calcula las multiplicaciones de elementos y las suma. Pero en lugar de que su núcleo / entrada sea una matriz, aquí están las matrices.

Sin relleno, zancadas = 1

Este es el ejemplo más básico, con los cálculos más fáciles. Supongamos que su input y el kernel son: introduzca la descripción de la imagen aquí

Cuando tu kernel recibas la siguiente salida: introduzca la descripción de la imagen aquí , que se calcula de la siguiente manera:

  • 14 = 4 * 1 + 3 * 0 + 1 * 1 + 2 * 2 + 1 * 1 + 0 * 0 + 1 * 0 + 2 * 0 + 4 * 1
  • 6 = 3 * 1 + 1 * 0 + 0 * 1 + 1 * 2 + 0 * 1 + 1 * 0 + 2 * 0 + 4 * 0 + 1 * 1
  • 6 = 2 * 1 + 1 * 0 + 0 * 1 + 1 * 2 + 2 * 1 + 4 * 0 + 3 * 0 + 1 * 0 + 0 * 1
  • 12 = 1 * 1 + 0 * 0 + 1 * 1 + 2 * 2 + 4 * 1 + 1 * 0 + 1 * 0 + 0 * 0 + 2 * 1

La función conv2d de TF calcula las convoluciones en lotes y utiliza un formato ligeramente diferente. Para una entrada es [batch, in_height, in_width, in_channels] para el núcleo es [filter_height, filter_width, in_channels, out_channels] . Así que necesitamos proporcionar los datos en el formato correcto:

import tensorflow as tf
k = tf.constant([
    [1, 0, 1],
    [2, 1, 0],
    [0, 0, 1]
], dtype=tf.float32, name='k')
i = tf.constant([
    [4, 3, 1, 0],
    [2, 1, 0, 1],
    [1, 2, 4, 1],
    [3, 1, 0, 2]
], dtype=tf.float32, name='i')
kernel = tf.reshape(k, [3, 3, 1, 1], name='kernel')
image  = tf.reshape(i, [1, 4, 4, 1], name='image')

Posteriormente se calcula la convolución con:

res = tf.squeeze(tf.nn.conv2d(image, kernel, [1, 1, 1, 1], "VALID"))
# VALID means no padding
with tf.Session() as sess:
   print sess.run(res)

Y será equivalente al que calculamos a mano.

Un poco de relleno, zancadas = 1

El relleno es solo un nombre elegante de narración: rodee su matriz de entrada con alguna constante. En la mayoría de los casos, la constante es cero y esta es la razón por la que las personas lo llaman "cero relleno". Entonces, si desea usar un relleno de 1 en nuestra entrada original (verifique el primer ejemplo con padding=0, strides=1 ), la matriz se verá así:

introduzca la descripción de la imagen aquí

Para calcular los valores de la convolución se hace el mismo deslizamiento. Tenga en cuenta que, en nuestro caso, no es necesario volver a calcular muchos valores en el medio (serán los mismos que en el ejemplo anterior. Tampoco mostraré todos los cálculos aquí, porque la idea es sencilla. El resultado es:

introduzca la descripción de la imagen aquí

dónde

  • 5 = 0 * 1 + 0 * 0 + 0 * 1 + 0 * 2 + 4 * 1 + 3 * 0 + 0 * 0 + 0 * 1 + 1 * 1
  • ...
  • 6 = 4 * 1 + 1 * 0 + 0 * 1 + 0 * 2 + 2 * 1 + 0 * 0 + 0 * 0 + 0 * 0 + 0 * 1

TF no admite un relleno arbitrario en la función conv2d , por lo que si necesita un relleno no compatible, utilice tf.pad () . Afortunadamente para nuestra entrada, el relleno 'SAME' será igual a padding = 1. Por lo tanto, no tenemos que cambiar casi nada en nuestro ejemplo anterior:

res = tf.squeeze(tf.nn.conv2d(image, kernel, [1, 1, 1, 1], "SAME"))
# 'SAME' makes sure that our output has the same size as input and 
# uses appropriate padding. In our case it is 1.
with tf.Session() as sess:
   print sess.run(res)

Puede verificar que la respuesta sea la misma que la calculada a mano.

Relleno y zancadas (el caso más general)

Ahora aplicaremos una convolución de pasos a nuestro ejemplo rellenado descrito anteriormente y calcularemos la convolución donde p = 1, s = 2

introduzca la descripción de la imagen aquí

Anteriormente, cuando utilizábamos strides = 1 , nuestra ventana deslizante se movía 1 posición, con strides = s se mueve por posiciones s (necesitas calcular s^2 elementos menos. Pero en nuestro caso podemos tomar un atajo y no realizar ninguna acción). cálculos. Como ya calculamos los valores para s = 1 , en nuestro caso solo podemos tomar cada segundo elemento.

Entonces si la solución es caso de s = 1 fue

introduzca la descripción de la imagen aquí

en caso de s = 2 será:

introduzca la descripción de la imagen aquí

Verifique las posiciones de los valores 14, 2, 12, 6 en la matriz anterior. El único cambio que debemos realizar en nuestro código es cambiar los pasos de 1 a 2 para las dimensiones de ancho y alto (2-en, 3-en).

res = tf.squeeze(tf.nn.conv2d(image, kernel, [1, 2, 2, 1], "SAME"))
with tf.Session() as sess:
   print sess.run(res)

Por cierto, no hay nada que nos impida utilizar diferentes zancadas para diferentes dimensiones.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow