たそらぼ

日頃思ったこととかメモとか。

tensorflow2.0でシンプルなオートエンコーダーを作る

tensorflow2.0で一番シンプルなオートエンコーダーを作りました。
SageMakerとかに自作のモデルを乗せて動かしてみたいのですが、まだ作れるモデルが少ないので、基本的なところから書いていくことにしました。

コードは以下にあります。
github.com

ネットワーク

下図のモデルを訓練しました。層の厚さなどのパラメータはチューニングしていません。

f:id:tasotasoso:20191001214131p:plain
今回作ったモデル

class Encoder(layers.Layer):
    def __init__(self):
        super(Encoder, self).__init__()
        self.d1 = Dense(units=64, activation='relu')
        self.d2 = Dense(units=64, activation='relu')
    def call(self, x):
        x = self.d1(x)
        z = self.d2(x)
        return z

class Decoder(layers.Layer):
    def __init__(self):
        super(Decoder, self).__init__()
        self.d3 = Dense(units=64, activation='relu')
        self.d4 = Dense(units=784, activation='sigmoid')
    def call(self, z):
        x = self.d3(z)
        x = self.d4(x)
        return x

class Autoencorder(Model):
    def __init__(self):
        super(Autoencorder, self).__init__()
        self.encoder = Encoder()
        self.decoder = Decoder()

    def call(self, x):
        z = self.encoder(x)
        reconstructed = self.decoder(z)
        return reconstructed

ただ、要は一度入力より小さい次元に落として、再度次元を上げて、入力に対して学習させているので、一応、簡単に以下のように書いても同じモデルが得られるはずです。

class Autoencorder(Model):
  def __init__(self):
    super(Autoencorder, self).__init__()
    self.d1 = Dense(units=64, activation='relu')
    self.d2 = Dense(units=64, activation='relu')
    self.d3 = Dense(units=64, activation='relu')
    self.d4 = Dense(units=784, activation='sigmoid')

  def call(self, x):
    
    x = self.d1(x)
    z = self.d2(x)
    x = self.d3(z)
    x = self.d4(x)
    return x

結果

10エポック学習させたニューラルネットにデータを流してみて、出来を見てみます。

f:id:tasotasoso:20191001204720p:plain
テストデータのひとつ


f:id:tasotasoso:20191001204804p:plain
学習後のネットワークに流したテストデータ

確かに入力に似た感じの画像が生成されています。

損失関数

Implementing an Autoencoder in TensorFlow 2.0 - Towards Data Scienceを参考にMSEにしています。
L=\frac{1}n\sum^{n-1}_{i=0}(\hat{x}_i - x_i)^2

train_loss = tf.keras.metrics.Mean(name='train_loss')
loss = tf.reduce_mean(tf.square(tf.subtract(predictions, image)))
train_loss(loss)

何気に基本的な演算のAPIが分からなかったのですが、これは公式のAPIドキュメントを確認します。

ちなみに、これの感じだと、reduce_meanをした後に、metrics.Meanをする必要があんまりないかもです。

参考にしたもの

tensorflow2.0.0-beta1のコードとネットワークの図の記載ありです。
towardsdatascience.com

tensorflow2.0のページです。
www.tensorflow.org

オートエンコーダーの概要です。
deepage.net