QBoard » Artificial Intelligence & ML » AI and ML - Tensorflow » Keras, How to get the output of each layer?

Keras, How to get the output of each layer?

  • I have trained a binary classification model with CNN, and here is my code

    model = Sequential()
    model.add(Convolution2D(nb_filters, kernel_size[0], kernel_size[1],
                            border_mode='valid',
                            input_shape=input_shape))
    model.add(Activation('relu'))
    model.add(Convolution2D(nb_filters, kernel_size[0], kernel_size[1]))
    model.add(Activation('relu'))
    model.add(MaxPooling2D(pool_size=pool_size))
    # (16, 16, 32)
    model.add(Convolution2D(nb_filters*2, kernel_size[0], kernel_size[1]))
    model.add(Activation('relu'))
    model.add(Convolution2D(nb_filters*2, kernel_size[0], kernel_size[1]))
    model.add(Activation('relu'))
    model.add(MaxPooling2D(pool_size=pool_size))
    # (8, 8, 64) = (2048)
    model.add(Flatten())
    model.add(Dense(1024))
    model.add(Activation('relu'))
    model.add(Dropout(0.5))
    model.add(Dense(2))  # define a binary classification problem
    model.add(Activation('softmax'))
    
    model.compile(loss='categorical_crossentropy',
                  optimizer='adadelta',
                  metrics=['accuracy'])
    model.fit(x_train, y_train,
              batch_size=batch_size,
              nb_epoch=nb_epoch,
              verbose=1,
              validation_data=(x_test, y_test))
    ​

    And here, I wanna get the output of each layer just like TensorFlow, how can I do that? This post was edited by Nitara Bobal at August 31, 2020 12:01 PM IST
      August 31, 2020 10:46 AM IST
    1
  • From https://keras.io/getting-started/faq/#how-can-i-obtain-the-output-of-an-intermediate-layer

    One simple way is to create a new Model that will output the layers that you are interested in:

    from keras.models import Model
    
    model = ...  # include here your original model
    
    layer_name = 'my_layer'
    intermediate_layer_model = Model(inputs=model.input,
                                     outputs=model.get_layer(layer_name).output)
    intermediate_output = intermediate_layer_model.predict(data)

    Alternatively, you can build a Keras function that will return the output of a certain layer given a certain input, for example:


    from keras import backend as K
    
    # with a Sequential model
    get_3rd_layer_output = K.function([model.layers[0].input],
                                      [model.layers[3].output])
    layer_output = get_3rd_layer_output([x])[0]
    ​
     
      August 31, 2020 11:12 AM IST
    1
  • You can easily get the outputs of any layer by using: model.layers[index].output

    For all layers use this:

    from keras import backend as K
    
    inp = model.input                                           # input placeholder
    outputs = [layer.output for layer in model.layers]          # all layer outputs
    functors = [K.function([inp, K.learning_phase()], [out]) for out in outputs]    # evaluation functions
    
    # Testing
    test = np.random.random(input_shape)[np.newaxis,...]
    layer_outs = [func([test, 1.]) for func in functors]
    print layer_outs​

    Note: To simulate Dropout use learning_phase as 1. in layer_outs otherwise use 0.

    Edit 1:

    K.function creates theano/tensorflow tensor functions which is later used to get the output from the symbolic graph given the input.

    Now K.learning_phase() is required as an input as many Keras layers like Dropout/Batchnomalization depend on it to change behavior during training and test time.

    So if you remove the dropout layer in your code you can simply use:

    from keras import backend as K
    
    inp = model.input                                           # input placeholder
    outputs = [layer.output for layer in model.layers]          # all layer outputs
    functors = [K.function([inp], [out]) for out in outputs]    # evaluation functions
    
    # Testing
    test = np.random.random(input_shape)[np.newaxis,...]
    layer_outs = [func([test]) for func in functors]
    print layer_outs​

    Edit 2: More optimized

    I just realized that the previous answer is not that optimized as for each function evaluation the data will be transferred CPU->GPU memory and also the tensor calculations needs to be done for the lower layers over-n-over.

    Instead this is a much better way as you don't need multiple functions but a single function giving you the list of all outputs:

    from keras import backend as K
    
    inp = model.input                                           # input placeholder
    outputs = [layer.output for layer in model.layers]          # all layer outputs
    functor = K.function([inp, K.learning_phase()], outputs )   # evaluation function
    
    # Testing
    test = np.random.random(input_shape)[np.newaxis,...]
    layer_outs = functor([test, 1.])
    print layer_outs​
    This post was edited by Advika Banerjee at August 31, 2020 12:01 PM IST
      August 31, 2020 11:31 AM IST
    1
    • Rakesh Racharla
      Rakesh Racharla Excellent answer, np.random.random(input_shape)[np.newaxis,...] can also be written as np.random.random(input_shape)[np.newaxis,:]
      August 31, 2020
  • Previous solutions were not working for me. I handled this issue as shown below.

    layer_outputs = []
    for i in range(1, len(model.layers)):
        tmp_model = Model(model.layers[0].input, model.layers.output)
        tmp_output = tmp_model.predict(img)[0]
        layer_outputs.append(tmp_output)
      December 3, 2021 12:50 PM IST
    0
  • Well, other answers are very complete, but there is a very basic way to "see", not to "get" the shapes.

    Just do a model.summary(). It will print all layers and their output shapes. "None" values will indicate variable dimensions, and the first dimension will be the batch size.

      December 10, 2021 11:05 AM IST
    0
  • Assuming you have:

    1- Keras pre-trained model.

    2- Input x as image or set of images. The resolution of image should be compatible with dimension of the input layer. For example 80*80*3 for 3-channels (RGB) image.

    3- The name of the output layer to get the activation. For example, "flatten_2" layer. This should be include in the layer_names variable, represents name of layers of the given model.

    4- batch_size is an optional argument.

    Then you can easily use get_activation function to get the activation of the output layer for a given input x and pre-trained model:

    import six
    import numpy as np
    import keras.backend as k
    from numpy import float32
    def get_activations(x, model, layer, batch_size=128):
    """
    Return the output of the specified layer for input `x`. `layer` is specified by layer index (between 0 and
    `nb_layers - 1`) or by name. The number of layers can be determined by counting the results returned by
    calling `layer_names`.
    :param x: Input for computing the activations.
    :type x: `np.ndarray`. Example: x.shape = (80, 80, 3)
    :param model: pre-trained Keras model. Including weights.
    :type model: keras.engine.sequential.Sequential. Example: model.input_shape = (None, 80, 80, 3)
    :param layer: Layer for computing the activations
    :type layer: `int` or `str`. Example: layer = 'flatten_2'
    :param batch_size: Size of batches.
    :type batch_size: `int`
    :return: The output of `layer`, where the first dimension is the batch size corresponding to `x`.
    :rtype: `np.ndarray`. Example: activations.shape = (1, 2000)
    """
    
        layer_names = [layer.name for layer in model.layers]
        if isinstance(layer, six.string_types):
            if layer not in layer_names:
                raise ValueError('Layer name %s is not part of the graph.' % layer)
            layer_name = layer
        elif isinstance(layer, int):
            if layer < 0 or layer >= len(layer_names):
                raise ValueError('Layer index %d is outside of range (0 to %d included).'
                                 % (layer, len(layer_names) - 1))
            layer_name = layer_names[layer]
        else:
            raise TypeError('Layer must be of type `str` or `int`.')
    
        layer_output = model.get_layer(layer_name).output
        layer_input = model.input
        output_func = k.function([layer_input], [layer_output])
    
        # Apply preprocessing
        if x.shape == k.int_shape(model.input)[1:]:
            x_preproc = np.expand_dims(x, 0)
        else:
            x_preproc = x
        assert len(x_preproc.shape) == 4
    
        # Determine shape of expected output and prepare array
        output_shape = output_func([x_preproc[0][None, ...]])[0].shape
        activations = np.zeros((x_preproc.shape[0],) + output_shape[1:], dtype=float32)
    
        # Get activations with batching
        for batch_index in range(int(np.ceil(x_preproc.shape[0] / float(batch_size)))):
            begin, end = batch_index * batch_size, min((batch_index + 1) * batch_size, x_preproc.shape[0])
            activations[begin:end] = output_func([x_preproc[begin:end]])[0]
    
        return activations​
      August 31, 2020 12:04 PM IST
    0