Codificador automático de imágenes mediante desconvolución y desagrupación
Tabla de contenido
Resumen
En el ejemplo Image\GettingStarted\07_Deconvolution_PY.py se muestra cómo usar Deconvolución y Unpooling para generar un codificador automático de imagen simple (07_Deconvolution_BS.cntk es la versión de BrainScript correspondiente). Usa el conjunto de datos MNIST, que tiene una resolución de 28x28x1, lo codifica en una representación 7x7x1 mediante convolución y agrupación y descodificaciones en la resolución original. El criterio de entrenamiento es el error raíz medio cuadrado (RMSE). En la ilustración anterior se muestran visualizaciones de la imagen original, la imagen codificada y la imagen descodificada para las cinco primeras imágenes del conjunto de pruebas MNIST.
Configurar
Para ejecutar el ejemplo, necesita el conjunto de datos MNIST. Para obtener los datos, ejecute el siguiente comando desde la Examples\Image\DataSets\MNIST
carpeta :
python install_mnist.py
Ejecutar el ejemplo
El ejemplo se encuentra en la Examples\Image\GettingStarted
carpeta . Para ejecutar este ejemplo, use el siguiente comando para ejecutar la versión de Python (desde un entorno de python CNTK):
python 07_Deconvolution_PY.py
o este comando para la versión de BrainScript:
cntk configFile=07_Deconvolution_BS.cntk
Los valores de RMSE para entrenamiento y pruebas son 0,225 y 0,223 respectivamente. Para visualizar las imágenes codificadas y descodificadas, ejecute el siguiente comando:
python 07_Deconvolution_Visualizer.py
Establezca use_brain_script_model=True
para el modelo BrainScript y False
para el modelo de Python.
Las visualizaciones se almacenarán en la Output
carpeta en Examples\Image\GettingStarted
junto con una representación de texto del codificador y la salida del descodificador.
Detalles técnicos
A continuación se muestra la definición del modelo para el codificador automático de imagen simple en BrainScript (para obtener el archivo de configuración completo, consulte Image\GettingStarted\07_Deconvolution_BS.cntk).
cMap = 1
model = inputFeatures => {
conv1 = ConvolutionalLayer {cMap, (5:5), pad = true, activation=ReLU}(inputFeatures)
pool1 = MaxPoolingLayer {(4:4), stride=(4:4)}(conv1)
unpool1 = MaxUnpoolingLayer {(4:4), stride=(4:4)}(pool1, conv1)
deconv1 = DeconvLayer {1, (5:5), cMap, lowerPad=(2:2:0), upperPad=(2:2:0), bias=false}(unpool1)
}.deconv1
La definición del modelo correspondiente en 07_Deconvolution_PY.py es
cMap = 1
conv1 = cntk.layers.Convolution ((5,5), cMap, pad=True, activation=cntk.ops.relu)(scaled_input)
pool1 = cntk.layers.MaxPooling ((4,4), (4,4))(conv1)
unpool1 = cntk.layers.MaxUnpooling ((4,4), (4,4))(pool1, conv1)
z = cntk.layers.Deconvolution((5,5), num_channels, cMap, lower_pad=(0,2,2), upper_pad=(0,2,2), bias=False, init=cntk.glorot_uniform(0.001))(unpool1)
Aquí se describe la versión de BrainScript, la versión de Python es análoga. El modelo aplica primero una Clase ConvolucionalLayer con una profundidad de a las características de cMap=1
entrada seguidas de una activación de ReLU y usa maxPoolingLayer con una forma de filtro y un paso de (4:4)
. Esto da como resultado un tensor codificado de tamaño 7x7x1
. A continuación, usa maxUnpoolingLayer y deconvLayer con las formas de filtro correspondientes para descodificarla a la resolución original.
La parte del descodificador comprime los números originales 784
(28 x 28) en 49
(7x7), un factor de 16
. El uso de solo una profundidad de 1
para ConvolucionalLayer tiene la ventaja de que los resultados del codificador se pueden visualizar de forma significativa (vea la figura en la parte superior de esta página). Uno puede aumentar el número de filtros convolucionales, por ejemplo, para cMap=3
tener menos compresión y, con suerte, mejores resultados de descodificación. En este ejemplo, el RMSE para el entrenamiento y las pruebas se reduce a 0.196
. Otra manera de tener menos compresión es usar una forma de filtro más pequeña y un paso para la capa de agrupación. El uso (2:2)
de para agrupar y desagrupar produce un tensor codificado de tamaño 14x14x1
y reduce el RMSE de este ejemplo a 0.136
para el entrenamiento y 0.131
para las pruebas. En la ilustración siguiente se muestra la visualización de la imagen original y la imagen descodificada para las cinco primeras imágenes del conjunto de pruebas MNIST para los tres valores descritos.
Desconvolución y desagrupación
Veamos un poco más cerca de MaxUnpoolingLayer y DeconvLayer.
MaxUnpoolingLayer {(4:4), stride=(4:4)}(pool1, conv1)
MaxPoolingLayer requiere dos entradas, que son la salida de la capa de agrupación correspondiente (pool1
en este caso) y la entrada de la capa de agrupación correspondiente (conv1
en este caso). conv1
es necesario en CNTK para determinar el destino de la operación Desagrupar, ya que CNTK no almacena las variables de modificador llamadas (consulte aquí para obtener más información).
DeconvLayer {1, (5:5), cMap, lowerPad=(2:2:0), upperPad=(2:2:0)}
El primer parámetro de DeconvLayer es la profundidad del volumen de salida, el segundo es la forma del kernel (width:height) y la tercera es la profundidad del volumen de entrada. Los parámetros de relleno deben establecerse de acuerdo con la forma del kernel para lograr el ancho y alto deseados del tensor de salida (28 x 28 en este caso). Para obtener más información sobre DeconvLayer, consulte la página Referencia de capas.
Codificador automático de varias capas
Puede apilar más capas de Conv/Deconv y Pool/Unpool para un codificador automático más complejo. A continuación se muestra un ejemplo con dos capas de cada tipo que puede usar ( 07_Deconvolution_BS.cntk
simplemente reemplace el modelo en el archivo):
inputDim = 1
cMap1 = 5
cMap2 = 1
model = inputFeatures => {
conv_A = ConvolutionalLayer {cMap1, (5:5), pad = true, activation=ReLU}(inputFeatures)
pool_A = MaxPoolingLayer {(2:2), stride=(2:2)}(conv_A)
conv_B = ConvolutionalLayer {cMap2, (5:5), pad = true, activation=ReLU}(pool_A)
pool_B = MaxPoolingLayer {(2:2), stride=(2:2)}(conv_B)
unpool_B = MaxUnpoolingLayer {(2:2), stride=(2:2)}(pool_B, conv_B)
deconv_B = DeconvLayer {cMap1, (5:5), cMap2, lowerPad=(2:2:0), upperPad=(2:2:0)}(unpool_B)
unpool_A = MaxUnpoolingLayer {(2:2), stride=(2:2)}(deconv_B, conv_A)
deconv_A = DeconvLayer {inputDim, (5:5), cMap1, lowerPad=(2:2:0), upperPad=(2:2:0)}(unpool_A)
}.deconv_A
Para visualizar los resultados, debe reemplazar z.pool1
por z.pool_B
antes 07_Deconvolution_Visualizer.py
de ejecutarlo para abordar el nombre de nodo correcto para la salida del codificador. Para investigar todos los nombres de nodo del modelo, simplemente quite la marca de comentario en el script de print_all_node_names(model_file)
Python.