Keras, 각 레이어의 출력을 얻는 방법?


155

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

그리고 여기에서는 TensorFlow와 같이 각 레이어의 출력을 얻고 싶습니다. 어떻게 할 수 있습니까?

답변:


182

다음을 사용하여 모든 레이어의 출력을 쉽게 얻을 수 있습니다. model.layers[index].output

모든 레이어에 다음을 사용하십시오.

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

참고 : 드롭 아웃의 사용을 시뮬레이션 learning_phase으로 1.layer_outs다른 사용0.

편집 : (주석에 따라)

K.function ano / tensorflow 텐서 함수를 생성하여 나중에 입력이 주어진 기호 그래프에서 출력을 얻는 데 사용됩니다.

이제 K.learning_phase()교육 및 테스트 시간 동안 동작을 변경하기 위해 Dropout / Batchnomalization과 같은 많은 Keras 레이어가 입력으로 필요합니다.

따라서 코드에서 드롭 아웃 레이어를 제거하면 간단하게 사용할 수 있습니다.

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

편집 2 : 더 최적화

방금 이전의 대답이 각 기능 평가에서 데이터가 CPU-> GPU 메모리로 전송되고 텐서 계산이 하위 계층 오버 오버에 대해 수행되어야하므로 최적화되지 않았다는 것을 깨달았습니다.

대신 여러 기능이 필요하지 않고 단일 출력으로 모든 출력 목록을 제공하므로 훨씬 더 나은 방법입니다.

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

2
선생님, 대답이 좋습니다. K.function([inp]+ [K.learning_phase()], [out])코드에서 무슨 의미입니까?
GoingMyWay

훌륭한 답변 np.random.random(input_shape)[np.newaxis,...]은 다음과 같이 쓸 수도 있습니다np.random.random(input_shape)[np.newaxis,:]
Tom

K.function은 무엇입니까? GPU (MPI?)에 어떻게 전달됩니까? 무대 뒤에서 무엇인가? CUDA와의 대화는 어떻습니까? 소스 코드는 어디에 있습니까?
Stav Bodik

3
@StavBodik 모델은 사용 함수를 구축 예측 K.function 여기서 , 상기의 용도를 예측 루프를 예측 여기 . 배치 크기에 대한 루프 예측 (기본값은 32로 설정되지 않은 경우)이지만 GPU 메모리의 제약 조건을 완화합니다. 그래서 나는 왜 당신이 관찰하고 있는지 model.predict더 잘 모르겠습니다 .
indraforyou

1
이것을 얻는 중 : InvalidArgumentError : S_input_39 : 0이 공급되고 페치됩니다. ... 아이디어가있는 사람?
mathtick

138

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

간단한 방법 중 하나는 원하는 레이어를 출력하는 새 모델을 만드는 것입니다.

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)

또는 특정 입력이 주어지면 특정 레이어의 출력을 반환하는 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]

내가 두 가지를 줄 수 있다면 ^,이 방법은 입력이 많을 때 훨씬 편리합니다.
Dan Erez

위의 코드에서 꽤 분명하지만 내 이해를 다시 확인하기 위해 기존 모델에서 모델을 만든 후 (이미 훈련 된 것으로 가정) 새 모델에서 set_weights를 호출 할 필요가 없습니다. 그 맞습니까?
JZ

것 사이의 차이는 layer_output = get_3rd_layer_output([X, 0])[0]하고 layer_output = get_3rd_layer_output([X, 1])[0]워드 프로세서 기차 모드와 테스트 모드 언급
제이슨

죄송합니다.이 모델의 기능이 정확히 무엇인지 설명해 주시겠습니까? 훈련해야합니까? 나는 그것에 대한 어떤 다이어그램도 상상할 수 없다. 다른 모델의 입력 레이어를 추가 한 다음 다른 모델의 임의의 중간 레이어를 출력으로 추가하고 입력을 공급합니까? 왜 원본 모델을 공급하지 않고 중개 계층에 직접 액세스 할 수 있습니까? 이 이상한 모델을 만드는 이유는 무엇입니까? 그리고 출력에 영향을 미치지 않습니까? 교육을 배우거나 요구하지 않습니까? 아니면 레이어가 원래 모델에서 사전 훈련 된 자체 가중치를 가져옵니다.
PedroD

19

이 스레드의 모든 좋은 대답을 바탕으로 각 레이어의 출력을 가져 오기 위해 라이브러리를 작성했습니다. 모든 복잡성을 추상화하고 가능한 한 사용자 친화적으로 설계되었습니다.

https://github.com/philipperemy/keract

거의 모든 에지 케이스를 처리합니다.

그것이 도움이되기를 바랍니다!


8

다음은 나에게 매우 단순 해 보입니다.

model.layers[idx].output

