LoginSignup
10
13

More than 5 years have passed since last update.

KerasでAutoEncoderその2

Last updated at Posted at 2018-07-14

KerasでAutoEncoderの続き。

Kearsのexamplesの中にvariational autoencoderがあったのだ

以上のように、KerasのBlogに書いてあるようにやればOKなんだけれど、Deep Convolutional Variational Autoencoderについては、サンプルコードが書いてないので、チャレンジしてみる。

とか前回の記事には書いてたんだけれど、https://github.com/keras-team/keras/blob/master/examples/variational_autoencoder_deconv.py は、ConvolutionでVariationalなAutoEncoderだった。

潜在変数を求める関数sampling()

def sampling(args):
    z_mean, z_log_var = args
    batch = K.shape(z_mean)[0]
    dim = K.int_shape(z_mean)[1]
    epsilon = K.random_normal(shape=(batch, dim))
    return z_mean + K.exp(0.5 * z_log_var) * epsilon

前回の記事に書いたのは以下のようになっていて、違うような同じような。

def sampling(args):
    z_mean, z_log_var = args
    latent_dim = 20
    epsilon_std = 1.0
    epsilon = K.random_normal(shape=(K.shape(z_mean)[0],
                                     K.shape(z_mean)[1],
                                     K.shape(z_mean)[2],
                                     latent_dim),
                              mean=0.,
                              stddev=epsilon_std)
    return z_mean + K.exp(z_log_var / 2) * epsilon

多分、kerasのsampleにある方が汎用的な気がする。

loss関数

前回の記事では、loss関数は以下の様に定義していた。

# loss関数
# Compute VAE loss
xent_loss = K.mean(metrics.binary_crossentropy(input_img, decoded), axis=-1)
kl_loss =  - 0.5 * K.mean(K.sum(1 + K.log(K.square(z_log_var)) - K.square(z_mean) - K.square(z_log_var), axis=-1))
vae_loss = K.mean(xent_loss + kl_loss)

けれど、kerasのexampleに書いてあるものは、少し違う。

reconstruction_loss = binary_crossentropy(K.flatten(inputs),
                                          K.flatten(outputs))

reconstruction_loss *= image_size * image_size
kl_loss = 1 + z_log_var - K.square(z_mean) - K.exp(z_log_var)
kl_loss = K.sum(kl_loss, axis=-1)
kl_loss *= -0.5
vae_loss = K.mean(reconstruction_loss + kl_loss)

kerasのexampleでは、コマンドライン引数でMSEかBinaryCrossEntropyかを指定するようになっているんだけれど、いずれにせよ、上記のような定義になっている。

特にimage_size*image_sizeを乗算するところとか、どんな意味があるのかは、ちょっと分からない。

CNNの定義

kerasのexampleには、CNNの定義にMaxPoolingが含まれていない。
それから、この書き方は、楽でイイな。

inputs = Input(shape=input_shape, name='encoder_input')
x = inputs
for i in range(2):
    filters *= 2
    x = Conv2D(filters=filters,
               kernel_size=kernel_size,
               activation='relu',
               strides=2,
               padding='same')(x)

実行結果

前回の記事と同様に、数字の1のみを学習させてみる。

ちなみに、我が家の2012年型のMacBook Pro 13inchで、CPUだけで学習させても、MNISTで50 epochs程度なら、10分もかからない。

20180714_001.png

なんか、前回よりも、ちゃんと入力からむりくり1を復元しようとしている感がある。

20180714_002.png

異常検知

異常検知とは、1じゃない画像が入力された場合には、その画像を1と思って再構成した画像と元の画像との間には差異があるはずで、ソレを可視化できれば異常検知に使えるはずだ、という理屈。

20180714_003.png

意図どおりに動作した感がある。

本日のコード

解消できなかった課題

さて、今回は使っている画像がMNISTなので、全画像をメモリの上に置くことができたのだが、もう少し大きいサイズで、大量の画像で同様のことをやろうとすると、kerasのImageDataGeneratorflow_from_directory()のお世話になる他はない。

ということで、試してみたのだけれど、fit_generator()でエラーになってしまって、どうにもうまくいかなかった。
なんか良い方法があるんかなぁ。

駄目だったコード

#(前略)

gen = ImageDataGenerator(rescale=1./255)
train_gen = gen.flow_from_directory(
    'train',
    target_size=(image_size, image_size),
    batch_size=batch_size,
    class_mode=None)
valid_gen = gen.flow_from_directory(
    'valid',
    target_size=(image_size, image_size),
    batch_size=batch_size,
    class_mode=None)

autoencoder.fit_generator(
    train_gen,
    steps_per_epoch=int(np.ceil(train_gen.samples/batch_size)),
    epochs=epochs,
    validation_data=(valid_gen, None)
    validation_steps=int(np.ceil(valid_gen.samples/batch_size)))

どうしたら良いんでしょうね、コレ。
情報求ム。

10
13
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
13