まんぼう日記

takataka's diary

Denoising Autoencoder の実験をしてみる (5)

Denoising Autoencoder の実験をしてみる (4) - まんぼう日記 のつづき.今度は convolution / transposed convolution 使ってみました.

 

 

実験

これまで同様,MNISTの画像にごま塩とランダム平行移動のノイズを加えて denoising させます.

 

データの作り方等の詳細は前々回( Denoising Autoencoder の実験をしてみる (3) - まんぼう日記 )参照.プログラムはこちら:  https://gist.github.com/takatakamanbou/01a529f38ac40f39a343c2bf619dccb6TensorFlow 1.3 使ってます.

 

ネットワークの構成は次の通り.convX, convY_Tには Batch Normalization 組み込みました(conv6_Tを除く).

 

layer type output shape 備考
conv1 convolution 28 x 28 x 32 kernel:4x4, stride:1, ReLU
pool1 max-pooling 14 x 14 x 32 kernel:2x2, stride:2
conv2 convolution 14 x 14 x 64 kernel:4x4, stride:1, ReLU
pool2 max-pooling 7 x 7 x 64 kernel:2x2, stride:2
conv3 convolution 7 x 7 x 128 kernel:4x4, stride:1, ReLU
pool3 max-pooling 4 x 4 x 128 kernel:2x2, stride:2
conv4_T transposed-conv. 7 x 7 x 64 kernel:4x4, stride:2, ReLU
conv5_T transposed-conv. 14 x 14 x 32 kernel:4x4, stride:2, ReLU
conv6_T transposed-conv. 28 x 28 x 1 kernel:4x4, stride:2, linear

  

で,結果はこんなん.CNN と書いてある行が今回の結果,MLP は前回の.sqeL は学習データで測った誤差(出力とノイズなしの教師との間の二乗誤差),sqeT はテストデータの誤差です.

ノイズを加えたテスト画像 f:id:takatakamanbou:20170818181257p:plain
元の画像(正解) f:id:takatakamanbou:20170818181634p:plain
CNN (sqeL = 9.72, sqeT = 11.67) f:id:takatakamanbou:20170917180744p:plain
MLP (sqeL = 12.74, sqeT = 21.73) f:id:takatakamanbou:20170818181835p:plain

 

学習にかかった時間は,NVIDIA GeForce GTX 1080 使って3分ほど.CPUだけだと約35分でした.

いろいろ

Transposed Convolution 関係

今回一番苦労したのは,TensorFlow で Transposed Convolution(転置畳み込み,以下TC)を実装するとこでした. tf.nn.conv2d_transpose  |  TensorFlow 使うだけなんですが,引数の設定にいろいろ落とし穴がありまして.詳しくはソースを見てもらうとして,はまりそうなとこはこんな感じ:

  •  第2引数 filter の値の順序.[height, width, output_channels, in_channels] となっていて, tf.nn.conv2d  |  TensorFlow とチャンネル数の順序が逆.
  •  第3引数 output_shape を指定しないといけない.かつ…
    1. output_shape[0](バッチサイズ)を指定しないといけない
    2. output_shape[1],[2] の決め方がよくわからない

たかたかは特に output_shape 周りの問題を解決するのにえらい時間食ってまいました.興味のある方はこの辺をどうぞ.

output_shape の幅と高さについては結局上記を見ても解決しなくて,値を決め打ちするださださなプログラムでごまかしてしまいました.

 

Batch Normalization 関係

まんぼう日記には書いてませんが,昨日,TensorFlow で MLP と CNN (2) - まんぼう日記 のプログラムを Batch Normalization (以下BN) 使うように改造してみたので,今回も BN 使ってみました.そのときのプログラムはこちら: https://gist.github.com/takatakamanbou/ffba1efa4900971b5be3a1986a1149ed.BN は昔 Theano で自分で書いたことがある(Batch Normalization を実装する - まんぼう日記)けど,いまどき TensorFlow では簡単に組み込めます.今回は tf.nn.batch_normalization  |  TensorFlow 使ってます.

 

ただ,BN 使ってはみたものの,今回のネットワーク構成では特に恩恵は感じられませんでした.バイアス項使って BN しないプログラムも動かしてみたけど,普通に学習進むし速さもほとんど変わらへんかったし.

 

んでこれは余談ですが,BN を ReLU の前に入れるか後に入れるかは議論の余地があるようですね.元の論文では前に入れるべしと言うてるんやけど,後の方がいい結果が出ると言ってるひともいたりして.

 理論的にどちらがよいと言う話はまだなさそうなので,後がいいっちう結果もたまたまその実験条件ではそうなったって話にしか見えへんけど.

 

そんなことより,BN して ReLU やとどのユニットもだいたい半分は 0 を出力することになると思うんやけど,適当にオフセットさせて 0 の割合を変えたらどうなるかって,誰か調べてみーへんかな.特徴表現のスパースネス(もどき)をコントロールすることになるような….

 

Convolution だけにしたらどうなる?

上記の実験では前半に convolution + pooling の層,後半に transposed convolution の層を並べた素直な encoder-decoder 型の構成にしましたが,よく考えたら別にこの構成にしばられる理由ないですよね.ちうわけで,全部 conv 層にしたらどうなるかも試してみました.C32-C64-C128-C128-C128-C1 と 6 つの conv層を連ねる形です.カーネルは全部 4x4.padding = 'SAME' なので,出力マップは最初から最後まで 28 x 28 のまま.結果は,sqeL = 18.87, sqeT = 21.16 となりました.とりあえず encoder-decoder 型の方がよさげ.