J'ai formé 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 exactement comme TensorFlow, comment puis-je faire cela?
Vous pouvez facilement obtenir les résultats 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
Remarque: pour simuler un abandon, utilisez learning_phase
comme 1.
dans layer_outs
sinon utilisez 0.
.
Edit: (basé sur les commentaires)
K.function
crée les fonctions tensioanean/tensorflow qui sont ensuite utilisées pour obtenir la sortie du graphe symbolique donné en entrée.
Maintenant, K.learning_phase()
est requis en tant qu'entrée, car de nombreuses couches de Keras telles que Dropout/Batchnomalization en dépendent pour changer le comportement pendant la formation et la période de test.
Donc, si vous supprimez la couche de suppression 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 me rendre compte que la réponse précédente n’est pas optimisée, car pour chaque évaluation de fonction, les données seront transférées CPU-> mémoire GPU et les calculs de tenseur doivent également être effectués pour les couches inférieures sur-n-over.
Au lieu de cela, c'est une bien meilleure façon, car vous n'avez pas besoin de plusieurs fonctions, mais d'une seule fonction vous donnant 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
De https://keras.io/getting-started/faq/#how-can-i-obtain-the-output-of-an-intermediate-layer
Un moyen simple consiste à créer un nouveau modèle qui générera 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 couche donnée à partir d'une entrée donné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]
J'ai écrit cette fonction pour moi-même (en Jupyter) et elle s’inspire de la réponse de indraforyo . Il va tracer toutes les sorties de couche automatiquement. Vos images doivent avoir une forme (x, y, 1) où 1 représente 1 canal. Vous appelez simplement 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')
Suivre me semble très simple:
model.layers[idx].output
Ci-dessus est un objet tenseur, vous pouvez donc le modifier à l'aide d'opérations pouvant être appliquées à un objet tenseur.
Par exemple, pour obtenir la forme model.layers[idx].output.get_shape()
idx
est l'index de la couche et vous pouvez le trouver dans model.summary()
Sur la base de toutes les bonnes réponses de ce fil, j'ai écrit une bibliothèque pour récupérer le résultat de chaque couche. Il en résume toute la complexité et a été conçu pour être le plus convivial possible:
https://github.com/philipperemy/keract
Il gère presque tous les cas Edge
J'espère que ça aide!
Voulait ajouter ceci en tant que commentaire (mais ne pas avoir une assez haute réputation) pour la réponse de @ indraforyou à corriger pour le problème mentionné dans le commentaire de @ mathtick. Pour éviter l'exception InvalidArgumentError: input_X:Y is both fed and fetched.
, remplacez simplement la ligne outputs = [layer.output for layer in model.layers]
par outputs = [layer.output for layer in model.layers][1:]
, c'est-à-dire.
adapter l'exemple de travail minimal d'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. mes tentatives d'essayer des choses telles que outputs = [layer.output for layer in model.layers[1:]]
n'ont pas fonctionné.
De: 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
Eh bien, les autres réponses sont très complètes, mais il existe un moyen très simple de "voir", de "ne pas" obtenir les formes.
Il suffit de faire un model.summary()
. Il imprimera tous les calques et leurs formes de sortie. Les valeurs "Aucune" indiquent des dimensions variables et la première dimension correspond à la taille du lot.
En supposant que vous ayez:
1- Keras pré-formés model
.
2- Entrez x
sous forme d'image ou de jeu d'images. La résolution de l'image doit être compatible avec la dimension du calque d'entrée. Par exemple, 80 * 80 * pour une image à 3 canaux (RVB).
3- Le nom de la sortie layer
pour obtenir l'activation. Par exemple, couche "flatten_2". Ceci doit être inclus dans la variable layer_names
, représente le nom des couches de la variable model
donnée.
4- batch_size
est un argument optionnel.
Ensuite, vous pouvez facilement utiliser la fonction get_activation
pour obtenir l'activation de la sortie layer
pour une entrée donnée x
et préformé 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