webentwicklung-frage-antwort-db.com.de

Holen Sie sich Klassen-Labels vom Keras-Funktionsmodell

Ich habe ein Funktionsmodell in Keras (Resnet50 aus Repo-Beispielen). Ich habe es mit ImageDataGenerator- und flow_from_directory-Daten trainiert und das Modell in der .h5-Datei gespeichert. Wenn ich model.predict anrufe, erhalte ich ein Array von Klassenwahrscheinlichkeiten. Ich möchte sie jedoch mit Klassenbezeichnungen (in meinem Fall - Ordnernamen) verknüpfen. Wie kann ich sie bekommen? Ich habe festgestellt, dass ich model.predict_classes und model.predict_proba verwenden könnte, aber ich habe diese Funktionen nicht im Funktionsmodell, nur in Sequential.

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

Wie vorgeschlagen hier .

35

Wenn man flow_from_directory verwendet, besteht das Problem darin, die Wahrscheinlichkeitsausgaben zu interpretieren. Wie man die Wahrscheinlichkeitsausgaben und die Klassenbezeichnungen so abbildet, wie flow_from_directory One-Hot-Vektoren erzeugt, ist im Vorhinein nicht bekannt.

Wir können ein Wörterbuch erhalten, das die Klassenbezeichnungen auf den Index des Vorhersagevektors abbildet, den wir als Ausgabe erhalten, wenn wir ihn verwenden 

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 Wahrscheinlichkeitswerten und 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!

17
Lokesh Kumar

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 Funktion predict(), die zur Klassifizierung die Klassenwahrscheinlichkeiten zurückgibt. Sie können dann die wahrscheinlichsten Klassen mit der Dienstfunktion probas_to_classes() auswählen. Beispiel:

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

Dies ist äquivalent zu model.predict_classes(x) im sequentiellen Modell.

Der Grund dafür ist, dass die funktionale API eine allgemeinere Klasse von Aufgaben unterstützt, bei denen predict_classes() nicht sinnvoll wäre.

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

7

Zusätzlich zu @Emilia Apostolova antworten Sie auf die Bodenwahrungsetiketten 

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

ruf einfach an

y_true_labels = generator.classes
1
Hemerson Tacon

Sie müssen den Etikettenindex verwenden, den Sie haben, hier, was ich zur 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
1
Thomas Decaux

Es ist möglich, eine "Liste" von Etiketten 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 Etiketten "injizieren" 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])

Wenn dieses Modell für die Vorhersage verwendet wird, gibt es den Tensor der Kerben und den Tensot der Stringslabels zurück. Ein solches Modell kann in h5 gespeichert werden. In diesem Fall enthält die Datei die Etiketten. Dieses Modell kann auch nach save_model exportiert und für die Bereitstellung in der Cloud verwendet werden.

0
Fedor Petrov

Um vorhergesagte Klassen und Dateinamen mit ImageDataGenerator abzubilden, 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 die vorhergesagten Klassen und den zugehörigen Dateinamen durchlaufen, indem ich Folgendes verwende:

for f in Zip(classes, filenames):
    ...
0
Peter