Los Autoencoders (codificadores automáticos) son redes neuronales artificiales capaces de aprender representaciones densas de los datos de entrada, llamados representaciones latentes o codificadores (codings), sin supervisión, es decir entrenamiento no etiquetado. Estos codificadores normalmente tienen mucha menor dimensión que los datos de entrada, haciendo los codificadores útiles para la reducción dimensional, especialmente para propósitos de visualización. También funcionan como detectores de características y se pueden utilizar para preentrenar redes neuronales profundas. Finalmente algunos codificadores sirven como modelos generativos, son capaces de generar aleatoriamente nuevos datos muy similares a los datos de entrenamiento. Por ejemplo, si lo entrenamos con caras humanas, son capaces de generar nuevas aunque normalmente serán borrosas o con características que las hacen irreales.
En contraste, las caras humanas creadas por las Redes Generativas Adversarias (GAN) son bastante convincentes y es difícil cree que la gente que representan no existe. Las GAN´s son utilizadas actualmente para incrementar la resolución de una imagen, colorear imágenes en blanco y negro, hacer potentes ediciones de imágenes y convertir bocetos en fotos realistas etc.
Los codificadores y las GAN son ambos no supervisados, aprenden representaciones densas y son utilizados ambos como modelos generativos, y tienen aplicaciones muy similares sin embargo trabajan de forma muy diferente.
Autoencoders (Codificadores)
Simplemente aprenden a copiar la entrada en la salida. Esto puede sonar bastante trivial, pero veremos cómo algunas limitaciones en la red, lo convertirán en una tarea más bien difícil. Por ejemplo, podemos añadir ruido a una imagen de entrada y entrenar la red para que nos devuelva la imagen original. ,Esta limitaciones impiden que el codificador copie directamente la entrada en la salida y los fuerza a aprender vías eficientes de representación de datos.
GANs
Están compuestas por dos redes neuronales: un generador que intenta generar datos similares a los de entrenamiento de la red y un discriminador, que trata de averiguar si la imagen recibida pertenece a los datos de entrenamiento o ha sido generada por el generador. El generador y el discriminador compiten entre sí durante el entrenamiento. El generador intenta generar imágenes nuevas pero indistinguibles de las del swet de entrenamiento, mientras que el discriminador trata de averiguar si la imagen que procesa pertenece al set de entrenamiento o la ha generado el generador.
Autoencoders
Un autoecoder está siempre compuesto de dos partes: un codificador (o red de reconocimiento) que convierte la entrada en una representación latente, seguido de un decodificador (o red generativa) que convierte la representación interna en salidas. Un autoencoder tiene la misma arquitectura que un perceptrón multicapa (una red neuronal) excepto que el número de neuronas en la capa de salida debe ser igual al número de entradas.
A menudo las salidas, son llamadas reconstrucciones por que el autoencoder trata de reconstruir las entradas, y la función de coste contiene una reconstrucción de pérdida que penaliza el modelo que penaliza el modelo cuando la reconstrucción difiere de la entrada.
Como la representación interna tiene una dimensionalidad inferior que los datos de entrada (por ejemplo contiene una representación en dos dimensiones 2D de un objeto de tres dimensiones 3D) el autoencoder se dice que es incompleto. Un autoencoder incompleto no puede copiar trivialmente sus entradas a los codificadores, antes debe encontrar una vía para trasladar una copia desde las entradas a las salidas, por tanto es forzado a aprender las características más importantes de los datos de entrada y eliminar las que nos son importantes.
A continuación vamos a implementar un autoencoder incompleto muy simple para reducir la dimensionalidad.
Ejecutando PCA (Principal Component Analisis) con un Autoencoder incompleto lineal
Si el autoencoder utiliza solamente activaciones lineales y la función de coste es el error cuadrático medio (MSE). Entonces termina actuando como un PCA.
Un PCA es un algoritmo que identifica el plano óptimo sobre el que representar los datos y proyecta sobre dicho plano el dataset, de modo que se produce una reducción de dimensionalidad con una pérdida mínima de información.
El siguiente código sirve para construir un Autoencoder lineal simple para ejecutar PCA desde un dataset de 3D y proyectarlo sobre un plano 2D.
Lo primero de todo es activar nuestro entorno virtual aislado y abrir un notebook de Jupyter apuntando a nuestro entorno virtual aislado.
Primero, importaremos algunos módulos comunes, y nos aseguramos de que MatplotLib traza las figuras online y prepararemos una función para guardar las imágenes. También verificamos que la versión de Python sea 3.5 o posterior y esté instalado, así como Scikit-Learn ≥0.20 y TensorFlow ≥2.0.
# Se necesita
una versión de Python ≥3.5
import sys
assert sys.version_info >= (3, 5)
# Se require una version de
Scikit-Learn ≥0.20
import sklearn
assert sklearn.__version__ >= "0.20"
try:
# %tensorflow_version solo existe en Colab.
%tensorflow_version 2.x
IS_COLAB = True
except Exception:
IS_COLAB = False
# Se requiere TensorFlow ≥2.0
import tensorflow as tf
from tensorflow import keras
assert tf.__version__ >= "2.0"
if not tf.config.list_physical_devices('GPU'):
print("No se ha
detectado una GPU. LSTMs y CNNs pueden ser muy lentas sin una GPU")
if IS_COLAB:
print("Ir a
Runtime > Change runtime y seleccionar GPU hardware accelerator.")
# Impoeraciones comunes
import numpy as np
import os
# para hacer este cuaderno estable
np.random.seed(42)
tf.random.set_seed(42)
# Para mostrar en pantalla
gráficos
%matplotlib inline
import matplotlib as mpl
import matplotlib.pyplot as plt
mpl.rc('axes', labelsize=14)
mpl.rc('xtick', labelsize=12)
mpl.rc('ytick', labelsize=12)
# Directorio donde se guardarán las imágenes
PROJECT_ROOT_DIR = "."
CHAPTER_ID = "autoencoders"
IMAGES_PATH = os.path.join(PROJECT_ROOT_DIR, "imagenes", CHAPTER_ID)
os.makedirs(IMAGES_PATH, exist_ok=True)
def save_fig(fig_id, tight_layout=True, fig_extension="png", resolution=300):
path = os.path.join(IMAGES_PATH, fig_id + "." + fig_extension)
print("Guardando imagen", fig_id)
if tight_layout:
plt.tight_layout()
plt.savefig(path, format=fig_extension, dpi=resolution)
Implementamos un par de funciones de utilidad para trazar una imagen en escala de grises de 28x28:
def plot_image(image):
plt.imshow(image, cmap="binary")
plt.axis("off")
Creamos un dataset de tres dimensiones
np.random.seed(4)
def generate_3d_data(m, w1=0.1, w2=0.3, noise=0.1):
angles = np.random.rand(m) * 3 * np.pi / 2 - 0.5
data = np.empty((m, 3))
data[:, 0] = np.cos(angles) + np.sin(angles)/2 + noise * np.random.randn(m) / 2
data[:, 1] = np.sin(angles) * 0.7 + noise * np.random.randn(m) / 2
data[:, 2] = data[:, 0] * w1 + data[:, 1] * w2 + noise * np.random.randn(m)
return data
X_train = generate_3d_data(60)
X_train =
X_train - X_train.mean(axis=0,
keepdims=0)
Y creamos el autoencoder
np.random.seed(42)
tf.random.set_seed(42)
encoder = keras.models.Sequential([keras.layers.Dense(2, input_shape=[3])])
decoder = keras.models.Sequential([keras.layers.Dense(3, input_shape=[2])])
autoencoder = keras.models.Sequential([encoder, decoder])
autoencoder.compile(loss="mse",
optimizer=keras.optimizers.SGD(lr=1.5))
Este código en realidad no es muy diferente de cualquier MLP (Perceptrón multicapa) pero tiene algunas diferencias:
Hemos organizado el autoencoder en dos subcomponentes: el codificador y el decodificador. Ambos son modelos de secuencia regular cada uno con una capa densa simple y el autoencoder es un modelo secuencial que contiene el codificador seguido por el decodificador (cada modelo puede ser utilizado como una capa en otro modelo).
El número de salidas del autoencoder es igual al número de entradas, en este caso tres.
Al ejecutar un PCA simple no podemos usar ninguna función de activación, es decir, todas las neuronas tienen activación lineal, y la función de coste es el error cuadrático medio.
Vamos a entrenar el modelo con un dataset 3D simple y lo vamos a utilizar para codificar el mismo dataset y proyectarlo sobre dos dimensiones 2D.
history =
autoencoder.fit(X_train,
X_train, epochs=20)
codings = encoder.predict(X_train)
fig = plt.figure(figsize=(4,3))
plt.plot(codings[:,0], codings[:, 1], "b.")
plt.xlabel("$z_1$", fontsize=18)
plt.ylabel("$z_2$", fontsize=18, rotation=0)
plt.grid(True)
save_fig("autoencoder
lineal_pca")
plt.show()
El mismo dataset X_train se utiliza en las entradas y en los objetivos (la proyección de dicho dataset en un plano de 2D) que es la salida de la capa oculta del autoencoder. El autoencoder encuentra el mejor plano para proyectrar el dataset en 2D preservando la máxima varianza de los datos sobre dicho plano, justo como haría un PCA.
Podemos pensar que los autoencoders son una forma de aprendizaje autosupervisado, utilizando una técnica de aprendizaje con etiquetas generadas automáticamente.
Si vamos a la carpeta imágenes de nuestro entorno virtual aislado podemos ver que nos ha guardado la imagen del dataset de 3D proyectado sobre un plano 2D.
Traducido del capítulo 17 de “Hands-On Machine Learning with Scikit-Learn, Keras and Tensorflow, 2nd Edition by Aurelien Géron (O’Reilly). Copyright 2019 Kiwisoft S.A.S., 978-1-492-03264-9”
No hay comentarios:
Publicar un comentario