title: Extract encoder and decoder from trained autoencoder
body: <p>I want to divide the autoencoder learning and applying into two parts following <a href="https://blog.keras.io/building-autoencoders-in-keras.html" rel="nofollow noreferrer">https://blog.keras.io/building-autoencoders-in-keras.html</a> and using the fashion-mnist data for testing purposes:</p>
  <ol>
  <li>Load the images, do the fitting that may take some hours or days and use a callback to save the best autoencoder model. That process can be some weeks before the following part.</li>
  <li>Use this best model (manually selected by filename) and plot original image, the encoded representation made by the encoder of the autoencoder and the prediction using the decoder of the autoencoder.
  I have problems (see second step) to extract the encoder and decoder layers from the trained and saved autoencoder.</li>
  </ol>
  <p>For <strong>step one</strong> I have the very simple network as follows:</p>
  <pre><code>input_img = Input(shape=(784,))
  # encoded representation
  encoded = Dense(encoding_dim, activation='relu')(input_img)
  # lossy reconstruction
  decoded = Dense(784, activation='sigmoid')(encoded)
  
  # full AE model: map an input to its reconstruction
  autoencoder = Model(input_img, decoded)
  
  # encoder: map an input to its encoded representation
  encoder = Model(input_img, encoded)
  # placeholder for an encoded input
  encoded_input = Input(shape=(encoding_dim,))
  # last layer of the autoencoder model
  decoder_layer = autoencoder.layers[-1]
  # decoder
  decoder = Model(encoded_input, decoder_layer(encoded_input))
  </code></pre>
  <p>The networks are:</p>
  <pre><code>autoencoder.summary()
  _________________________________________________________________
  Layer (type)                 Output Shape              Param #   
  =================================================================
  input_5 (InputLayer)         (None, 784)               0         
  _________________________________________________________________
  dense_5 (Dense)              (None, 32)                25120     
  _________________________________________________________________
  dense_6 (Dense)              (None, 784)               25872     
  =================================================================
  </code></pre>
  <p>and</p>
  <pre><code>encoder.summary()
  _________________________________________________________________
  Layer (type)                 Output Shape              Param #   
  =================================================================
  input_5 (InputLayer)         (None, 784)               0         
  _________________________________________________________________
  dense_5 (Dense)              (None, 32)                25120     
  =================================================================
  </code></pre>
  <p>So I train the model and save it by <code>autoencoder.save('fashion-autoencoder.hdf5')</code>. In my real example I save it with a callback so a workaround by saving the encoder and decoder does not seem a real solution. Later, I load the images (not shown) and do the predictions like</p>
  <pre><code># encode and decode some images from test set
  encoded_imgs = encoder.predict(x_test)
  decoded_imgs = decoder.predict(encoded_imgs)
  # test the shape
  print(encoded_imgs[0].shape)
  </code></pre>
  <p>and get a shape of <code>(32,0)</code>.</p>
  <p>So lets go to <strong>step 2</strong> where I have my problems. I load the model using</p>
  <pre><code>encoder= K.models.load_model('fashion-autoencoder.hdf5')
  # delete the last layers to get the encoder
  encoder.layers.pop()
  encoder.summary() # show model data
  </code></pre>
  <p>and the encoder looks the same as the original in step one what makes me think the extraction has worked well:</p>
  <pre><code>Layer (type)                 Output Shape              Param #   
  =================================================================
  input_5 (InputLayer)         (None, 784)               0         
  _________________________________________________________________
  dense_5 (Dense)              (None, 32)                25120     
  =================================================================
  Total params: 50,992
  Trainable params: 50,992
  Non-trainable params: 0
  </code></pre>
  <p>But I also get the warning</p>
  <pre><code>training.py:478: UserWarning: Discrepancy between trainable weights and collected trainable weights, did you set `model.trainable` without calling `model.compile` after ?
  'Discrepancy between trainable weights and collected trainable'
  </code></pre>
  <p>that I understand in a kind of way but do not know how important it is. Then I load images again (not shown) and use the encoder</p>
  <pre><code>encoded_imgs = encoder.predict(x_test)
  
  # test the shape
  print(encoded_imgs[0].shape)
  </code></pre>
  <p>but shape is not right with <code>(784,)</code>.</p>
  <p>So, my extraction for the encoder did not work since the dimensions are not correct.
  I even have less success extracting the decoder (from the saved autoencoder) since I cannot use <code>push()</code> and tried stuff like <code>decoder = decoder.layers[-1:-2]</code> but it did not work.</p>
  <p>So, my general question is how to extract parts of loaded models.</p>