デコンボリューションとアンプールを使用したイメージ オート エンコーダー
目次
まとめ
Image\GettingStarted\07_Deconvolution_PY.py の例は、Deconvolution と Unpooling を使用して単純なイメージ自動エンコーダーを生成する方法を示しています (07_Deconvolution_BS.cntk は対応する BrainScript バージョンです)。 これは、28x28x1 の解像度を持つ MNIST データセットを使用し、畳み込みとプーリングを使用して 7x7x1 表現にエンコードし、元の解像度にデコードします。 トレーニング基準は、ルート平均 2 乗誤差 (RMSE) です。 上の図は、MNIST テスト セットの最初の 5 つの画像に対する元のイメージ、エンコードされたイメージ、デコードされたイメージの視覚化を示しています。
セットアップ
この例を実行するには、MNIST データ セットが必要です。 フォルダーから次のコマンドを実行すると、データを Examples\Image\DataSets\MNIST
取得できます。
python install_mnist.py
例を実行する
この例はフォルダーにあります Examples\Image\GettingStarted
。 この例を実行するには、次のコマンドを使用して Python バージョンを実行します (Python CNTK環境から)。
python 07_Deconvolution_PY.py
BrainScript バージョンの場合は、次のコマンドを実行します。
cntk configFile=07_Deconvolution_BS.cntk
トレーニングとテストの RMSE 値はそれぞれ 0.225 と 0.223 です。 エンコードおよびデコードされたイメージを視覚化するには、次のコマンドを実行します。
python 07_Deconvolution_Visualizer.py
BrainScript モデルと False
Python モデル用に設定use_brain_script_model=True
されます。
視覚化は、エンコーダーとデコーダー出力の Output
テキスト表現と共にフォルダー Examples\Image\GettingStarted
に格納されます。
技術的な詳細
BrainScript の単純な画像自動エンコーダーのモデル定義を次に示します (完全な構成ファイルについては、 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
07_Deconvolution_PY.py の対応するモデル定義は次のとおりです。
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)
ここでは BrainScript のバージョンについて説明します。Python のバージョンは似ています。 このモデルでは、最初に入力フィーチャに深さを cMap=1
持つ ConvolutionalLayer を適用し、続いて ReLU アクティブ化を行い、フィルターの形状とストライド (4:4)
を持つ MaxPoolingLayer を使用します。 これにより、エンコードされたサイズ 7x7x1
のテンソルが発生します。 次に、MaxUnpoolingLayer と DeconvLayer と対応するフィルター図形を使用して、元の解像度にデコードします。
デコーダー部分は、元 784
の(28x28)数値を 49
(7x7) 16
に圧縮します。 ConvolutionalLayer の深度 1
のみを使用すると、エンコーダーの結果を意味のある方法で視覚化できるという利点があります (このページの上部にある図を参照)。 畳み込みフィルターの数を増やすことができます。たとえば cMap=3
、圧縮を減らし、できればデコード結果を向上させることができます。 この例では、トレーニングとテストの両方の RMSE が次の値に 0.196
減らされます。 圧縮を減らすもう 1 つの方法は、プーリング レイヤーに小さいフィルター図形とストライドを使用することです。 プールとプール解除の両方に使用 (2:2)
すると、エンコードされたサイズ 14x14x1
のテンソルが生成され、この例 0.136
の RMSE はトレーニングと 0.131
テストに縮小されます。 次の図は、3 つの設定について説明した MNIST テスト セットの最初の 5 つのイメージの元の画像とデコードされたイメージの視覚化を示しています。
デコンボリューションとアンプール
MaxUnpoolingLayer と DeconvLayer を少し詳しく見てみましょう。
MaxUnpoolingLayer {(4:4), stride=(4:4)}(pool1, conv1)
MaxPoolingLayer には 2 つの入力が必要です。これは、対応するプーリング レイヤー (pool1
この場合) の出力と、対応するプーリング レイヤー (conv1
この場合) の入力です。 conv1
CNTKはスイッチ変数と呼ばれる変数を格納しないため、CNTKではプール解除操作のターゲットを決定する必要があります (詳細については、こちらを参照してください)。
DeconvLayer {1, (5:5), cMap, lowerPad=(2:2:0), upperPad=(2:2:0)}
DeconvLayer の最初のパラメーターは出力ボリュームの深さ、2 つ目はカーネルシェイプ (width:height) で、3 つ目は入力ボリュームの深さです。 パディングパラメータは、出力テンソルの所望の幅と高さを達成するためにカーネル形状に従って設定する必要があります(この場合は28x28)。 DeconvLayer の詳細については、「 レイヤーリファレンス」ページを参照してください。
多層自動エンコーダー
より複雑な自動エンコーダーのために、Conv/Deconv と Pool/Unpool のレイヤーをさらに積み重ねることができます。 次の例は、使用できる各種類の 2 つのレイヤーを含む例です (ファイル内の 07_Deconvolution_BS.cntk
モデルを置き換えるだけです)。
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
結果を視覚化するには、エンコーダー出力の07_Deconvolution_Visualizer.py
正しいノード名に対処するために、実行する前に置き換えるz.pool1
z.pool_B
必要があります。 モデル内のすべてのノード名を調査するには、Python スクリプトでコメント print_all_node_names(model_file)
を解除するだけです。