केरस, प्रत्येक परत का आउटपुट कैसे प्राप्त करें?


155

मैंने सीएनएन के साथ एक द्विआधारी वर्गीकरण मॉडल प्रशिक्षित किया है, और यहां मेरा कोड है

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 थीनो / ​​टेंसरफ़्लो टेंसर फ़ंक्शंस बनाता है जो बाद में इनपुट दिए गए प्रतीकात्मक ग्राफ से आउटपुट प्राप्त करने के लिए उपयोग किया जाता है।

अब K.learning_phase()एक इनपुट के रूप में आवश्यक है क्योंकि ड्रॉपआउट / बाटचोमलाइज़ेशन जैसी कई केरस परतें प्रशिक्षण और परीक्षण समय के दौरान व्यवहार को बदलने के लिए इस पर निर्भर करती हैं।

इसलिए यदि आप अपने कोड में ड्रॉपआउट लेयर को हटाते हैं तो आप आसानी से उपयोग कर सकते हैं:

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: अधिक अनुकूलित

मुझे अभी पता चला है कि पिछला उत्तर यह नहीं है कि प्रत्येक फ़ंक्शन मूल्यांकन के लिए डेटा को सीपीयू -> जीपीयू मेमोरी में स्थानांतरित कर दिया जाएगा और साथ ही टेंसरों की गणना को निचली परतों के लिए ओवर-एन-ओवर करने की आवश्यकता है।

इसके बजाय यह एक बेहतर तरीका है क्योंकि आपको कई कार्यों की आवश्यकता नहीं है, लेकिन एक ही फ़ंक्शन आपको सभी आउटपुट की सूची प्रदान करता है:

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])आपके कोड में क्या मतलब है?
गोइंगमवाय

उत्कृष्ट उत्तर, के np.random.random(input_shape)[np.newaxis,...]रूप में भी लिखा जा सकता हैnp.random.random(input_shape)[np.newaxis,:]
टॉम

K.function क्या है? यह GPU (MPI?) में कैसे पास हुआ? दृश्य के पीछे क्या है? यह कैसे CUDA के साथ बातचीत है? स्रोत कोड कहां है?
स्टड बोडिक

3
@StavBodik मॉडल K.function यहां उपयोग करने वाले प्रेडिक्शन फंक्शन का निर्माण करता है , और प्रेडिक्ट इसका उपयोग यहां प्रिव्यू लूप में करता है । बैच आकार पर भविष्यवाणी करें (यदि यह 32 तक डिफ़ॉल्ट सेट नहीं है) लेकिन GPU मेमोरी पर बाधाओं को कम करने के लिए thats। इसलिए मुझे यकीन नहीं है कि आप क्यों देख रहे हैं कि model.predictयह तेज है।
indraforyou

1
यह हो रहा है: InvalidArgumentError: S_input_39: 0 दोनों खिलाया और प्राप्त किया जाता है। ... विचारों वाला कोई?
मैथिक

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)

वैकल्पिक रूप से, आप एक केरस फ़ंक्शन का निर्माण कर सकते हैं जो एक निश्चित इनपुट के दिए गए एक निश्चित लेयर का आउटपुट लौटाएगा, उदाहरण के लिए:

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]

अगर मैं आपको दो ^ दे सकता था, तो जब आप इनपुट का एक समूह है, तो यह तरीका बहुत अधिक सुविधाजनक है।
डैन एरेज़

यह ऊपर दिए गए आपके कोड से बहुत स्पष्ट है, लेकिन मेरी समझ को दोबारा जांचने के लिए: मौजूदा मॉडल से एक मॉडल बनाने के बाद (यह पहले से प्रशिक्षित है), नए मॉडल पर set_weights को कॉल करने की आवश्यकता नहीं है। क्या वो सही है?
JZ

डॉक्स layer_output = get_3rd_layer_output([X, 0])[0]और layer_output = get_3rd_layer_output([X, 1])[0]ट्रेन मोड और टेस्ट मोड के बीच अंतर क्या है
जेसन

क्षमा करें, क्या आप मुझे बता सकते हैं कि यह मॉडल वास्तव में क्या करता है? क्या आपको इसे प्रशिक्षित करना है? मैं किसी भी आरेख की कल्पना नहीं कर सकता। आप किसी अन्य मॉडल की इनपुट परत जोड़ते हैं, फिर आउटपुट के रूप में उस अन्य मॉडल की एक यादृच्छिक मध्यस्थ परत जोड़ते हैं, और उस पर इनपुट फ़ीड करते हैं? मूल मॉडल को खिलाने के बजाय ऐसा क्यों करते हैं और इसमें किसी भी मध्यस्थ परत तक सीधी पहुंच प्राप्त करते हैं? यह अतिरिक्त अजीब मॉडल क्यों बनाएं? और क्या यह आउटपुट को प्रभावित नहीं करेगा? क्या यह सीखने या प्रशिक्षण की आवश्यकता नहीं होगी, या परत अपने स्वयं के वजन को मूल मॉडल से प्रशिक्षित पूर्व लाता है?
7

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

