web-dev-qa-db-fra.com

Obtenir les étiquettes de classe du modèle fonctionnel de Keras

J'ai un modèle fonctionnel dans Keras (Resnet50 à partir d'exemples de pension). Je l'ai entraîné avec les données ImageDataGenerator et flow_from_directory et ai enregistré le modèle dans le fichier .h5. Lorsque j'appelle model.predict, je reçois un tableau de probabilités de classe. Mais je veux les associer à des étiquettes de classe (dans mon cas - les noms de dossiers). Comment puis-je les obtenir? J'ai découvert que je pouvais utiliser model.predict_classes et model.predict_proba, mais je n'ai pas ces fonctions dans le modèle fonctionnel, uniquement dans le séquentiel.

35
Ledzz
y_prob = model.predict(x) 
y_classes = y_prob.argmax(axis=-1)

Comme suggéré ici .

35
Emilia Apostolova

Quand on utilise flow_from_directory, le problème est de savoir comment interpréter les résultats de probabilité. Comme dans, la manière de mapper les sorties de probabilité et les étiquettes de classe, comme comment flow_from_directory crée des vecteurs one-hot, n'est pas connue auparavant.

Nous pouvons obtenir un dictionnaire qui mappe les étiquettes de classe sur l'index du vecteur de prédiction que nous obtenons en sortie lorsque nous utilisons 

generator= train_datagen.flow_from_directory("train", batch_size=batch_size)
label_map = (generator.class_indices)

La variable label_map est un dictionnaire comme celui-ci

{'class_14': 5, 'class_10': 1, 'class_11': 2, 'class_12': 3, 'class_13': 4, 'class_2': 6, 'class_3': 7, 'class_1': 0, 'class_6': 10, 'class_7': 11, 'class_4': 8, 'class_5': 9, 'class_8': 12, 'class_9': 13}

On peut alors déduire la relation entre les scores de probabilité et les noms de classe.

Fondamentalement, vous pouvez créer ce dictionnaire avec ce code.

from glob import glob
class_names = glob("*") # Reads all the folders in which images are present
class_names = sorted(class_names) # Sorting them
name_id_map = dict(Zip(class_names, range(len(class_names))))

La variable name_id_map dans le code ci-dessus contient également le même dictionnaire que celui obtenu à partir de la fonction class_indices de flow_from_directory.

J'espère que cela t'aides!

17
Lokesh Kumar

UPDATE: Ceci n'est plus valable pour les nouvelles versions de Keras. Veuillez utiliser argmax() comme dans la réponse d'Emilia Apostolova.

Les modèles d'API fonctionnels ont uniquement la fonction predict() qui, pour la classification, renverrait les probabilités de classe. Vous pouvez ensuite sélectionner les classes les plus probables à l'aide de la fonction utilitaire probas_to_classes(). Exemple:

y_proba = model.predict(x)
y_classes = keras.np_utils.probas_to_classes(y_proba)

Ceci équivaut à model.predict_classes(x) sur le modèle séquentiel.

La raison en est que l'API fonctionnelle prend en charge une classe de tâches plus générale dans laquelle predict_classes() n'aurait aucun sens.

Plus d'infos: https://github.com/fchollet/keras/issues/2524

7
Bohumir Zamecnik

En plus de @Emilia Apostolova répondre pour obtenir les étiquettes de vérité au sol de 

generator = train_datagen.flow_from_directory("train", batch_size=batch_size)

il suffit d'appeler

y_true_labels = generator.classes
1
Hemerson Tacon

Vous devez utiliser l'index des étiquettes que vous avez, voici ce que je fais pour la classification du texte:

# data labels = [1, 2, 1...]
labels_index = { "website" : 0, "money" : 1 ....} 
# to feed model
label_categories = to_categorical(np.asarray(labels)) 

Ensuite, pour les prédictions:

texts = ["hello, rejoins moi sur skype", "bonjour comment ça va ?", "tu me donnes de l'argent"]

sequences = tokenizer.texts_to_sequences(texts)

data = pad_sequences(sequences, maxlen=MAX_SEQUENCE_LENGTH)

predictions = model.predict(data)

t = 0

for text in texts:
    i = 0
    print("Prediction for \"%s\": " % (text))
    for label in labels_index:
        print("\t%s ==> %f" % (label, predictions[t][i]))
        i = i + 1
    t = t + 1

Cela donne:

Prediction for "hello, rejoins moi sur skype": 
    website ==> 0.759483
    money ==> 0.037091
    under ==> 0.010587
    camsite ==> 0.114436
    email ==> 0.075975
    abuse ==> 0.002428
Prediction for "bonjour comment ça va ?": 
    website ==> 0.433079
    money ==> 0.084878
    under ==> 0.048375
    camsite ==> 0.036674
    email ==> 0.369197
    abuse ==> 0.027798
Prediction for "tu me donnes de l'argent": 
    website ==> 0.006223
    money ==> 0.095308
    under ==> 0.003586
    camsite ==> 0.003115
    email ==> 0.884112
    abuse ==> 0.007655
1
Thomas Decaux

Il est possible de sauvegarder directement une "liste" d'étiquettes dans le modèle keras. Ainsi, l'utilisateur qui utilise le modèle pour les prédictions et ne dispose d'aucune autre source d'informations peut effectuer la recherche lui-même. Voici un exemple factice de la façon dont on peut effectuer une "injection" d'étiquettes

# assume we get labels as list
labels = ["cat","dog","horse","tomato"]
# here we start building our model with input image 299x299 and one output layer
xx = Input(shape=(299,299,3))
flat = Flatten()(xx)
output = Dense(shape=(4))(flat)
# here we perform injection of labels
tf_labels = tf.constant([labels],dtype="string")
tf_labels = tf.tile(labels,[tf.shape(xx)[0],1])
output_labels = Lambda(lambda x: tf_labels,name="label_injection")(xx)
#and finaly creating a model
model=tf.keras.Model(xx,[output,output_labels])

Lorsqu'il est utilisé pour la prédiction, ce modèle renvoie le tenseur des scores et le tensot des étiquettes de chaîne. Un modèle comme celui-ci peut être enregistré en h5. Dans ce cas, le fichier contient les étiquettes. Ce modèle peut également être exporté vers saved_model et utilisé pour servir dans le nuage.

0
Fedor Petrov