Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extracting last layers of keras model as a submodel

Tags:

python

keras

Say we have a convolutional neural network M. I can extract features from images by using

extractor = Model(M.inputs, M.get_layer('last_conv').output)
features = extractor.predict(X)

How can I get the model that will predict classes using features?

I can't use the following lines because it requires the input of the model to be a placeholder.

predictor = Model([M.get_layer('next_layer').input], M.outputs)
pred = predictor.predict(features)

I also can't use K.function because later I want to use it as part of another model, so I will be appliyng predictor to tf.tensor, not np.array.

like image 750
eclique Avatar asked Oct 04 '17 19:10

eclique


People also ask

How do you save a subclass model?

The recommended way to save a subclassed model is to use save_model_weights_tf to create a TensorFlow SavedModel checkpoint, which will contain the value of all variables associated with the model: - The layers' weights - The optimizer's state - Any variables associated with stateful model metrics (if any).

What is model subclassing in keras?

In Model Sub-Classing there are two most important functions __init__ and call. Basically, we will define all the trainable tf. keras layers or custom implemented layers inside the __init__ method and call those layers based on our network design inside the call method which is used to perform a forward propagation.

How do I retrain a saved model in keras?

After loading the saved model, you can retrain as usual using loaded_model. fit() . Please check detailed example here. Another most important point is that when you have a custom_objects, then you need to select compile=False when you load the model and then compile the model with the custom_objects.


2 Answers

This is not the nicest solution, but it works:

from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Dense, Dropout, Flatten

def cnn():
    model = Sequential()
    model.add(Conv2D(32, kernel_size=(3, 3),
                     activation='relu',
                     input_shape=(28, 28, 1), name='l_01'))
    model.add(Conv2D(64, (3, 3), activation='relu', name='l_02'))
    model.add(MaxPooling2D(pool_size=(2, 2), name='l_03'))
    model.add(Dropout(0.25, name='l_04'))
    model.add(Flatten(name='l_05'))
    model.add(Dense(128, activation='relu', name='l_06'))
    model.add(Dropout(0.5, name='l_07'))
    model.add(Dense(10, activation='softmax', name='l_08'))
    return model

def predictor(input_shape):
    model = Sequential()
    model.add(Flatten(name='l_05', input_shape=(12, 12, 64)))
    model.add(Dense(128, activation='relu', name='l_06'))
    model.add(Dropout(0.5, name='l_07'))
    model.add(Dense(10, activation='softmax', name='l_08'))
    return model

cnn_model = cnn()
cnn_model.save('/tmp/cnn_model.h5')

predictor_model = predictor(cnn_model.output.shape)
predictor_model.load_weights('/tmp/cnn_model.h5', by_name=True)
like image 61
Oliver Wilken Avatar answered Sep 20 '22 00:09

Oliver Wilken


Every layer in the model is indexed. So if you know which layers you need, you could loop through them, copying them into a new model. This operation should copy the weights inside the layer as well.

Here's a model (from Oli Blum's answer):

  model = Sequential()
  # add some layers
  model.add(Conv2D(32, kernel_size=(3, 3),
                 activation='relu',
                 input_shape=(28, 28, 1), name='l_01'))
  model.add(Conv2D(64, (3, 3), activation='relu', name='l_02'))
  model.add(MaxPooling2D(pool_size=(2, 2), name='l_03'))
  model.add(Dropout(0.25, name='l_04'))
  model.add(Flatten(name='l_05'))
  model.add(Dense(128, activation='relu', name='l_06'))
  model.add(Dropout(0.5, name='l_07'))
  model.add(Dense(10, activation='softmax', name='l_08'))

Say you wanted the last three layers:

def extract_layers(main_model, starting_layer_ix, ending_layer_ix):
  # create an empty model
  new_model = Sequential()
  for ix in range(starting_layer_ix, ending_layer_ix + 1):
    curr_layer = main_model.get_layer(index=ix)
    # copy this layer over to the new model
    new_model.add(curr_layer)
  return new_model
like image 45
ljacob15 Avatar answered Sep 19 '22 00:09

ljacob15