Codificador automático en TensorFlow con ejemplo
⚡ Resumen inteligente
Los autoencoders comprimen una entrada en una representación interna más pequeña y luego la reconstruyen, aprendiendo las características más importantes sin etiquetas. Este tutorial apila cuatro capas densas en TensorFlow y reconstruye imágenes de caballos de CIFAR-10.

¿Qué es el codificador automático en el aprendizaje profundo?
An Codificador automático es una herramienta para aprender a codificar datos de manera eficiente en un sin supervisión manera. Es un tipo de Red neuronal artificial Esto te ayuda a aprender la representación de conjuntos de datos para la reducción de dimensionalidad, entrenando la red neuronal para que ignore el ruido de la señal. Es una excelente herramienta para recrear una entrada.
En pocas palabras, la máquina toma, por ejemplo, una imagen y puede producir una imagen muy similar. La entrada en este tipo de red neuronal no está etiquetada, lo que significa que la red es capaz de aprender sin supervisión. Más precisamente, la red codifica la entrada para centrarse únicamente en la característica más importante. Esta es una de las razones por las que el autoencoder es popular para la reducción de dimensionalidad. Además, los autoencoders se pueden usar para producir modelos de aprendizaje generativo. Por ejemplo, la red neuronal se puede entrenar con un conjunto de rostros y luego producir nuevos rostros.
¿Cómo funciona el codificador automático TensorFlow?
El propósito de un codificador automático es producir una aproximación de la entrada centrándose sólo en las características esenciales. Quizás pienses por qué no simplemente aprender a copiar y pegar la entrada para producir la salida. De hecho, un codificador automático es un conjunto de restricciones que obligan a la red a aprender nuevas formas de representar los datos, distintas de simplemente copiar la salida.
Un autoencoder típico se define con una entrada, una representación interna y una salida (una aproximación de la entrada). El aprendizaje se produce en las capas asociadas a la representación interna. De hecho, existen dos bloques principales de capas que se asemejan a una red neuronal tradicional. La ligera diferencia radica en que la capa que contiene la salida debe ser igual a la entrada. En el diagrama siguiente, la entrada original se introduce en el primer bloque, denominado codificador. Esta representación interna comprime (reduce) el tamaño de la entrada. En el segundo bloque se lleva a cabo la reconstrucción de la entrada. Esta es la fase de decodificación.