मैंने यह फंक्शन खुद के लिए (जुपिटर में) लिखा था और यह indraforyou के जवाब से प्रेरित था । यह सभी लेयर आउटपुट को स्वचालित रूप से प्लॉट करेगा। आपकी छवियों में एक (x, y, 1) आकार होना चाहिए, जहां 1 1 चैनल के लिए खड़ा है। आप बस प्लॉट करने के लिए प्लॉट_लेयर_आउटपुट (...) कहते हैं।

%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 खड़ा है? है ना?
कोंगसी

यह मेरे लिए काम नहीं कर रहा है। मैंने एक रंगीन छवि का उपयोग किया है और यह मुझे त्रुटि दे रही है: InvalidArgumentError: input_2: 0 दोनों को खिलाया और लाया गया है।
वैभव के

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

लिंक पदावनत है।
सईद


5

इसे एक टिप्पणी के रूप में जोड़ना चाहते थे (लेकिन इसमें पर्याप्त उच्च प्रतिनिधि नहीं है) @ गणित की टिप्पणी में वर्णित मुद्दे के लिए सही करने के लिए @ 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 की टिप्पणी के आधार पर: मेरा मॉडल सिर्फ 3 लेयर्स है (शब्द एम्बेडिंग - BiLSTM - CRF), इसलिए मुझे लगता है कि मुझे लेयर को बाहर करना था [0] क्योंकि यह तब से है बस एम्बेडिंग और एक सक्रियण नहीं होना चाहिए, है ना?
केमुनरो

@MpizosDimitris हाँ यह सही है, लेकिन @indraforyou (जो मैं संशोधन कर रहा था) द्वारा प्रदान किए गए उदाहरण में, यह मामला था। @KMunro अगर मैं सही तरीके से समझ रहा हूं, तो इसका कारण यह है कि आप पहली परत के अपने आउटपुट के बारे में परवाह नहीं करते हैं, क्योंकि यह केवल एम्बेडिंग शब्द का आउटपुट है, जो कि केवल शब्द ही है जो टेंसर रूप में एम्बेड कर रहा है (जो कि बस है आपके kerasमॉडल के "नेटवर्क" भाग में इनपुट )। आपका शब्द एम्बेडिंग परत यहां दिए गए उदाहरण में इनपुट परत के बराबर है।
कामकम

3

आपके पास यह मानते हुए:

1- केरस पूर्व प्रशिक्षित model

2- xइमेज या इमेज के सेट के रूप में इनपुट । छवि का रिज़ॉल्यूशन इनपुट परत के आयाम के साथ संगत होना चाहिए। उदाहरण के लिए 3-चैनलों (RGB) छवि के लिए 80 * 80 * 3

3- layerएक्टिवेशन पाने के लिए आउटपुट का नाम । उदाहरण के लिए, "flatten_2" परत। इसे layer_namesचर में शामिल किया जाना चाहिए , दिए गए परतों के नाम का प्रतिनिधित्व करता है model

4- batch_sizeएक वैकल्पिक तर्क है।

फिर आप दिए गए इनपुट और पूर्व-प्रशिक्षित get_activationके लिए आउटपुट की सक्रियता प्राप्त करने के लिए आसानी से फ़ंक्शन का उपयोग कर सकते हैं :layerxmodel

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 x1और x2मॉडल के इनपुट हैं। जैसा कि कहा गया है कि आपको अपने मॉडल पर 2 इनपुट मिले हैं।
मपीज़ोस दिमित्रिस

1

ठीक है, अन्य उत्तर बहुत पूर्ण हैं, लेकिन "देखने" के लिए एक बहुत ही मूल तरीका है, आकृतियों को "प्राप्त" करने के लिए नहीं।

बस एक करो model.summary()। यह सभी परतों और उनके आउटपुट आकृतियों को प्रिंट करेगा। "कोई नहीं" मान चर आयामों को इंगित करेगा, और पहला आयाम बैच आकार होगा।


यह परत के उत्पादन के बारे में है (आधार परत को दिए गए इनपुट) परत नहीं।
मैथिक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.