Path: blob/master/site/es-419/tutorials/generative/pix2pix.ipynb
25118 views
Copyright 2019 The TensorFlow Authors.
Licensed under the Apache License, Version 2.0 (the "License");
pix2pix: Traducción de imagen a imagen con un GAN condicional
En este tutorial se muestra cómo construir y entrenar una red generativa condicional adversarial (cGAN) llamada pix2pix, la cual aprende un mapeo desde las imágenes de entrada a las de salida, como se describe en Image-to-image translation with conditional adversarial networks{:.external} de Isola et al. (2017). pix2pix no es específico de una determinada aplicación, sino que puede aplicarse a una amplia gama de tareas, como sintetizar fotos a partir de mapas de etiquetas, generar fotos coloreadas a partir de imágenes en blanco y negro, convertir fotos de Google Maps en imágenes aéreas e incluso transformar bocetos en fotos.
En este ejemplo, su red generará imágenes de fachadas de edificios utilizando la base de datos CMP Facade Database proporcionada por el Center for Machine Perception{:.external} de la Universidad Técnica Checa de Praga{:.external}. Para abreviar, utilizará una copia preprocesada{:.external} de este conjunto de datos creado por los autores de pix2pix.
En el cGAN pix2pix, se condiciona a las imágenes de entrada y se generan las imágenes de salida correspondientes. Los cGAN se propusieron por primera vez en Conditional Generative Adversarial Nets (Mirza y Osindero, 2014)
La arquitectura de tu red incluirá:
Un generador con una arquitectura basada en U-Net{:.external}.
Un discriminador representado por un clasificador PatchGAN convolucional (propuesto en el documento pix2pix{:. external}).
Tenga en cuenta que cada época puede tardar unos 15 segundos en una sola GPU V100.
A continuación se muestran algunos ejemplos de la salida generada por el cGAN pix2pix después de entrenar durante 200 épocas en el conjunto de datos de fachadas (80,000 pasos).
Importar TensorFlow y otras bibliotecas
Cargar el conjunto de datos
Descargue los datos de la base de datos de fachadas CMP (30MB). Los conjuntos de datos adicionales están disponibles en el mismo formato aquí{:.external}. En Colab puede seleccionar otros conjuntos de datos en el menú desplegable. Tenga en cuenta que algunos de los otros conjuntos de datos son significativamente mayores (edges2handbags
tiene un tamaño de 8 GB).
Cada imagen original es de tamaño 256 x 512
y contiene dos imágenes 256 x 256
:
Es necesario separar las imágenes reales de las fachadas de los edificios de las imágenes de las etiquetas de arquitectura, todas ellas de tamaño 256 x 256
.
Defina una función que cargue archivos de imagen y dé como salida dos tensores de imágenes:
Represente una muestra de las imágenes de entrada (imagen de la etiqueta de arquitectura) y reales (foto de la fachada del edificio):
Tal y como se describe en el documento pix2pix{:.external}, es necesario aplicar el jittering aleatorio y el reflejo para preprocesar el conjunto de entrenamiento.
Defina varias funciones que:
Cambie el tamaño de cada imagen
256 x 256
a un alto y ancho mayores-286 x 286
.Recórtelo aleatoriamente a
256 x 256
.Dé la vuelta a la imagen horizontalmente de forma aleatoria, es decir, de izquierda a derecha (reflejo aleatorio).
Normalice las imágenes al rango
[-1, 1]
.
Puede inspeccionar parte de la salida preprocesada:
Después de comprobar que la carga y el preprocesamiento funcionan, definamos un par de funciones de ayudante que carguen y preprocesen los conjuntos de entrenamiento y de prueba:
Cree una canalización de entrada con tf.data
Construya el generador
El generador de su cGAN pix2pix es un U-Netmodificado {:.external}. Una U-Net consta de un codificador (downsampler) y un decodificador (upsampler). (Puede encontrar más información al respecto en el tutorial Segmentación de imágenes y en la página web del proyecto U-Net{:.external}).
Cada bloque del codificador es Convolution -> Batch normalization -> Leaky ReLU
Cada bloque del descodificador es Transposed convolution -> Batch normalization -> Dropout (aplicado a los 3 primeros bloques) -> ReLU
Hay conexiones de omisión entre el codificador y el decodificador (como en la U-Net).
Defina el reductor de muestreo o downsampler (codificador):
Defina el amplificador de muestreo o upsampler (decodificador):
Defina el generador con el "downsampler" y el "upsampler":
Visualice la arquitectura del modelo generador:
Pruebe el generador:
Defina la pérdida del generador
Las GAN aprenden que una pérdida se adapta a los datos, mientras que las cGAN aprenden una pérdida estructurada que penaliza una posible estructura que difiera de la salida de la red y de la imagen objetivo, como se describe en el documento pix2pix{:.external}.
La pérdida del generador es una pérdida de entropía cruzada sigmoidea de las imágenes generadas y un arreglo de unos.
El documento pix2pix también menciona la pérdida L1, que es un MAE (error promedio absoluto) entre la imagen generada y la imagen objetivo.
Esto permite que la imagen generada se asemeje estructuralmente a la imagen objetivo.
La fórmula para calcular la pérdida total del generador es
gan_loss + LAMBDA * l1_loss
, dondeLAMBDA = 100
. Este valor se decidió por los autores del documento.
El procedimiento de entrenamiento del generador es el siguiente:
Construya el discriminador
El discriminador en el cGAN pix2pix es un clasificador PatchGAN convolucional: intente clasificar si cada imagen patch es real o no es real, como se describe en el documento pix2pix{:.external}.
Cada bloque del discriminador es Convolution -> Batch normalization -> Leaky ReLU.
La forma de la salida después de la última capa es
(batch_size, 30, 30, 1)
.Cada parche de imagen
30 x 30
de la salida clasifica una porción70 x 70
de la imagen de entrada.El discriminador recibe 2 entradas:
La imagen de entrada y la imagen objetivo, que deben clasificarse como reales.
La imagen de entrada y la imagen generada (la salida del generador), que debe clasificarse como falsa.
Utilice
tf.concat([inp, tar], axis=-1)
para concatenar estas 2 entradas.
Vamos a definir el discriminador:
Visualice la arquitectura del modelo discriminador:
Pruebe el discriminador:
Defina la pérdida del discriminador
La función
discriminator_loss
toma 2 entradas: imágenes reales e imágenes generadas.real_loss
es una pérdida de entropía cruzada sigmoidea de las imágenes reales y un arreglo de unos (ya que éstas son las imágenes reales).generated_loss
es una pérdida de entropía cruzada sigmoide de las imágenes generadas y un arreglo de ceros (ya que éstas son las imágenes falsas).La
total_loss
es la suma dereal_loss
ygenerated_loss
.
A continuación se muestra el procedimiento de entrenamiento del discriminador.
Para obtener más información sobre la arquitectura y los hiperparámetros, puede consultar el documento pix2pix{:.external}.
Defina los optimizadores y un salvador de puntos de verificación
Generar imágenes
Escriba una función para trazar algunas imágenes durante el entrenamiento.
Pasar imágenes del equipo de pruebas al generador.
A continuación, el generador traducirá la imagen de entrada a la de salida.
¡El último paso consiste en representar gráficamente las predicciones y voila!
Nota: El training=True
es intencional aquí ya que usted quiere las estadísticas por lotes, mientras ejecuta el modelo en el conjunto de datos de prueba. Si utiliza training=False
, obtendrá las estadísticas acumuladas aprendidas del conjunto de datos de entrenamiento (que no desea).
Pruebe la función:
Entrenamiento
Para cada entrada de ejemplo se genera una salida.
El discriminador recibe como primera entrada la
input_image
y la imagen generada. La segunda entrada es lainput_image
y latarget_image
.A continuación, calcule la pérdida del generador y del discriminador.
A continuación, calcule los gradientes de pérdida con respecto a las variables generadoras y discriminadoras (entradas) y aplíquelos al optimizador.
Por último, registre las pérdidas en TensorBoard.
El bucle de entrenamiento propiamente dicho. Como este tutorial puede ejecutarse con más de un conjunto de datos, y éstos varían mucho en tamaño, el bucle de entrenamiento está configurado para trabajar por pasos en vez de por épocas.
Itera sobre el número de pasos.
Cada 10 pasos imprime un punto (
.
).Cada 1,000 pasos: borre la pantalla y ejecute
generate_images
para mostrar el progreso.Cada 5,000 pasos: guarde un punto de verificación.
Este bucle de entrenamiento guarda registros que puede ver en TensorBoard para supervisar el progreso del entrenamiento.
Si trabaja en una máquina local, lanzaría un proceso TensorBoard separado. Cuando trabaje en un cuaderno, lance el visor antes de iniciar el entrenamiento para monitorizar con TensorBoard.
Inicie el visor TensorBoard (Lo sentimos, esto no se muestra en tensorflow.org):
Puede ver los resultados de una ejecución previa de este bloc de notas en TensorBoard.dev.
Por último, ejecute el bucle de entrenamiento:
La interpretación de los registros es más sutil cuando se entrena un GAN (o un cGAN como pix2pix) en comparación con un modelo sencillo de clasificación o regresión. Cosas en las que debe fijarse:
Revise que ni el modelo generador ni el discriminador hayan "ganado". Si el
gen_gan_loss
o eldisc_loss
se vuelven muy bajos, es un indicador de que este modelo está dominando al otro, y usted no está entrenando correctamente el modelo combinado.El valor
log(2) = 0.69
es un buen punto de referencia para estas pérdidas, ya que indica una perplejidad de 2: el discriminador tiene, por término medio, la misma incertidumbre sobre las dos opciones.Para el
disc_loss
, un valor inferior a0,69
significa que el discriminador obtiene mejores resultados que el azar en el conjunto combinado de imágenes reales y generadas.Para el
gen_gan_loss
, un valor inferior a0,69
significa que el generador lo hace mejor que el azar al momento de engañar al discriminador.A medida que progresa el entrenamiento, la
gen_l1_loss
debería disminuir.