229 votes

Keras, comment obtenir la sortie de chaque couche ?

J'ai entraîné un modèle de classification binaire avec CNN, et voici mon 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))

Et ici, je veux obtenir la sortie de chaque couche comme TensorFlow, comment puis-je le faire ?

237voto

indraforyou Points 5483

Vous pouvez facilement obtenir les sorties de n'importe quelle couche en utilisant : model.layers[index].output

Pour toutes les couches, utilisez ceci :

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 : Pour simuler le Dropout, utilisez learning_phase comme 1. sur layer_outs sinon, utiliser 0.

Edit : (sur la base des commentaires)

K.function crée des fonctions tensorielles theano/tensorflow qui sont ensuite utilisées pour obtenir la sortie du graphe symbolique à partir de l'entrée.

Maintenant K.learning_phase() est nécessaire en tant qu'entrée car de nombreuses couches Keras, telles que Dropout/Batchnomalization, en dépendent pour modifier leur comportement pendant la formation et le test.

Ainsi, si vous supprimez la couche d'exclusion dans votre code, vous pouvez simplement utiliser :

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 : Plus optimisé

Je viens de réaliser que la réponse précédente n'est pas si optimisée que cela, car pour chaque évaluation de fonction, les données seront transférées de la mémoire du CPU->GPU et les calculs tensoriels doivent également être effectués pour les couches inférieures.

Au lieu de cela, cette méthode est bien meilleure, car vous n'avez pas besoin de plusieurs fonctions, mais d'une seule fonction qui vous donne la liste de toutes les sorties :

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 votes

Monsieur, votre réponse est bonne. K.function([inp]+ [K.learning_phase()], [out]) signifie dans votre code ?

0 votes

Excellente réponse, np.random.random(input_shape)[np.newaxis,...] peut également s'écrire comme suit np.random.random(input_shape)[np.newaxis,:]

0 votes

Qu'est-ce que la fonction K. ? Comment est-elle transmise au GPU (MPI ?) ? Qu'y a-t-il derrière la scène ? Comment cela se passe-t-il avec CUDA ? Où se trouve le code source ?

210voto

blue-sky Points 7469

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

Une méthode simple consiste à créer un nouveau modèle qui produira les couches qui vous intéressent :

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)

Vous pouvez également créer une fonction Keras qui renverra la sortie d'une certaine couche en fonction d'une certaine entrée, par exemple :

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]

1 votes

Si je pouvais, je vous en donnerais deux ^, Cette méthode est tellement plus pratique lorsque vous avez un tas d'entrées.

0 votes

C'est assez clair dans votre code ci-dessus mais juste pour vérifier ma compréhension : après avoir créé un modèle à partir d'un modèle existant (en supposant qu'il est déjà formé), il n'est pas nécessaire d'appeler set_weights sur le nouveau modèle. Est-ce correct ?

0 votes

Quelle est la différence entre layer_output = get_3rd_layer_output([X, 0])[0] et layer_output = get_3rd_layer_output([X, 1])[0] La documentation mentionne le mode train et le mode test

15voto

La suite me semble très simple :

model.layers[idx].output

Above est un objet tensoriel, vous pouvez donc le modifier en utilisant des opérations qui peuvent être appliquées à un objet tensoriel.

Par exemple, pour obtenir la forme model.layers[idx].output.get_shape()

idx est l'index de la couche et vous pouvez le trouver à partir de model.summary()

1 votes

Quel est le problème avec cette réponse ? Pourquoi n'a-t-elle pas été votée comme la meilleure réponse ?

8 votes

Il retourne un objet tenseur, pas un dataframe. Les objets tf sont bizarres à travailler.

3 votes

Le poster dit qu'ils veulent obtenir la sortie de chaque couche. Étant donné certaines données, comment pouvez-vous obtenir la sortie de la couche de model.layers[idx].output ?

8voto

Miladiouss Points 642

J'ai écrit cette fonction pour moi-même (dans Jupyter) et elle a été inspirée par indraforyou La réponse de l'entreprise. Il tracera automatiquement toutes les sorties des couches. Vos images doivent avoir une forme (x, y, 1) où 1 représente 1 canal. Il suffit d'appeler plot_layer_outputs(...) pour tracer.

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

0 votes

Que faire si le modèle a plusieurs entrées ? Comment spécifier les entrées ?

0 votes

Dans cette ligne : layer_outputs_list = [op([test_image, 1.]). Est-ce que 1. doit être égal à 0 ? Il semble que 1 représente la formation et 0 le test ? Ce n'est pas le cas ?

1 votes

Cela ne fonctionne pas pour moi. J'ai utilisé une image en couleur et cela me donne l'erreur suivante : InvalidArgumentError : input_2:0 est à la fois alimenté et récupéré.

0voto

Daniel Points 2149

Eh bien, les autres réponses sont très complètes, mais il existe une façon très élémentaire de "voir", et non de "comprendre" les formes.

Faites juste un model.summary() . Il imprimera toutes les couches et leurs formes de sortie. Les valeurs "Aucune" indiqueront des dimensions variables, et la première dimension sera la taille du lot.

0 votes

Il s'agit de la sortie de la couche (étant donné les entrées de la couche de base) et non de la couche.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X