Search code examples
pythontensorflowkerasdeep-learningautoencoder

Defining encoder and decoder models from autoencoder: ValueError: Input 0 of layer dense_3 is incompatible with the layer:


I'm creating an autoencoder using this tutorial. When I define the encoder and decoder models separately, I get the following error:

decoder = tf.keras.Model(encoded_input, decoder_layer(encoded_input))

File ".../site-packages/tensorflow/python/keras/engine/base_layer.py", line 586, in __call__
            self.name)
File ".../site-packages/tensorflow/python/keras/engine/input_spec.py", line 159, in assert_input_compatibility
            ' but received input with shape ' + str(shape))
ValueError: Input 0 of layer dense_3 is incompatible with the layer: expected axis -1 of input shape to have value 128 but received input with shape [None, 16]

I'm thinking that I need to reshape the output of my layer somewhere but I don't fully understand the reason behind this error.

Here is a minimal working example of my code:

def top_k(input, k):
    return tf.nn.top_k(input, k=k, sorted=True).indices
encoding_dim = 16
input_img = tf.keras.layers.Input(shape=(16, 16, 256), name ="input")
encoded = tf.keras.layers.Dense(encoding_dim, activation='relu')(input_img)
encoded2 = tf.keras.layers.Dense(256, activation='sigmoid')(encoded)
# top_k layer
topk = tf.keras.layers.Lambda(lambda x: tf.nn.top_k(x, k=int(int(x.shape[-1])/2),
                                                sorted=True,
                                                name="topk").values)(encoded)
decoded = tf.keras.layers.Dense(128, activation='relu')(topk) # one dimensional problem
decoded2 = tf.keras.layers.Dense(256, activation='sigmoid')(decoded)
autoencoder = tf.keras.Model(input_img, decoded2)

encoded_input = tf.keras.layers.Input(shape=(encoding_dim,))
# this is the problem
decoder_layer = autoencoder.layers[-1]
encoder = tf.keras.Model(input_img, encoded)
decoder = tf.keras.Model(encoded_input, decoder_layer(encoded_input))

Solution

  • You have several mistakes in you code. Check out the code snippet below and the comments listing what I changed.

    def top_k(input, k):
        return tf.nn.top_k(input, k=k, sorted=True).indices
    
    encoding_dim = 16
    input_img = tf.keras.layers.Input(shape=(16, 16, 256), name ="input")
    # The MNIST images are flattened in the tutorial you are following, so you have to do the same if you want to proceed in the same way.
    flatten = tf.keras.layers.Flatten()(input_img)
    encoded = tf.keras.layers.Dense(encoding_dim, activation='relu')(flatten)
    encoded2 = tf.keras.layers.Dense(256, activation='sigmoid')(encoded)
    # You were using encoded as input, which makes the encoded2 redundant, so I changed the input to be encoded2
    topk = tf.keras.layers.Lambda(lambda x: tf.nn.top_k(x, k=int(int(x.shape[-1])/2),
                                                    sorted=True,
                                                    name="topk").values)(encoded2)
    decoded = tf.keras.layers.Dense(128, activation='relu')(topk) # one dimensional problem
    decoded2 = tf.keras.layers.Dense(256, activation='sigmoid')(decoded)
    
    autoencoder = tf.keras.Model(input_img, decoded2) 
    encoder = tf.keras.Model(input_img, encoded2)
    
    # The actual input to the decoder is the shape of topk as in the autoencoder model
    encoded_input = tf.keras.layers.Input(shape=topk.shape)
    # You model is more complicated than the one in the tutorial, so if you want to recreate the decoder you have to do it layer by layer. This is the first layer
    decoded1 = autoencoder.layers[-2](encoded_input)
    # This is the second layer
    decoded2 = autoencoder.layers[-1](decoded1)
    # Finally, the decoder
    decoder = tf.keras.Model(encoded_input, decoded2)
    

    I assume that it should be pretty clear for you now.