Python Keras,如何获得每一层的输出?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41711190/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 01:29:07  来源:igfitidea点击:

Keras, How to get the output of each layer?

pythontensorflowdeep-learningkeras

提问by GoingMyWay

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

我已经用 CNN 训练了一个二元分类模型,这是我的代码

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?

在这里,我想像 TensorFlow 一样获得每一层的输出,我该怎么做?

回答by indraforyou

You can easily get the outputs of any layer by using: model.layers[index].output

您可以使用以下方法轻松获取任何层的输出: 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_phaseas 1.in layer_outsotherwise use 0.

注:为了模拟差使用learning_phase1.layer_outs以其它方式使用0.

Edit:(based on comments)

编辑:(基于评论)

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

K.function创建 theano/tensorflow 张量函数,稍后用于从给定输入的符号图中获取输出。

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.

现在K.learning_phase()需要作为输入,因为许多 Keras 层(如 Dropout/Batchnomalization)依赖于它在训练和测试期间改变行为。

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

因此,如果您删除代码中的 dropout 层,您可以简单地使用:

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

编辑 2:更优化

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.

我刚刚意识到之前的答案并没有针对每个函数评估进行优化,数据将被传输到 CPU->GPU 内存,并且还需要对较低层进行一次次的张量计算。

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

回答by blue-sky

From https://keras.io/getting-started/faq/#how-can-i-obtain-the-output-of-an-intermediate-layer

来自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:

或者,您可以构建一个 Keras 函数,该函数将在给定某个输入的情况下返回某个层的输出,例如:

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]

回答by Philippe Remy

Based on all the good answers of this thread, I wrote a library to fetch the output of each layer. It abstracts all the complexity and has been designed to be as user-friendly as possible:

基于这个线程的所有好的答案,我写了一个库来获取每一层的输出。它抽象了所有的复杂性,并被设计为尽可能用户友好:

https://github.com/philipperemy/keract

https://github.com/philipperemy/keract

It handles almost all the edge cases

它处理几乎所有的边缘情况

Hope it helps!

希望能帮助到你!

回答by devil in the detail

Following looks very simple to me:

以下对我来说看起来很简单:

model.layers[idx].output

Above is a tensor object, so you can modify it using operations that can be applied to a tensor object.

上面是一个张量对象,因此您可以使用可应用于张量对象的操作来修改它。

For example, to get the shape model.layers[idx].output.get_shape()

例如,要获得形状 model.layers[idx].output.get_shape()

idxis the index of the layer and you can find it from model.summary()

idx是图层的索引,您可以从 model.summary()

回答by Miladiouss

I wrote this function for myself (in Jupyter) and it was inspired by indraforyou's answer. It will plot all the layer outputs automatically. Your images must have a (x, y, 1) shape where 1 stands for 1 channel. You just call plot_layer_outputs(...) to plot.

我为自己编写了这个函数(在 Jupyter 中),它的灵感来自indraforyou的答案。它将自动绘制所有图层输出。您的图像必须具有 (x, y, 1) 形状,其中 1 代表 1 个通道。您只需调用 plot_layer_outputs(...) 即可绘图。

%matplotlib inline
import matplotlib.pyplot as plt
from keras import backend as K

def get_layer_outputs():
    test_image = YOUR IMAGE GOES HERE!!!
    outputs    = [layer.output for layer in model.layers]          # all layer outputs
    comp_graph = [K.function([model.input]+ [K.learning_phase()], [output]) for output in outputs]  # evaluation functions

    # Testing
    layer_outputs_list = [op([test_image, 1.]) for op in comp_graph]
    layer_outputs = []

    for layer_output in layer_outputs_list:
        print(layer_output[0][0].shape, end='\n-------------------\n')
        layer_outputs.append(layer_output[0][0])

    return layer_outputs

def plot_layer_outputs(layer_number):    
    layer_outputs = get_layer_outputs()

    x_max = layer_outputs[layer_number].shape[0]
    y_max = layer_outputs[layer_number].shape[1]
    n     = layer_outputs[layer_number].shape[2]

    L = []
    for i in range(n):
        L.append(np.zeros((x_max, y_max)))

    for i in range(n):
        for x in range(x_max):
            for y in range(y_max):
                L[i][x][y] = layer_outputs[layer_number][x][y][i]


    for img in L:
        plt.figure()
        plt.imshow(img, interpolation='nearest')

