"BOKU"のITな日常

62歳・文系システムエンジニアの”BOKU”は日々勉強を楽しんでます

kerasブログのAutoencoderサンプルに中間レイヤー出力を付け加える

Tensorflow2.0環境で動くように手直ししたkerasのAutoencoderサンプルに中間層の出力をつけくわえてみました。

f:id:arakan_no_boku:20200604232413p:plain

 

今回やってみること

 

前回、keras Blogの「Building Autoencoders in Keras」を、Tensorflow2.0環境で動くようにしてみました。

arakan-pgm-ai.hatenablog.com

ついでなので、中間レイヤーの出力も以前と同じようにできるかやってみます。

 

ポイント

 

ベースは前回のソースです。

arakan-pgm-ai.hatenablog.com

なので、以前のkerasと、tensorflow2.0環境のtf.kerasの違いの吸収方法について、繰り返しは説明しません。

kerasで中間レイヤーを出力する方法のおさらいだけやります。

まず、出力対象とする中間レイヤー名称が必要です。

これは「summary()」を使います。

今回の場合だと、こうです。

autoencoder.summary()

出力例です。

f:id:arakan_no_boku:20200605202111p:plain

左端のLayer列の「dense_1」等が指定する名前です。

もうひとつ重要な情報が「output shape」です。

画像で中間レイヤーのイメージを出力時のreshape()に必須の情報です。

今回は「dense_4」の出力する例にします。

まず、入力から中間レイヤーまでのモデルを生成します。

intermediate_layer_model = tf.keras.Model(
inputs=input_img,
outputs=autoencoder.get_layer('dense_4').output)

そして、そのモデルで「predict()」して、そのアウトプットを出力します。

intermediate_imgs = intermediate_layer_model.predict(x_test)

あとは、最後の出力に追加します。

# display reconstruction
ax = plt.subplot(3, n, i + 1 + n)
plt.imshow(intermediate_imgs[i].reshape(16, 8))
plt.gray()
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)

サイズが128なので、reshape(16, 8)にします。

これで中間レイヤーの出力ができます。 

 

ソースコード全文です

 

Deep autoencoderのケースだけやってます。

データはファッションMINISTに変えてみました。

import tensorflow as tf
from tensorflow.keras.layers import Dense
from tensorflow.keras.datasets import fashion_mnist as mnist
import numpy as np
# use Matplotlib (don't ask)
import matplotlib.pyplot as plt


# this is the size of our encoded representations
# 32 floats -> compression of factor 24.5, assuming the input is 784 floats
encoding_dim = 32

# this is our input placeholder
input_img = tf.keras.Input(shape=(784,))

encoded = Dense(128, activation='relu')(input_img)
encoded = Dense(64, activation='relu')(encoded)
encoded = Dense(32, activation='relu')(encoded)

decoded = Dense(64, activation='relu')(encoded)
decoded = Dense(128, activation='relu')(decoded)
decoded = Dense(784, activation='sigmoid')(decoded)
# this model maps an input to its reconstruction
autoencoder = tf.keras.Model(inputs=input_img, outputs=decoded)

autoencoder.summary()

(x_train, _), (x_test, _) = mnist.load_data()

x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.
x_train = x_train.reshape((len(x_train), np.prod(x_train.shape[1:])))
x_test = x_test.reshape((len(x_test), np.prod(x_test.shape[1:])))
print(x_train.shape)
print(x_test.shape)

autoencoder.compile(
    optimizer=tf.keras.optimizers.Adam(),
    loss=tf.keras.losses.BinaryCrossentropy())

# autoencoder.load_weights('autoencoder.h5')
autoencoder.fit(x_train, x_train,
                epochs=100,
                batch_size=256,
                shuffle=True,
                validation_data=(x_test, x_test))

autoencoder.save_weights('autoencoder.h5')
# encode and decode some digits
# note that we take them from the *test* set
decoded_imgs = autoencoder.predict(x_test)

intermediate_layer_model = tf.keras.Model(
    inputs=input_img,
    outputs=autoencoder.get_layer('dense_4').output)
intermediate_imgs = intermediate_layer_model.predict(x_test)

n = 10  # how many digits we will display
plt.figure(figsize=(10, 4))

for i in range(n):
    # display original
    ax = plt.subplot(3, n, i + 1)
    plt.imshow(x_test[i].reshape(28, 28))
    plt.gray()
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)

    # display reconstruction
    ax = plt.subplot(3, n, i + 1 + n)
    plt.imshow(intermediate_imgs[i].reshape(16, 8))
    plt.gray()
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)

    # display reconstruction
    ax = plt.subplot(3, n, i + 1 + n + n)
    plt.imshow(decoded_imgs[i].reshape(28, 28))
    plt.gray()
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)
plt.show()

今回も学習を繰り返さなくてすむように

autoencoder.save_weights('autoencoder.h5')

を追加しています。

一度学習したあとは、こちらをコメントアウトして、こちら 

# autoencoder.load_weights('autoencoder.h5')

のコメントを外して、結果表示してます。

実行します。

ロス率は、たぶん、0.27あたりで頭打ちにはなります。

上段が元画像・中に中間レイヤー画像、下段に結果画像を10個表示します。

f:id:arakan_no_boku:20200605210430p:plain

今回はこんなところで。

ではでは。