Dela via


Automatisk avkodare för bilder med delegering och avpoolning

Innehållsförteckning

Sammanfattning

image

Exemplet Image\GettingStarted\07_Deconvolution_PY.py visar hur du använder Deconvolution och Unpooling för att generera en enkel automatisk avbildningskodare (07_Deconvolution_BS.cntk är motsvarande BrainScript-version). Den använder MNIST-datauppsättningen, som har en upplösning på 28x28x1, kodar den till en 7x7x1-representation med hjälp av decentralisering och poolning och avkodning till den ursprungliga upplösningen. Träningskriteriet är RMSE (root-mean-square error). Bilden ovan visar visualiseringar av den ursprungliga bilden, den kodade bilden och den avkodade bilden för de fem första bilderna i MNIST-testuppsättningen.

Installation

Om du vill köra exemplet behöver du MNIST-datauppsättningen. Du kan hämta data genom att köra följande kommando från Examples\Image\DataSets\MNIST mappen :

python install_mnist.py

Kör exemplet

Exemplet finns i Examples\Image\GettingStarted mappen . Om du vill köra det här exemplet använder du följande kommando för att köra Python version (från en Python CNTK miljö):

python 07_Deconvolution_PY.py

eller det här kommandot för BrainScript-versionen:

cntk configFile=07_Deconvolution_BS.cntk

RMSE-värdena för träning och testning är 0,225 respektive 0,223. Om du vill visualisera de kodade och avkodade bilderna kör du följande kommando:

python 07_Deconvolution_Visualizer.py

Ange use_brain_script_model=True för BrainScript-modellen och False för den Python modellen. Visualiseringarna lagras i Output mappen under Examples\Image\GettingStarted tillsammans med en textrepresentation av kodaren och avkodarens utdata.

Teknisk information

Nedan visas modelldefinitionen för den enkla autokodaren för bilder i BrainScript (för den fullständiga konfigurationsfilen se 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

Motsvarande modelldefinition i 07_Deconvolution_PY.py är

    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)
    

Vi beskriver BrainScript-versionen här, den Python versionen är analog. Modellen tillämpar först en ConvolutionalLayer med djupet cMap=1 på indatafunktionerna följt av en ReLU-aktivering och använder en MaxPoolingLayer med en filterform och steg av (4:4). Detta resulterar i en kodad tensor av storleken 7x7x1. Den använder sedan en MaxUnpoolingLayer och en DeconvLayer med motsvarande filterformer för att avkoda den tillbaka till den ursprungliga upplösningen.

Avkodardelen komprimerar de ursprungliga 784 (28x28) talen till 49 (7x7), en faktor av 16. Om du bara använder djupet 1 för för ConvolutionalLayer kan kodarens resultat visualiseras på ett meningsfullt sätt (se bilden överst på den här sidan). Man kan öka antalet faltningsfilter, t.ex. för att cMap=3 få mindre komprimering och förhoppningsvis bättre avkodningsresultat. I det här exemplet reduceras RMSE för både träning och testning till 0.196. Ett annat sätt att få mindre komprimering är att använda en mindre filterform och steg för poolningsskiktet. Användning för (2:2) både poolning och avpoolning ger en kodad tensor av storlek 14x14x1 och minskar RMSE i det här exemplet till 0.136 för träning och 0.131 testning. Bilden nedan visar visualisering av den ursprungliga bilden och den avkodade bilden för de första fem bilderna i MNIST-testuppsättningen för de tre diskuterade inställningarna.

image

Decentralisering och avpoolning

Låt oss titta lite närmare på MaxUnpoolingLayer och DeconvLayer.

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

MaxPoolingLayer kräver två indata, som är utdata från motsvarande poollager (pool1 i det här fallet) och indata för motsvarande poollager (conv1 i det här fallet). conv1krävs i CNTK för att fastställa målet för avpoolningsåtgärden, eftersom CNTK inte lagrar så kallade växelvariabler (se här för mer information).

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

Den första parametern i DeconvLayer är djupet på utdatavolymen, den andra är kernelformen (width:height) och den tredje är djupet på indatavolymen. Utfyllnadsparametrarna måste anges i enlighet med kernelformen för att uppnå önskad bredd och höjd för utdata tensorn (i det här fallet 28x28). Mer information om DeconvLayer finns på sidan Lagerreferens.

Automatisk kodare med flera lager

Du kan stapla fler lager av Conv/Deconv och Pool/Unpool för en mer komplex automatisk kodare. Följande är ett exempel med två lager av varje typ som du kan använda i 07_Deconvolution_BS.cntk (ersätt helt enkelt modellen i filen):

    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

För att visualisera resultaten måste du ersätta z.pool1 med z.pool_B i 07_Deconvolution_Visualizer.py innan du kör det för att adressera rätt nodnamn för kodarens utdata. Om du vill undersöka alla nodnamn i modellen tar du helt enkelt bort kommentaren print_all_node_names(model_file) i Python skriptet.