Partager via


Image Auto Encoder à l’aide de la décovolution et du dépooling

Table des matières

Résumé

image

L’exemple Image\GetStarted\07_Deconvolution_PY.py montre comment utiliser Deconvolution et Unpooling pour générer un encodeur automatique d’image simple (07_Deconvolution_BS.cntk est la version de BrainScript correspondante). Il utilise le jeu de données MNIST, qui a une résolution de 28x28x1, l’encode dans une représentation 7x7x1 à l’aide de convolution et de regroupement et de décodages vers la résolution d’origine. Le critère d’entraînement est une erreur de carré racine (RMSE). La figure ci-dessus montre les visualisations de l’image d’origine, l’image encodée et l’image décodée pour les cinq premières images du jeu de test MNIST.

Programme d’installation

Pour exécuter l’exemple, vous avez besoin du jeu de données MNIST. Vous pouvez obtenir les données en exécutant la commande suivante à partir du Examples\Image\DataSets\MNIST dossier :

python install_mnist.py

Exécuter l’exemple

L’exemple se trouve dans le Examples\Image\GettingStarted dossier. Pour exécuter cet exemple, utilisez la commande suivante pour exécuter la version Python (à partir d’un environnement Python CNTK) :

python 07_Deconvolution_PY.py

ou cette commande pour la version de BrainScript :

cntk configFile=07_Deconvolution_BS.cntk

Les valeurs RMSE pour l’entraînement et les tests sont respectivement 0,225 et 0,223. Pour visualiser les images codées et décodées, exécutez la commande suivante :

python 07_Deconvolution_Visualizer.py

Définissez use_brain_script_model=True le modèle BrainScript et False le modèle Python. Les visualisations seront stockées dans le dossier sous Examples\Image\GettingStarted lequel se trouvent une représentation textuelle de l’encodeur Output et la sortie du décodeur.

Détails techniques

Voici la définition de modèle pour l’encodeur automatique d’image simple dans BrainScript (pour le fichier de configuration complet, voir 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 définition de modèle correspondante dans 07_Deconvolution_PY.py est

    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)
    

Nous décrivons ici la version de BrainScript, la version Python est analogue. Le modèle applique d’abord un ConvolutionalLayer avec une profondeur des cMap=1 fonctionnalités d’entrée suivies d’une activation ReLU et l’utilisation d’un MaxPoolingLayer avec une forme de filtre et une progression de (4:4). Cela entraîne un tensoreur encodé de taille 7x7x1. Il utilise ensuite un MaxUnpoolingLayer et un DeconvLayer avec les formes de filtre correspondantes pour le décoder vers la résolution d’origine.

La partie décodeur compresse les nombres d’origine 784 (28x28) sur 49 (7x7), un facteur de 16. L’utilisation d’une profondeur 1 uniquement pour convolutionalLayer présente l’avantage que les résultats de l’encodeur peuvent être visualisées de manière significative (voir la figure en haut de cette page). On peut augmenter le nombre de filtres convolutionnels, par exemple pour cMap=3 avoir moins de compression et, espérons-le, de meilleurs résultats de décodage. Dans cet exemple, le RMSE pour l’apprentissage et le test sont réduits à 0.196. Une autre façon d’avoir moins de compression consiste à utiliser une forme de filtre plus petite et une progression pour la couche de regroupement. L’utilisation (2:2) pour le regroupement et le dépooling génère un tensor codé de taille 14x14x1 et réduit le RMSE dans cet exemple pour 0.136 l’entraînement et 0.131 pour les tests. La figure ci-dessous montre la visualisation de l’image d’origine et l’image décodée pour les cinq premières images du jeu de test MNIST pour les trois paramètres abordés.

image

Déconvolution et dépooling

Permet d’examiner un peu plus près le MaxUnpoolingLayer et le DeconvLayer.

MaxUnpoolingLayer {(4:4), stride=(4:4)}(pool1, conv1)

MaxPoolingLayer nécessite deux entrées, qui sont la sortie de la couche de regroupement correspondante (pool1 dans ce cas) et l’entrée de la couche de regroupement correspondante (conv1 dans ce cas). conv1est nécessaire dans CNTK pour déterminer la cible de l’opération de dépoolage, car CNTK ne stocke pas les variables de commutateur (voir ici pour plus d’informations).

DeconvLayer {1, (5:5), cMap, lowerPad=(2:2:0), upperPad=(2:2:0)}

Le premier paramètre du DeconvLayer est la profondeur du volume de sortie, le deuxième est la forme du noyau (largeur:hauteur) et la troisième est la profondeur du volume d’entrée. Les paramètres de remplissage doivent être définis conformément à la forme du noyau pour obtenir la largeur et la hauteur souhaitées du capteur de sortie (28x28 dans ce cas). Pour plus d’informations sur le DeconvLayer, consultez la page Référence de couche.

Encodeur automatique multicouche

Vous pouvez empiler davantage de couches de Conv/Deconv et Pool/Unpool pour un encodeur automatique plus complexe. Voici un exemple avec deux couches de chaque type que vous pouvez utiliser 07_Deconvolution_BS.cntk (remplacez simplement le modèle dans le fichier) :

    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

Pour visualiser les résultats que vous devez remplacer z.pool1z.pool_B07_Deconvolution_Visualizer.py avant de l’exécuter pour traiter le nom de nœud approprié pour la sortie de l’encodeur. Pour examiner tous les noms de nœuds dans le modèle, il suffit de annuler les commentaires print_all_node_names(model_file) dans le script Python.