简体   繁体   English

Keras,如何获取每一层的output?

[英]Keras, How to get the output of each layer?

I have trained a binary classification model with CNN, and here is my code我用 CNN 训练了一个二进制分类 model,这是我的代码

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?在这里,我想得到每一层的 output 就像 TensorFlow,我该怎么做?

You can easily get the outputs of any layer by using: model.layers[index].output您可以使用以下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_phase as 1. in layer_outs otherwise use 0.注意:要模拟 Dropout,请使用learning_phase作为1.layer_outs否则使用0.

Edit: (based on comments)编辑:(基于评论)

K.function creates 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

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]

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!希望能帮助到你!

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()

idx is the index of the layer and you can find it from model.summary() idx是层的索引,你可以从model.summary()找到它

I wrote this function for myself (in Jupyter) and it was inspired by indraforyou 's answer.我为自己编写了这个函数(在 Jupyter 中),它的灵感来自indraforyou的答案。 It will plot all the layer outputs automatically.它将自动绘制所有图层输出。 Your images must have a (x, y, 1) shape where 1 stands for 1 channel.您的图像必须具有 (x, y, 1) 形状,其中 1 代表 1 个通道。 You just call plot_layer_outputs(...) to plot.您只需调用 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')

This answer is based on: https://stackoverflow.com/a/59557567/2585501这个答案基于: https : //stackoverflow.com/a/59557567/2585501

To print the output of a single layer:要打印单层的输出:

from tensorflow.keras import backend as K
layerIndex = 1
func = K.function([model.get_layer(index=0).input], model.get_layer(index=layerIndex).output)
layerOutput = func([input_data])  # input_data is a numpy array
print(layerOutput)

To print output of every layer:打印每一层的输出:

from tensorflow.keras import backend as K
for layerIndex, layer in enumerate(model.layers):
    func = K.function([model.get_layer(index=0).input], layer.output)
    layerOutput = func([input_data])  # input_data is a numpy array
    print(layerOutput)

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

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.想将此作为评论(但没有足够高的代表。)添加到@indraforyou 的答案中,以纠正@mathtick 评论中提到的问题。 To avoid the InvalidArgumentError: input_X:Y is both fed and fetched.为避免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:] , ie例外,只需将行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

ps 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:]]类的尝试没有奏效。

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[i].output)
    tmp_output = tmp_model.predict(img)[0]
    layer_outputs.append(tmp_output)

Assuming you have:假设你有:

1- Keras pre-trained model . 1- Keras 预训练model

2- Input x as image or set of images. 2- 输入x作为图像或图像集。 The resolution of image should be compatible with dimension of the input layer.图像的分辨率应与输入层的尺寸兼容。 For example 80*80*3 for 3-channels (RGB) image.例如80*80*3用于 3 通道 (RGB) 图像。

3- The name of the output layer to get the activation. 3- 用于获取激活的输出layer的名称。 For example, "flatten_2" layer.例如,“flatten_2”层。 This should be include in the layer_names variable, represents name of layers of the given model .这应该包含在layer_names变量中,表示给定model的层名称。

4- batch_size is an optional argument. 4- batch_size是一个可选参数。

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

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

In case you have one of the following cases:如果您有以下情况之一:

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

You need to do the following changes:您需要进行以下更改:

  • add filter out for input layers in outputs variableoutputs变量中为输入层添加过滤器
  • minnor change on functors loop 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]

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() .只需做一个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. “无”值将指示可变维度,第一个维度将是批量大小。

Generally, output size can be calculated as一般output大小可以计算为

[(W−K+2P)/S]+1

where在哪里

W is the input volume - in your case you have not given us this
K is the Kernel size - in your case 2 == "filter" 
P is the padding - in your case 2
S is the stride - in your case 3

Another, prettier formulation:另一个更漂亮的公式:

美化的等式

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM