2017-10-04 2 views
1

Disons que nous avons un réseau de neurones convolutionnel M. Je peux extraire des caractéristiques à partir d'images en utilisantextraction dernières couches de modèle keras comme sous-modèle

extractor = Model(M.inputs, M.get_layer('last_conv').output) 
features = extractor.predict(X) 

Comment puis-je obtenir le modèle qui permettra de prédire les classes utilisant features ?

Je ne peux pas utiliser les lignes suivantes car l'entrée du modèle doit être un espace réservé.

predictor = Model([M.get_layer('next_layer').input], M.outputs) 
pred = predictor.predict(features) 

Je ne peux pas utiliser K.function parce que plus tard, je veux l'utiliser dans le cadre d'un autre modèle, donc je serai prédicteur appliyng à tf.tensor, non np.array.

+0

Quel est le problème avec l'utilisation d'un espace réservé ou une couche d'entrée? C'est la bonne façon. –

+1

@MatiasValdenegro Comment empiler des couches ** entraînées ** du prédicteur sur le nouveau calque d'entrée? – eclique

+0

Avec l'API fonctionnelle, vous utilisez simplement votre modèle comme s'il s'agissait d'une couche: in = Entrée (...) inter = yourModel (in) final = Dense (10) (inter) –

Répondre

2

Ce n'est pas la plus belle solution, mais il fonctionne:

from keras.models import Sequential 
from keras.layers import Conv2D, MaxPooling2D 
from keras.layers import Dense, Dropout, Flatten 

def cnn(): 
    model = Sequential() 
    model.add(Conv2D(32, kernel_size=(3, 3), 
        activation='relu', 
        input_shape=(28, 28, 1), name='l_01')) 
    model.add(Conv2D(64, (3, 3), activation='relu', name='l_02')) 
    model.add(MaxPooling2D(pool_size=(2, 2), name='l_03')) 
    model.add(Dropout(0.25, name='l_04')) 
    model.add(Flatten(name='l_05')) 
    model.add(Dense(128, activation='relu', name='l_06')) 
    model.add(Dropout(0.5, name='l_07')) 
    model.add(Dense(10, activation='softmax', name='l_08')) 
    return model 

def predictor(input_shape): 
    model = Sequential() 
    model.add(Flatten(name='l_05', input_shape=(12, 12, 64))) 
    model.add(Dense(128, activation='relu', name='l_06')) 
    model.add(Dropout(0.5, name='l_07')) 
    model.add(Dense(10, activation='softmax', name='l_08')) 
    return model 

cnn_model = cnn() 
cnn_model.save('/tmp/cnn_model.h5') 

predictor_model = predictor(cnn_model.output.shape) 
predictor_model.load_weights('/tmp/cnn_model.h5', by_name=True) 
+0

Oui .... jusqu'à présent, c'est la seule solution que j'ai trouvée pour ce cas, en recréant exactement la partie pertinente du modèle –

+0

Oui, j'ai aussi recouru à la reconstruction du prédicteur et du chargement des poids, 'by_name' est utile, mais je pense qu'il doit y avoir un nettoyeur Je vais accepter la réponse si nous ne trouvons pas le meilleur bientôt. – eclique

0

Cela dépend de ce que vous voulez faire.

  • Si vous allez jeter l'extracteur de fonction après
  • Si vous envisagez de formation de l'extracteur de caractéristiques plus tard

Si vous allez utiliser les fonctions extraites mais vous n'avez pas l'intention sur la formation du modèle utilisé pour les générer, vous pouvez utiliser la méthode pour obtenir prédire les caractéristiques que vous avez fait:

features = extractor.predict(X) 

puis enregistrez la sortie vers un fichier (ou np.save cPickle ou autre). Après cela, vous pouvez utiliser ce nouveau jeu de données comme entrée d'un nouveau modèle.

Si vous envisagez de formation de l'extracteur de caractéristiques plus tard, vous aurez besoin d'empiler les deux réseaux comme on le voit ici avec vgg comme extracteur de caractéristiques https://github.com/fchollet/keras/issues/4576:

img_width, img_height = 150, 150 
vgg16_model = VGG16(include_top=False, weights='imagenet') 

input = Input(batch_shape=vgg16_model.output_shape) 
x = GlobalAveragePooling2D()(input) 
x = Dense(256, activation='relu')(x) 
x = Dropout(0.5)(x) 
predict = Dense(1, activation='sigmoid')(x) 
top_model = Model(input, predict) 

top_model.load_weights(os.path.join(data_path, 'VGG16Classifier.hdf5')) 

input = Input(shape=(3, img_width, img_height)) 
x = vgg16_model(input) 
predict = top_model(x) 
model = Model(input, predict) 

PS: Cet exemple utilise des premiers canaux commande. Si vous utilisez tensorflow vous devez changer la forme pour la forme = (img_width, img_height, 3)

+0

Je suppose que je peux voir la solution dans le code que vous avez fourni. Je serai en mesure de le tester plus tard. Mais le problème principal est dans le prédicteur, pas extracteur. Voulez-vous dire prédicteur? Je vais jeter l'extracteur et j'utiliserai uniquement des poids fixes dans le prédicteur (sans l'entraîner). – eclique

+0

Si vous voulez jeter l'extracteur c'est simple, il suffit d'obtenir les données de sortie du modèle. Quand je dis "prédire", j'utilise l'extracteur.prédict comme pour obtenir sa sortie. Après cette sortie vous êtes fondamentalement avec un nouvel ensemble de données comme un autre.Construisez votre modèle symbolique avec keras/tensorflow et transmettez les données dans la méthode d'ajustement du modèle comme s'il s'agissait d'un autre ensemble de données avec un vecteur de carte-> label – maz

+1

Je charge les caractéristiques de extractor.predict (X) comme toute autre donnée. Le problème est d'obtenir la part du ** modèle symbolique du prédicteur ** avec les poids formés. Malheureusement, votre réponse ne résout pas ce problème. :( – eclique