Holen Sie sich Klassenbezeichnungen aus dem Keras-Funktionsmodell

75

Ich habe ein Funktionsmodell in Keras (Resnet50 aus Repo-Beispielen). Ich habe es mit ImageDataGeneratorund flow_from_directoryDaten trainiert und das Modell in einer .h5Datei gespeichert. Wenn ich anrufe, model.predicterhalte ich eine Reihe von Klassenwahrscheinlichkeiten. Aber ich möchte sie mit Klassenbezeichnungen verknüpfen (in meinem Fall - Ordnernamen). Wie kann ich sie bekommen? Ich habe festgestellt, dass ich model.predict_classesund verwenden kann model.predict_proba, aber ich habe diese Funktionen nicht im Funktionsmodell, sondern nur in Sequential.

Ledzz
quelle

Antworten:

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

Wie hier vorgeschlagen .

Emilia Apostolova
quelle
19
Dies gibt mir den Versatz, aber ich hatte bereits eine Möglichkeit, das herauszufinden ... wie bekomme ich den Markennamen?
Trejkaz
9
Keras sortiert die Beschriftungen (Namen der Ordner im Zugverzeichnis) nach alphabetischer Reihenfolge. Wenn Sie eine Liste von Labels mit dem Namen haben labels, lautet der vorhergesagte Labelname:predicted_label = sorted(labels)[y_classes]
Guillaume
1
Sie können auch aufrufen model.predict_classes, um die höchste Wahrscheinlichkeitsklasse in einem Ausgabevektor mit mehreren Klassen
abzurufen
1
Hey @ Guillaume, kannst du mich bitte auf die Dokumente verweisen, in denen dies alphabetical orderingerwähnt wird? Dies ist eine sehr wichtige Information, die ich anscheinend nirgendwo finde. danke
ameet chaubal
1
nm, fand es in directory_iterator.pyin keras_preprocessingmit Code als `Klassen = [] für subdir in sortiert (os.listdir (Verzeichnis)): Wenn os.path.isdir (os.path.join (Verzeichnis, subdir)): classes.append (subdir) `
ameet chaubal
44

Wenn man flow_from_directory verwendet, besteht das Problem darin, wie die Wahrscheinlichkeitsausgaben interpretiert werden. Wie in, wie die Wahrscheinlichkeitsausgaben und die Klassenbezeichnungen so abgebildet werden, wie flow_from_directory One-Hot-Vektoren erstellt, ist bisher nicht bekannt.

Wir können ein Wörterbuch erhalten, das die Klassenbezeichnungen dem Index des Vorhersagevektors zuordnet, den wir bei unserer Verwendung als Ausgabe erhalten

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

Die Variable label_map ist ein Wörterbuch wie dieses

{'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}

Daraus kann dann die Beziehung zwischen den Wahrscheinlichkeitsbewertungen und den Klassennamen abgeleitet werden.

Grundsätzlich können Sie dieses Wörterbuch mit diesem Code erstellen.

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

Die Variable name_id_map im obigen Code enthält auch dasselbe Wörterbuch wie das aus der class_indices-Funktion von flow_from_directory erhaltene.

Hoffe das hilft!

Lokesh Kumar
quelle
8
In meiner Interpretation beantwortet dies die eigentliche Frage - die Klassenbezeichnungen bekommen
CSquare
4
Ich stimme zu, ich denke, dies sollte die akzeptierte Antwort sein.
Shariful
2
Rettete meinen Tag <3
Rohit Swami
14

UPDATE: Dies gilt nicht mehr für neuere Keras-Versionen. Bitte verwenden Sie argmax()wie in der Antwort von Emilia Apostolova.

Die funktionalen API-Modelle haben nur die predict()Funktion, die zur Klassifizierung die Klassenwahrscheinlichkeiten zurückgeben würde. Sie können dann die wahrscheinlichsten Klassen mit der probas_to_classes()Utility-Funktion auswählen . Beispiel:

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

Dies entspricht model.predict_classes(x)dem sequentiellen Modell.

Der Grund dafür ist, dass die funktionale API allgemeinere Aufgabenklassen unterstützt, bei denen predict_classes()dies keinen Sinn ergibt .

Weitere Informationen: https://github.com/fchollet/keras/issues/2524

Bohumir Zamecnik
quelle
3
Derzeit verfügt der Code für np.utils.py (siehe github.com/fchollet/keras/blob/master/keras/utils/np_utils.py ) nicht über die Methode probas_to_classes. Haben sie dies in eine andere Funktion geändert? Bitte hilf mir.
Noobalert
1
Ich habe das gleiche Problem wie @noobalert erwähnt, es hat nicht die Funktion.
Stephen Johnson
8
Verwenden Sie y_classes = y_proba.argmax(axis=-1)stattdessen
Zach
3
AttributeError: Modul 'keras' hat kein Attribut 'np_utils'
Jürgen K.
@Zach Warum Achse = -1 und nicht 1?
WaterRocket8236
6

Zusätzlich zu @Emilia Apostolova antworten, um die Grundwahrheitsbezeichnungen von zu erhalten

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

Ruf einfach an

y_true_labels = generator.classes
Hemerson Tacon
quelle
1
Dies scheint den Labelnamen nicht zu geben, was das OP verlangt.
Moondra
Wie gesagt, es ist eine Ergänzung zur Antwort von @Emilia Apostolova. Wenn Sie diese zusätzlich zu dem, was sie gesagt hat, verwenden, können Sie die Markennamen nur mit erhalten map. Insbesondere habe ich dies verwendet, um die Verwirrungsmatrix zu erstellen. In der Zeit, als ich dies gepostet habe, hatte ich keinen Ruf, in ihrer Antwort einen Kommentar abzugeben, weil ich das hier gepostet habe.
Hemerson Tacon
2

Sie müssen den Etikettenindex verwenden, den ich habe. Hier ist, was ich für die Textklassifizierung mache:

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

Dann für Vorhersagen:

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

Das gibt:

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
Thomas Decaux
quelle
1

Es ist möglich, eine "Liste" von Beschriftungen direkt im Keras-Modell zu speichern. Auf diese Weise kann der Benutzer, der das Modell für Vorhersagen verwendet und keine anderen Informationsquellen hat, die Suche selbst durchführen. Hier ist ein Dummy-Beispiel, wie man eine "Injektion" von Etiketten durchführen kann

# 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])

Bei Verwendung für die Vorhersage gibt dieses Modell einen Tensor von Scores und einen Tensot von String-Labels zurück. Ein solches Modell kann in h5 gespeichert werden. In diesem Fall enthält die Datei die Beschriftungen. Dieses Modell kann auch in saved_model exportiert und für die Bereitstellung in der Cloud verwendet werden.

Fedor Petrov
quelle
1

Um vorhergesagte Klassen und Dateinamen mit zuzuordnen ImageDataGenerator, verwende ich:

# Data generator and prediction
test_datagen = ImageDataGenerator(rescale=1./255)
test_generator = test_datagen.flow_from_directory(
        inputpath,
        target_size=(150, 150),
        batch_size=20,
        class_mode='categorical',
        shuffle=False)
pred = model.predict_generator(test_generator, steps=len(test_generator), verbose=0)
# Get classes by max element in np (as a list)
classes = list(np.argmax(pred, axis=1))
# Get filenames (set shuffle=false in generator is important)
filenames = test_generator.filenames

Ich kann vorhergesagte Klassen und den zugehörigen Dateinamen durchlaufen, indem ich:

for f in zip(classes, filenames):
    ...
Peter
quelle