위는 텐서 객체이므로 텐서 객체에 적용 할 수있는 작업을 사용하여 수정할 수 있습니다.

예를 들어, 모양을 얻으려면 model.layers[idx].output.get_shape()

idx 레이어의 색인이며 다음에서 찾을 수 있습니다. model.summary()


1
이 답변에 어떤 문제가 있습니까? 이것이 왜 정답으로 올라가지 않습니까?
블랙 잭 21

1
데이터 프레임이 아닌 텐서 객체를 반환합니다. tf 객체는 이상하게 작동합니다.
HashRocketSyntax

7

나는 (Jpypyter에서) 나 자신을 위해이 기능을 작성했으며 영감을 얻었습니다. indraforyou 의 답변 . 모든 레이어 출력을 자동으로 플로팅합니다. 이미지는 1 개의 채널을 나타내는 (x, y, 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')

모델에 여러 입력이있는 경우 어떻게합니까? 입력을 어떻게 지정합니까?
안토니오 세 스토

이 줄에서 : layer_outputs_list = [op ([test_image, 1.]). 1. 0이어야합니까? 1은 훈련을 의미하고 0은 테스트를 의미합니까? 그렇지 않습니까?
Kongsea

이것은 나를 위해 작동하지 않습니다. 컬러 이미지를 사용했는데 오류가 발생했습니다. InvalidArgumentError : input_2 : 0이 공급되고 페치됩니다.
Vaibhav K

5

보낸 사람 : 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

링크가 더 이상 사용되지 않습니다.
Saeed


5

@mathtick의 의견에 언급 된 문제를 해결하기 위해 @indraforyou의 답변에 이것을 의견으로 추가하고 싶었지만 (응답이 충분하지는 않습니다.) 방지하기 위해 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:], 즉

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

추신 시도 outputs = [layer.output for layer in model.layers[1:]]가 작동하지 않는 등의 시도 .


1
정확하지 않습니다. 입력 레이어가 첫 번째로 정의 된 경우에만 해당됩니다.
Mpizos Dimitris

고마워요, 이것은 저에게 효과적이며 Mpizos의 의견에 따라 이유를 이해하고 싶습니다. 제 모델은 단지 3 개의 레이어 (단어 포함-BiLSTM-CRF)이므로 레이어 [0]을 제외해야했기 때문에 추측합니다. 퍼가기 만하고 활성화하지 않아야합니다.
KMunro

@MpizosDimitris 예, 맞습니다. 그러나 @indraforyou (내가 수정하고 있음)가 제공 한 예에서 이것은 그렇습니다. @KMunro 내가 올바르게 이해한다면, 첫 번째 레이어의 출력에 신경 쓰지 않는 이유는 단순히 텐서 형태로 임베드 된 단어 인 단어 임베딩의 출력이기 때문입니다. keras모델 의 "네트워크"부분에 입력 ). 단어 포함 레이어는 여기에 제공된 예제의 입력 레이어와 같습니다.
KamKam

3

당신이 있다고 가정 :

1- Keras 사전 훈련 model.

2- x이미지 또는 이미지 세트로 입력 하십시오. 이미지의 해상도는 입력 레이어의 치수와 호환되어야합니다. 예를 들어 3 채널 (RGB) 이미지의 경우 80 * 80 * 3 입니다.

3- layer활성화를 얻기위한 출력 이름 . 예를 들어 "flatten_2"레이어입니다. layer_names변수에 포함되어야하며 주어진 레이어의 이름을 나타냅니다 model.

4- batch_size는 선택적 인수입니다.

그런 다음 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

2

다음 중 하나에 해당하는 경우 :

  • 오류: InvalidArgumentError: input_X:Y is both fed and fetched
  • 여러 입력의 경우

다음 변경을 수행해야합니다.

  • outputs변수의 입력 레이어에 필터 아웃 추가
  • functors루프에서 미세한 변화

최소 예 :

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]

무엇을 의미 [x1, x2, xn, 1]합니까? 내 x1이 정의되지 않았으며 여기에서 정의한 내용을 이해하고 싶습니다.
HashRocketSyntax

@HashRocketSyntax x1x2모델의 입력입니다. 언급 한 바와 같이 모델에 2 개의 입력이있는 경우가 있습니다.
Mpizos Dimitris

1

글쎄, 다른 답변은 매우 완전하지만, 모양을 "얻는"것이 아니라 "보는"기본적인 방법이 있습니다.

그냥하세요 model.summary(). 모든 레이어와 출력 모양을 인쇄합니다. "없음"값은 가변 차원을 나타내며 첫 번째 차원은 배치 크기입니다.


이것은 레이어가 아닌 레이어의 출력 (기본 레이어에 주어진 입력)에 관한 것입니다.
mathtick
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.