I want to create VAE(variational autoencoder). During model creating it throws exception.
When subclassing the Model
class, you should implement a call
method.
I am using Tensorflow 2.0
JavaScript
x
77
77
1
def vae():
2
models ={}
3
4
def apply_bn_and_dropout(x):
5
return l.Dropout(dropout_rate)(l.BatchNormalization()(x))
6
input_image = l.Input(batch_shape=(batch_size,28,28,1))
7
x = l.Flatten()(input_image)
8
x = l.Dense(256,activation="relu")(x)
9
x = apply_bn_and_dropout(x)
10
x = l.Dense(128,activation="relu")(x)
11
x = apply_bn_and_dropout(x)
12
13
z_mean = l.Dense(latent_dim)(x)
14
z_log_var = l.Dense(latent_dim)(x)
15
16
def sampling(args):
17
z_mean, z_log_var = args
18
epsilon = K.random_normal(shape=(batch_size,latent_dim),mean=0., stddev=1.0)
19
return z_mean + K.exp(z_log_var/2) * epsilon
20
21
lambda_layer = l.Lambda(sampling,output_shape=(latent_dim,))([z_mean,z_log_var])
22
23
models["encoder"] = Model(input_image,lambda_layer,"Encoder")
24
models["z_meaner"] = Model(input_image,z_mean,"Enc_z_mean")
25
models["z_lvarer"] = Model(input_image, z_log_var,"Enc_z_log_var")
26
27
z = l.Input(shape=(latent_dim,))
28
x = l.Dense(128)(z)
29
x = l.LeakyReLU()(x)
30
x = apply_bn_and_dropout(x)
31
x = l.Dense(256)(x)
32
x = l.LeakyReLU()(x)
33
x = apply_bn_and_dropout(x)
34
x = l.Dense(28*28,activation="sigmoid")(x)
35
decoded = l.Reshape((28,28,1))(x)
36
37
models["decoder"] = Model(z,decoded,name="Decoder")
38
models["vae"] = Model(input_image, models["decoder"](models["encoder"](input_image)), name="VAE")
39
40
def vae_loss(x,decoded):
41
x = K.reshape(x,shape=(batch_size,28*28))
42
decoded = K.reshape(decoded,shape=(batch_size,28*28))
43
xent_loss = 28*28*binary_crossentropy(x, decoded)
44
kl_loss = -0.5 * K.sum(1 + z_log_var - K.square(z_mean) - K.exp(z_log_var), axis=-1)
45
return (xent_loss + kl_loss)/2/28/28
46
47
return models, vae_loss
48
49
---------------------------------------------------------------------------
50
NotImplementedError Traceback (most recent call last)
51
<ipython-input-34-186b31069dc3> in <module>
52
----> 1 models, vae_loss = vae()
53
2 vae = models["vae"]
54
55
<ipython-input-33-0fa06b39e41c> in vae()
56
36
57
37 models["decoder"] = Model(z,decoded,name="Decoder")
58
---> 38 models["vae"] = Model(input_image, models["decoder"](models["encoder"](input_image)), name="VAE")
59
39
60
40 def vae_loss(x,decoded):
61
62
~AppDataLocalContinuumanaconda3libsite-packagestensorflowpythonkerasenginebase_layer.py in __call__(self, inputs, *args, **kwargs)
63
610 base_layer_utils.AutoAddUpdates(self,
64
611 inputs)) as auto_updater:
65
--> 612 outputs = self.call(inputs, *args, **kwargs)
66
613 auto_updater.set_outputs(outputs)
67
614
68
69
~AppDataLocalContinuumanaconda3libsite-packagestensorflowpythonkerasenginenetwork.py in call(self, inputs, training, mask)
70
865 """
71
866 if not self._is_graph_network:
72
--> 867 raise NotImplementedError('When subclassing the `Model` class, you should'
73
868 ' implement a `call` method.')
74
869
75
76
NotImplementedError: When subclassing the `Model` class, you should implement a `call` method.
77
Models with names
JavaScript
1
19
19
1
def create_dense_ae():
2
encoding_dim = 64
3
4
input_img = layers.Input(shape=(28, 28, 1))
5
flat_img = layers.Flatten()(input_img)
6
7
encoded = layers.Dense(encoding_dim, activation='relu')(flat_img)
8
9
10
input_encoded = layers.Input(shape=(encoding_dim,))
11
flat_decoded = layers.Dense(28*28, activation='sigmoid')(input_encoded)
12
decoded = layers.Reshape((28, 28, 1))(flat_decoded)
13
14
15
encoder = tf.keras.Model(input_img, encoded, name="encoder")
16
decoder = tf.keras.Model(input_encoded, decoded, name="decoder")
17
autoencoder = tf.keras.Model(input_img, decoder(encoder(input_img)), name="autoencoder")
18
return encoder, decoder, autoencoder
19
I want to get model.
Advertisement
Answer
The problem is here:
JavaScript
1
4
1
models["encoder"] = Model(input_image,lambda_layer,"Encoder")
2
models["z_meaner"] = Model(input_image,z_mean,"Enc_z_mean")
3
models["z_lvarer"] = Model(input_image, z_log_var,"Enc_z_log_var")
4
You are passing three arguments to the construction, where only two are needed (inputs and outputs). Models do not have names. The problem is that three parameters will break the detection of network or sub-classed model as shown in the keras source code.
So just replace the code with:
JavaScript
1
4
1
models["encoder"] = Model(input_image,lambda_layer)
2
models["z_meaner"] = Model(input_image,z_mean)
3
models["z_lvarer"] = Model(input_image, z_log_var)
4