回答by cannin

From: https://github.com/philipperemy/keras-visualize-activations/blob/master/read_activations.py

来自:https: //github.com/philipperemy/keras-visualize-activations/blob/master/read_activations.py

import keras.backend as K

def get_activations(model, model_inputs, print_shape_only=False, layer_name=None):
    print('----- activations -----')
    activations = []
    inp = model.input

    model_multi_inputs_cond = True
    if not isinstance(inp, list):
        # only one input! let's wrap it in a list.
        inp = [inp]
        model_multi_inputs_cond = False

    outputs = [layer.output for layer in model.layers if
               layer.name == layer_name or layer_name is None]  # all layer outputs

    funcs = [K.function(inp + [K.learning_phase()], [out]) for out in outputs]  # evaluation functions

    if model_multi_inputs_cond:
        list_inputs = []
        list_inputs.extend(model_inputs)
        list_inputs.append(0.)
    else:
        list_inputs = [model_inputs, 0.]

    # Learning phase. 0 = Test mode (no dropout or batch normalization)
    # layer_outputs = [func([model_inputs, 0.])[0] for func in funcs]
    layer_outputs = [func(list_inputs)[0] for func in funcs]
    for layer_activations in layer_outputs:
        activations.append(layer_activations)
        if print_shape_only:
            print(layer_activations.shape)
        else:
            print(layer_activations)
    return activations

回答by KamKam

Wanted to add this as a comment (but don't have high enough rep.) to @indraforyou's answer to correct for the issue mentioned in @mathtick's comment. To avoid the InvalidArgumentError: input_X:Y is both fed and fetched.exception, simply replace the line outputs = [layer.output for layer in model.layers]with outputs = [layer.output for layer in model.layers][1:], i.e.

想将此作为评论(但没有足够高的代表。)添加到@indraforyou 的答案中,以纠正 @mathtick 评论中提到的问题。为了避免InvalidArgumentError: input_X:Y is both fed and fetched.异常,只需更换行outputs = [layer.output for layer in model.layers]outputs = [layer.output for layer in model.layers][1:],即

adapting indraforyou's minimal working example:

适应 indraforyou 的最小工作示例:

from keras import backend as K 
inp = model.input                                           # input placeholder
outputs = [layer.output for layer in model.layers][1:]        # all layer outputs except first (input) layer
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

p.s. my attempts trying things such as outputs = [layer.output for layer in model.layers[1:]]did not work.

ps 我尝试尝试诸如此类的事情outputs = [layer.output for layer in model.layers[1:]]没有奏效。

回答by imanzabet

Assuming you have:

假设你有:

1- Keras pre-trained model.

1- Keras 预训练model

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

2- 输入x为图像或图像集。图像的分辨率应与输入层的尺寸兼容。例如80*80*3用于 3 通道 (RGB) 图像。

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

3-layer用于获取激活的输出名称。例如,“flatten_2”层。这应该包含在layer_names变量中,代表给定的层的名称model

4- batch_sizeis an optional argument.

4-batch_size是一个可选参数。

Then you can easily use get_activationfunction to get the activation of the output layerfor a given input xand pre-trained model:

然后,您可以轻松地使用get_activation函数来获取layer给定输入x和预训练的输出的激活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

回答by Daniel M?ller

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.

只需做一个model.summary(). 它将打印所有图层及其输出形状。“无”值将指示可变维度,第一个维度将是批量大小。

回答by Mpizos Dimitris

In case you have one of the following cases:

如果您有以下情况之一:

  • error: InvalidArgumentError: input_X:Y is both fed and fetched
  • case of multiple inputs
  • 错误: InvalidArgumentError: input_X:Y is both fed and fetched
  • 多个输入的情况

You need to do the following changes:

您需要进行以下更改:

  • add filter out for input layers in outputsvariable
  • minnor change on functorsloop
  • outputs变量中的输入层添加过滤器
  • functors循环上的微小变化

Minimum example:

最小示例:

from keras.engine.input_layer import InputLayer
inp = model.input
outputs = [layer.output for layer in model.layers if not isinstance(layer, InputLayer)]
functors = [K.function(inp + [K.learning_phase()], [x]) for x in outputs]
layer_outputs = [fun([x1, x2, xn, 1]) for fun in functors]