El modelo actualizará los pesos minimizando la función de pérdida. El modelo es penalizado si el resultado de la reconstrucción es diferente de la entrada.
Concretamente, imagina una imagen de 50×50 píxeles (es decir, 2,500 píxeles) y una red neuronal con una sola capa oculta compuesta por cien neuronas. El aprendizaje se realiza sobre un mapa de características veinticinco veces menor que la entrada. Esto significa que la red debe encontrar la manera de reconstruir 2,500 píxeles con tan solo 100 neuronas.
Ejemplo de codificador automático apilado
En este tutorial sobre autoencoders, aprenderá a utilizar un autoencoder apilado. Su arquitectura es similar a la de una red neuronal tradicional. La entrada pasa a una capa oculta para comprimirse (reducir su tamaño) y luego llega a las capas de reconstrucción. El objetivo es generar una imagen de salida lo más parecida posible a la original. El modelo debe aprender a lograrlo bajo ciertas restricciones, es decir, con una dimensión menor.
Actualmente, los autoencoders en aprendizaje profundo se utilizan principalmente para eliminar el ruido de una imagen. Imaginemos una imagen con arañazos; un humano aún puede reconocer el contenido. La idea de un autoencoder para eliminar el ruido es añadir ruido a la imagen para obligar a la red a aprender el patrón subyacente a los datos.
La otra familia útil de autoencoders Aprendizaje profundo es un autoencoder variacional. Este tipo de red puede generar nuevas imágenes. Imagina que entrenas una red con la imagen de un hombre; dicha red puede producir nuevos rostros.
La tabla que aparece a continuación sitúa el autoencoder apilado que se ha creado en este tutorial junto a otras familias que probablemente encontrará, de modo que resulta fácil comparar la restricción que añade cada uno.
| Tipo de autoencoder | Restricción añadida | Uso típico |
|---|---|---|
| Incompleto / apilado | Capa de codificación más estrecha que la entrada | Reducción de dimensionalidad, ex de característicastracdisrupción |
| eliminación de ruido | Ruido añadido a la entrada, objetivo limpio | Limpieza de imágenes y señales |
| Escaso | Penalización sobre el número de unidades activas | Características interpretables basadas en partes |
| variacional | La capa de codificación aprende una distribución de probabilidad. | Generando nuevas muestras |
Cómo construir un codificador automático con TensorFlow
En este tutorial, aprenderá cómo construir un codificador automático apilado para reconstruir una imagen.
Utilizarás el conjunto de datos CIFAR-10, que contiene 60 000 imágenes en color de 32×32 píxeles. El conjunto de datos del autoencoder ya está dividido en 50 000 imágenes para entrenamiento y 10 000 para pruebas. Hay hasta diez clases:
- Avión
- Automobile
- Bird
- Gato
- Ciervo
- Perro
- rana
- caballo
- Enviar
- Camión
Necesitas descargar las imágenes desde el Página del conjunto de datos CIFAR-10 y descomprime el archivo. La carpeta cifar-10-batches-py contiene cinco lotes de datos con 10000 imágenes cada uno en un orden aleatorio.
Antes de construir y entrenar su modelo, debe aplicar algo de procesamiento de datos. Procederá de la siguiente manera:
- Importar los datos
- Convierta los datos a formato blanco y negro.
- Agregar todos los lotes
- Construir el conjunto de datos de entrenamiento
- Construir un visualizador de imágenes.
Nota de versión: El código de este tutorial está dirigido a TensorFlow 1.x. En TensorFlow 2, el módulo tf.contrib ya no existe, y los marcadores de posición, las sesiones y el iterador inicializable se encuentran en tf.compat.v1. La forma más rápida de ejecutar los listados sin cambios es llamar a tf.compat.v1.disable_v2_behavior() después de la importación.
Preprocesamiento de imágenes
Paso 1) Importar los datos
Según el sitio web oficial, puedes cargar los datos con el siguiente código. El código del autoencoder cargará los datos en un diccionario que contiene los datos y la etiqueta. Ten en cuenta que el código es una función.
import numpy as np import tensorflow as tf import pickle def unpickle(file): import pickle with open(file, 'rb') as fo: dict = pickle.load(fo, encoding='latin1') return dict
Paso 2) Convertir los datos a formato blanco y negro
Para simplificar, convertirá los datos a escala de grises. Es decir, con una sola dimensión frente a tres para la imagen de colores. La mayor parte de las redes neuronales funcionan solo con una entrada de dimensión.
def grayscale(im): return im.reshape(im.shape[0], 3, 32, 32).mean(1).reshape(im.shape[0], -1)
Paso 3) Agregue todos los lotes
Ahora que ambas funciones están creadas y el conjunto de datos cargado, puedes escribir un bucle para agregar los datos a la memoria. Si te fijas bien, el archivo descomprimido con los datos se llama data_batch_ y va numerado del 1 al 5. Puedes recorrer los archivos y agregarlos a data.
Una vez completado este paso, se convierten los datos de color a formato de escala de grises. Como se puede observar, la forma de los datos es de 50000 x 1024. Los píxeles de 32 x 32 se han aplanado a 1024.
# Load the data into memory data, labels = [], [] ## Loop over the b for i in range(1, 6): filename = './cifar-10-batches-py/data_batch_' + str(i) open_data = unpickle(filename) if len(data) > 0: data = np.vstack((data, open_data['data'])) labels = np.hstack((labels, open_data['labels'])) else: data = open_data['data'] labels = open_data['labels'] data = grayscale(data) x = np.matrix(data) y = np.array(labels) print(x.shape) (50000, 1024)
Nota: Cambie './cifar-10-batches-py/data_batch_' por la ubicación real de su archivo. Por ejemplo, para un Windows máquina, la ruta podría ser filename = 'E:\cifar-10-batches-py\data_batch_' + str(i)
Paso 4) Construya el conjunto de datos de entrenamiento
Para que el entrenamiento sea más rápido y sencillo, entrenarás un modelo únicamente con imágenes de caballos. Los caballos llevan la etiqueta 7 en los datos de etiquetas. Como se menciona en la documentación del conjunto de datos CIFAR-10, cada clase contiene 5000 imágenes. Puedes imprimir la forma de los datos para confirmar que hay 5,000 imágenes con 1024 columnas, como se muestra en el siguiente ejemplo de TensorFlow Autoencoder.
horse_i = np.where(y == 7)[0]
horse_x = x[horse_i]
print(np.shape(horse_x))
(5000, 1024)
Paso 5) Construya un visualizador de imágenes
Finalmente, construyes una función para trazar las imágenes. Necesitará esta función para imprimir la imagen reconstruida desde el codificador automático.
Una forma sencilla de imprimir imágenes es usar la función imshow() de la biblioteca Matplotlib. Ten en cuenta que debes convertir la forma de los datos de 1024 a 32x32 (es decir, al formato de una imagen).
# To plot pretty figures %matplotlib inline import matplotlib import matplotlib.pyplot as plt def plot_image(image, shape=[32, 32], cmap = "Greys_r"): plt.imshow(image.reshape(shape), cmap=cmap,interpolation="nearest") plt.axis("off")
La función toma 3 argumentos:
- Imagen: la entrada
- Forma: lista, la dimensión de la imagen
- Mapa de colores: elige el mapa de colores. Por defecto, gris.
Puede intentar trazar la primera imagen del conjunto de datos. Deberías ver a un hombre a caballo.
plot_image(horse_x[1], shape=[32, 32], cmap = "Greys_r")
La llamada devuelve la miniatura en escala de grises que se muestra a continuación y confirma que el redimensionamiento de 1024 valores a una imagen de 32×32 es correcto.
Establecer estimador de conjunto de datos
Muy bien, ahora que el conjunto de datos está listo para usarse, puedes empezar a usar TensorFlow. Antes de construir el modelo, usa el estimador de conjunto de datos de TensorFlow para alimentar la red.
Construirás un conjunto de datos con el estimador TensorFlow. Para refrescar tu mente, necesitas usar:
- from_tensor_slices
- repetir
- lote
El código completo para construir el conjunto de datos es:
dataset = tf.data.Dataset.from_tensor_slices(x).repeat().batch(batch_size)
Tenga en cuenta que x es un marcador de posición con forma [None,n_inputs]. La primera dimensión se establece en None porque el número de imágenes alimentadas a la red es igual al tamaño del lote, que solo se decide en tiempo de ejecución. Para obtener más detalles, consulte el tutorial sobre regresión lineal con TensorFlow.
Después de eso, necesitas crear el iterador. Sin esta línea de código, ningún dato pasará por el proceso.
iter = dataset.make_initializable_iterator() # create the iteratorfeatures = iter.get_next()
Ahora que la tubería está lista, puede verificar si la primera imagen es la misma que antes (es decir, un hombre a caballo).
Establece el tamaño del lote en 1 porque solo quieres procesar una imagen a la vez. Puedes ver la dimensión de los datos con print(sess.run(features).shape). Es igual a (1, 1024). El 1 significa que se procesa una sola imagen de 1024 valores cada vez. Si el tamaño del lote se establece en dos, se procesarán dos imágenes. No cambies el tamaño del lote, de lo contrario se producirá un error, ya que solo se puede procesar una imagen a la vez con la función plot_image().
## Parameters n_inputs = 32 * 32 BATCH_SIZE = 1 batch_size = tf.placeholder(tf.int64) # using a placeholder x = tf.placeholder(tf.float32, shape=[None,n_inputs]) ## Dataset dataset = tf.data.Dataset.from_tensor_slices(x).repeat().batch(batch_size) iter = dataset.make_initializable_iterator() # create the iterator features = iter.get_next() ## Print the image with tf.Session() as sess: # feed the placeholder with data sess.run(iter.initializer, feed_dict={x: horse_x, batch_size: BATCH_SIZE}) print(sess.run(features).shape) plot_image(sess.run(features), shape=[32, 32], cmap = "Greys_r") (1, 1024)
El proceso devuelve el mismo elemento que se generó directamente a partir de la matriz NumPy, lo que demuestra que el marcador de posición, el iterador y el tamaño del lote están conectados correctamente.
Construye la red
Es hora de construir la red. Entrenarás un codificador automático apilado, es decir, una red con múltiples capas ocultas.
Tu red tendrá una capa de entrada con 1024 puntos, es decir, 32×32, la forma de la imagen.
El bloque codificador tendrá una capa oculta superior con 300 neuronas y una capa central con 150 neuronas. El bloque decodificador es simétrico al codificador. Puede visualizar la red en el diagrama a continuación. Tenga en cuenta que puede modificar los valores de las capas oculta y central.
Crear un codificador automático es muy similar a cualquier otro modelo de aprendizaje profundo.
Construirás el modelo siguiendo estos pasos:
- Definir los parámetros
- Definir las capas
- Definir la arquitectura
- Definir la optimización
- Ejecute el modelo
- Evaluar el modelo
En la sección anterior, aprendiste a crear una canalización para alimentar el modelo, por lo que no es necesario crear el conjunto de datos nuevamente. Construirás un autoencoder con cuatro capas. Utilizarás la inicialización de Xavier. Esta técnica establece los pesos iniciales según la varianza tanto de la entrada como de la salida. Finalmente, utilizarás la función de activación ELU. Regularizarás la función de pérdida con un regularizador L2.
Paso 1) Definir los parámetros
El primer paso implica definir el número de neuronas en cada capa, la tasa de aprendizaje y el hiperparámetro del regularizador.
Antes de eso, importa la función parcial. Es un método mejor para definir los parámetros de las capas densas. El código a continuación define los valores de la arquitectura del autoencoder. Como se mencionó anteriormente, el codificador tiene dos capas, con 300 neuronas en la primera capa y 150 en la segunda. Sus valores se almacenan en n_hidden_1 y n_hidden_2.
Debes definir la tasa de aprendizaje y el hiperparámetro L2. Los valores se almacenan en learning_rate y l2_reg.
from functools import partial ## Encoder n_hidden_1 = 300 n_hidden_2 = 150 # codings ## Decoder n_hidden_3 = n_hidden_1 n_outputs = n_inputs learning_rate = 0.01 l2_reg = 0.0001
La técnica de inicialización de Xavier se llama con el objeto xavier_initializer del estimador contrib. En el mismo estimador, puede agregar el regularizador con l2_regularizer.
## Define the Xavier initialization xav_init = tf.contrib.layers.xavier_initializer() ## Define the L2 regularizer l2_regularizer = tf.contrib.layers.l2_regularizer(l2_reg)
Nota de versión: tf.contrib se eliminó en TensorFlow 2. Los reemplazos directos son tf.keras.initializers.GlorotUniform() para xavier_initializer() y tf.keras.regularizers.l2() para l2_regularizer().
Paso 2) Definir las capas
Se han configurado todos los parámetros de las capas densas; puede empaquetar todo en la variable dense_layer utilizando el objeto partial. dense_layer utiliza la activación ELU, la inicialización de Xavier y la regularización L2 en cada llamada.
## Create the dense layer
dense_layer = partial(tf.layers.dense,
activation=tf.nn.elu,
kernel_initializer=xav_init,
kernel_regularizer=l2_regularizer)
Paso 3) Definir la arquitectura
Si observas el diagrama de la arquitectura, notarás que la red apila tres capas con una capa de salida. En el código siguiente, conectas las capas correspondientes. Por ejemplo, la primera capa calcula el producto escalar entre las características de la matriz de entrada y la matriz que contiene los 300 pesos. Una vez calculado el producto escalar, la salida se aplica a la función de activación ELU. Esta salida se convierte en la entrada de la siguiente capa, por lo que se utiliza para calcular hidden_2, y así sucesivamente. La multiplicación de matrices es la misma para cada capa porque se utiliza la misma función de activación. Ten en cuenta que la última capa, outputs, no aplica ninguna función de activación. Esto tiene sentido, ya que se trata de la entrada reconstruida.
## Make the mat mul hidden_1 = dense_layer(features, n_hidden_1) hidden_2 = dense_layer(hidden_1, n_hidden_2) hidden_3 = dense_layer(hidden_2, n_hidden_3) outputs = dense_layer(hidden_3, n_outputs, activation=None)
Paso 4) Definir la optimización
El último paso es construir el optimizador. Se utiliza el error cuadrático medio (MSE) como función de pérdida. Si recuerdas el tutorial sobre regresión lineal, sabrás que el MSE se calcula con la diferencia entre la salida predicha y la etiqueta real. En este caso, la etiqueta es la característica, ya que el modelo intenta reconstruir la entrada. Por lo tanto, se busca la media de la suma de las diferencias al cuadrado entre la salida predicha y la entrada. Con TensorFlow, puedes codificar la función de pérdida de la siguiente manera:
loss = tf.reduce_mean(tf.square(outputs - features))
A continuación, debes optimizar la función de pérdida. Para ello, utilizas el optimizador Adam para calcular los gradientes. La función objetivo es minimizar la pérdida.
## Optimize
loss = tf.reduce_mean(tf.square(outputs - features))
optimizer = tf.train.AdamOptimizer(learning_rate)
train = optimizer.minimize(loss)
Una configuración más antes de entrenar el modelo. Desea utilizar un tamaño de lote de 150, es decir, alimentar la canalización con 150 imágenes en cada iteración. Debe calcular el número de iteraciones manualmente. Esto es trivial de hacer:
Si quieres pasar 150 imágenes cada vez y sabes que hay 5000 imágenes en el conjunto de datos, el número de iteraciones es igual a 5000 dividido por 150. Python Puedes ejecutar los siguientes códigos y asegurarte de que el resultado sea 33:
BATCH_SIZE = 150 ### Number of batches : length dataset / batch size n_batches = horse_x.shape[0] // BATCH_SIZE print(n_batches) 33
Paso 5) Ejecutar el modelo
Por último, pero no menos importante, entrena el modelo. Lo entrenarás durante 100 épocas. Es decir, el modelo verá las imágenes 100 veces mientras optimiza los pesos.
Ya estás familiarizado con los códigos para entrenar un modelo en TensorFlow. La pequeña diferencia radica en canalizar los datos antes de ejecutar el entrenamiento. De esta forma, el modelo se entrena más rápido.
Le interesa imprimir la pérdida después de diez épocas para ver si el modelo está aprendiendo algo (es decir, la pérdida está disminuyendo). La capacitación dura de 2 a 5 minutos, dependiendo del hardware de su máquina.
## Set params n_epochs = 100 ## Call Saver to save the model and re-use it later during evaluation saver = tf.train.Saver() with tf.Session() as sess: sess.run(tf.global_variables_initializer()) # initialise iterator with train data sess.run(iter.initializer, feed_dict={x: horse_x, batch_size: BATCH_SIZE}) print('Training...') print(sess.run(features).shape) for epoch in range(n_epochs): for iteration in range(n_batches): sess.run(train) if epoch % 10 == 0: loss_train = loss.eval() # not shown print("\r{}".format(epoch), "Train MSE:", loss_train) #saver.save(sess, "./my_model_all_layers.ckpt") save_path = saver.save(sess, "./model.ckpt") print("Model saved in path: %s" % save_path) Training... (150, 1024) 0 Train MSE: 2934.455 10 Train MSE: 1672.676 20 Train MSE: 1514.709 30 Train MSE: 1404.3118 40 Train MSE: 1425.058 50 Train MSE: 1479.0631 60 Train MSE: 1609.5259 70 Train MSE: 1482.3223 80 Train MSE: 1445.7035 90 Train MSE: 1453.8597 Model saved in path: ./model.ckpt
Paso 6) Evaluar el modelo
Ahora que ya tienes tu modelo entrenado, es hora de evaluarlo. Necesitas importar el conjunto de prueba del archivo /cifar-10-batches-py/.
test_data = unpickle('./cifar-10-batches-py/test_batch') test_x = grayscale(test_data['data']) #test_labels = np.array(test_data['labels'])
Nota: Para una Windows máquina, el código se convierte en test_data = unpickle(r”E:\cifar-10-batches-py\test_batch”)
Puedes intentar imprimir la imagen 13, que es un caballo.
plot_image(test_x[13], shape=[32, 32], cmap = "Greys_r")
El gráfico confirma que el lote de prueba se cargó correctamente y que la imagen 13 pertenece a la clase con la que se entrenó el modelo.
Para evaluar el modelo, utilizarás el valor de píxel de esta imagen y comprobarás si el codificador puede reconstruir la misma imagen tras reducirla a 1024 píxeles. Ten en cuenta que debes definir una función para evaluar el modelo con diferentes imágenes. El modelo debería funcionar mejor solo con caballos.
La función toma dos argumentos:
- df: Importar los datos de prueba
- image_number: indica qué imagen importar
La función se divide en tres partes:
- Cambie la forma de la imagen a la dimensión correcta, es decir, 1, 1024
- Alimente el modelo con la imagen invisible, codifique/decodifique la imagen
- Imprime la imagen real y reconstruida.
def reconstruct_image(df, image_number = 1): ## Part 1: Reshape the image to the correct dimension i.e 1, 1024 x_test = df[image_number] x_test_1 = x_test.reshape((1, 32*32)) ## Part 2: Feed the model with the unseen image, encode/decode the image with tf.Session() as sess: sess.run(tf.global_variables_initializer()) sess.run(iter.initializer, feed_dict={x: x_test_1, batch_size: 1}) ## Part 3: Print the real and reconstructed image # Restore variables from disk. saver.restore(sess, "./model.ckpt") print("Model restored.") # Reconstruct image outputs_val = outputs.eval() print(outputs_val.shape) fig = plt.figure() # Plot real ax1 = fig.add_subplot(121) plot_image(x_test_1, shape=[32, 32], cmap = "Greys_r") # Plot estimated ax2 = fig.add_subplot(122) plot_image(outputs_val, shape=[32, 32], cmap = "Greys_r") plt.tight_layout() fig = plt.gcf()
Ahora que la función de evaluación está definida, puede echar un vistazo a la imagen reconstruida número trece.
reconstruct_image(df =test_x, image_number = 13)
INFO:tensorflow:Restoring parameters from ./model.ckpt
Model restored.
(1, 1024)
La figura sitúa la imagen de prueba original a la izquierda y la salida del autoencoder a la derecha, de modo que resulta fácil apreciar la pérdida de detalles finos tras la compresión de 1024 a 150.




