Ich versuche, ein CNN zu trainieren, um Text nach Themen zu kategorisieren. Wenn ich binäre Kreuzentropie verwende, erhalte ich eine Genauigkeit von ~ 80%, bei kategorialer Kreuzentropie eine Genauigkeit von ~ 50%.
Ich verstehe nicht, warum das so ist. Es ist ein Problem mit mehreren Klassen. Bedeutet das nicht, dass ich eine kategoriale Kreuzentropie verwenden muss und dass die Ergebnisse mit binärer Kreuzentropie bedeutungslos sind?
model.add(embedding_layer)
model.add(Dropout(0.25))
# convolution layers
model.add(Conv1D(nb_filter=32,
filter_length=4,
border_mode='valid',
activation='relu'))
model.add(MaxPooling1D(pool_length=2))
# dense layers
model.add(Flatten())
model.add(Dense(256))
model.add(Dropout(0.25))
model.add(Activation('relu'))
# output layer
model.add(Dense(len(class_id_index)))
model.add(Activation('softmax'))
Dann kompiliere ich es entweder so oder benutze es categorical_crossentropy
als Verlustfunktion:
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
oder
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
Intuitiv macht es Sinn, warum ich kategoriale Kreuzentropie verwenden möchte. Ich verstehe nicht, warum ich mit binären Ergebnissen gute und mit kategorialen schlechte Ergebnisse erhalte.
machine-learning
keras
neural-network
deep-learning
conv-neural-network
Daniel Messias
quelle
quelle
categorical_crossentropy
. Auch Beschriftungen müssen in das kategoriale Format konvertiert werden. Sehen Sieto_categorical
, um dies zu tun. Siehe auch Definitionen von kategorialen und binären Crossentropien hier .categorical_crossentropy
. Wenn Sie zwei Klassen haben, werden diese wie0, 1
in binären Beschriftungen und10, 01
im kategorialen Beschriftungsformat dargestellt.Dense(1, activation='softmax')
für die binäre Klassifizierung ist einfach falsch. Denken Sie daran, dass die Softmax-Ausgabe eine Wahrscheinlichkeitsverteilung ist, die sich zu eins summiert. Wenn Sie nur ein Ausgangsneuron mit binärer Klassifizierung haben möchten, verwenden Sie Sigmoid mit binärer Kreuzentropie.Antworten:
Der Grund für diese offensichtliche Leistungsdiskrepanz zwischen kategorialer und binärer Kreuzentropie ist, was Benutzer xtof54 bereits in seiner Antwort unten angegeben hat , dh:
Ich möchte näher darauf eingehen, das eigentliche zugrunde liegende Problem aufzeigen, es erklären und Abhilfe schaffen.
Dieses Verhalten ist kein Fehler. Der zugrunde liegende Grund ist eine ziemlich subtile und nicht dokumentierte Frage, wie Keras tatsächlich errät, welche Genauigkeit abhängig von der von Ihnen ausgewählten Verlustfunktion verwendet werden soll, wenn Sie sie einfach
metrics=['accuracy']
in Ihre Modellzusammenstellung einbeziehen. Mit anderen Worten, während Ihrer ersten Kompilierungsoptionist gültig, dein zweiter:
wird nicht das produzieren, was Sie erwarten, aber der Grund ist nicht die Verwendung der binären Kreuzentropie (die zumindest im Prinzip eine absolut gültige Verlustfunktion ist).
Warum ist das so? Wenn Sie den Quellcode der Metriken überprüfen , definiert Keras keine einzelne Genauigkeitsmetrik, sondern mehrere verschiedene, darunter
binary_accuracy
undcategorical_accuracy
. Was unter der Haube passiert, ist, dass Keras (fälschlicherweise ...), da Sie die binäre Kreuzentropie als Verlustfunktion ausgewählt und keine bestimmte Genauigkeitsmetrik angegeben haben, darauf schließen lässt, dass Sie daran interessiert sindbinary_accuracy
, und dies ist, was es zurückgibt - während in der Tat interessieren Sie sich für diecategorical_accuracy
.Lassen Sie uns anhand des MNIST CNN-Beispiels in Keras mit der folgenden Änderung überprüfen, ob dies der Fall ist :
Um dies zu beheben, dh um tatsächlich binäre Kreuzentropie als Ihre Verlustfunktion zu verwenden (wie gesagt, zumindest im Prinzip nichts Falsches daran), während Sie dennoch die für das jeweilige Problem erforderliche kategoriale Genauigkeit erhalten, sollten Sie
categorical_accuracy
in der Modellzusammenstellung wie folgt:Im MNIST-Beispiel sind nach dem Training, Bewerten und Vorhersagen des Testsatzes, wie oben gezeigt, die beiden Metriken jetzt dieselben, wie sie sein sollten:
Systemkonfiguration:
UPDATE : Nach meinem Beitrag stellte ich fest, dass dieses Problem bereits in dieser Antwort identifiziert wurde .
quelle
loss='categorical_crossentropy', metrics=['categorical_accuracy']
für die Klassifizierung mehrerer Klassen? Dies wäre meine IntuitionEs hängt alles von der Art des Klassifizierungsproblems ab, mit dem Sie sich befassen. Es gibt drei Hauptkategorien
Im ersten Fall sollte eine binäre Kreuzentropie verwendet werden und Ziele sollten als One-Hot-Vektoren codiert werden.
Im zweiten Fall sollte eine kategoriale Kreuzentropie verwendet werden und Ziele sollten als One-Hot-Vektoren codiert werden.
Im letzten Fall sollte eine binäre Kreuzentropie verwendet werden und Ziele sollten als One-Hot-Vektoren codiert werden. Jedes Ausgangsneuron (oder jede Ausgangseinheit) wird als separate zufällige binäre Variable betrachtet, und der Verlust für den gesamten Ausgangsvektor ist das Produkt des Verlusts einzelner binärer Variablen. Daher ist es das Produkt der binären Kreuzentropie für jede einzelne Ausgabeeinheit.
Die binäre Kreuzentropie ist definiert als
und kategoriale Kreuzentropie ist definiert als
Wo
c
läuft der Index über die Anzahl der Klassen?quelle
c
Index in der binären Kreuzentropieformel redundant, er muss nicht vorhanden sein (da es nur 2 Klassen gibt und die Wahrscheinlichkeit jeder Klasse eingebettet isty(x)
. Andernfalls sollten diese Formeln korrekt sein, aberlog
Ich bin auf ein "invertiertes" Problem gestoßen - ich habe gute Ergebnisse mit kategorialer Kreuzentropie (mit 2 Klassen) und schlechte mit binärer Kreuzentropie erzielt. Es scheint, dass das Problem mit der falschen Aktivierungsfunktion war. Die richtigen Einstellungen waren:
binary_crossentropy
: Sigmoidaktivierung, skalares Zielcategorical_crossentropy
: Softmax-Aktivierung, One-Hot-codiertes Zielquelle
Es ist wirklich ein interessanter Fall. Tatsächlich ist in Ihrem Setup die folgende Aussage wahr:
Dies bedeutet, dass Ihre Verluste bis zu einem konstanten Multiplikationsfaktor gleichwertig sind. Das seltsame Verhalten, das Sie während einer Trainingsphase beobachten, könnte ein Beispiel für ein folgendes Phänomen sein:
adam
die Lernrate einen viel geringeren Wert als zu Beginn des Trainings (dies liegt an der Natur dieses Optimierers). Dies verlangsamt das Training und verhindert, dass Ihr Netzwerk z. B. ein schlechtes lokales Minimum weniger möglich macht.Deshalb könnte dieser konstante Faktor bei helfen
binary_crossentropy
. Nach vielen Epochen ist der Wert der Lernrate größer als imcategorical_crossentropy
Fall. Normalerweise starte ich das Training (und die Lernphase) einige Male neu, wenn ich ein solches Verhalten bemerke oder / und ein Klassengewicht nach folgendem Muster anpasse:Dies führt zu einem Verlust aus weniger häufigen Klassen, der den Einfluss eines dominanten Klassenverlusts zu Beginn eines Trainings und in einem weiteren Teil eines Optimierungsprozesses ausgleicht.
BEARBEITEN:
Eigentlich - ich habe das überprüft, obwohl im Falle von Mathematik:
sollte gelten - falls
keras
dies nicht der Fall ist, dakeras
automatisch alle Ausgänge normalisiert werden, um eine Summe zu erhalten1
. Dies ist der eigentliche Grund für dieses seltsame Verhalten, da im Falle einer Mehrfachklassifizierung eine solche Normalisierung einem Training schadet.quelle
Nachdem ich die Antwort von @Marcin kommentiert habe, habe ich einen meiner Schülercodes genauer überprüft, bei dem ich das gleiche seltsame Verhalten festgestellt habe, selbst nach nur 2 Epochen! (Also @ Marcins Erklärung war in meinem Fall nicht sehr wahrscheinlich).
Und ich fand, dass die Antwort eigentlich sehr einfach ist: Die mit der Keras-Methode berechnete Genauigkeit
evaluate
ist einfach falsch, wenn binäre_kreuzentropie mit mehr als 2 Beschriftungen verwendet wird. Sie können dies überprüfen, indem Sie die Genauigkeit selbst neu berechnen (rufen Sie zuerst die Keras-Methode "Vorhersagen" auf und berechnen Sie dann die Anzahl der korrekten Antworten, die von Vorhersagen zurückgegeben werden): Sie erhalten die wahre Genauigkeit, die viel niedriger ist als die von Keras "Auswerten".quelle
Ein einfaches Beispiel unter einer Einstellung für mehrere Klassen zur Veranschaulichung
Angenommen, Sie haben 4 Klassen (onehot codiert) und unten ist nur eine Vorhersage
true_label = [0,1,0,0] prognostiziertes_Label = [0,0,1,0]
Wenn Sie categoryical_crossentropy verwenden, ist die Genauigkeit nur 0, es ist nur wichtig, ob Sie die betreffende Klasse richtig machen.
Bei Verwendung von binary_crossentropy wird die Genauigkeit jedoch für alle Klassen berechnet. Für diese Vorhersage beträgt sie 50%. und das Endergebnis ist der Mittelwert der individuellen Genauigkeiten für beide Fälle.
Es wird empfohlen, kategoriale_Crossentropie für Probleme mit mehreren Klassen (Klassen schließen sich gegenseitig aus), binäre_Crossentropie für Probleme mit mehreren Bezeichnungen zu verwenden.
quelle
Da es sich um ein Problem mit mehreren Klassen handelt, müssen Sie die kategoriale Kreuzentropie verwenden. Die binäre Kreuzentropie führt zu falschen Ergebnissen und bewertet höchstwahrscheinlich nur die ersten beiden Klassen.
50% für ein Problem mit mehreren Klassen können je nach Anzahl der Klassen recht gut sein. Wenn Sie n Klassen haben, ist 100 / n die Mindestleistung, die Sie durch Ausgabe einer zufälligen Klasse erzielen können.
quelle
Wenn Sie den
categorical_crossentropy
Verlust verwenden, sollten Ihre Ziele in einem kategorialen Format vorliegen (z. B. wenn Sie 10 Klassen haben, sollte das Ziel für jede Stichprobe ein 10-dimensionaler Vektor sein, der aus Nullen besteht, mit Ausnahme einer 1 im Index, der der Klasse der Klasse entspricht Stichprobe).quelle
Schauen Sie sich die Gleichung an, mit der Sie diese binäre Kreuzentropie finden können nicht nur die Bezeichnung = 1, vorhergesagt = 0, sondern auch die Bezeichnung = 0, vorhergesagt = 1 bestraft.
Eine kategoriale Kreuzentropie bestraft jedoch nur das Label = 1, aber das vorhergesagte = 1. Deshalb gehen wir davon aus, dass es nur EIN Label gibt, das positiv ist.
quelle
Sie übergeben ein Zielarray mit Form (x-dim, y-dim), während Sie es als Verlust verwenden
categorical_crossentropy
.categorical_crossentropy
erwartet, dass Ziele binäre Matrizen (1s und 0s) mit Form (Samples, Klassen) sind. Wenn Ihre Ziele ganzzahlige Klassen sind, können Sie sie über Folgendes in das erwartete Format konvertieren.Alternativ können Sie
sparse_categorical_crossentropy
stattdessen die Verlustfunktion verwenden, die ganzzahlige Ziele erwartet.quelle
Die binary_crossentropy (y_target, y_predict) muss bei binären Klassifizierungsproblemen nicht angewendet werden. .
Im Quellcode von binary_crossentropy ()
nn.sigmoid_cross_entropy_with_logits(labels=target, logits=output)
wurde tatsächlich die TensorFlow-Funktion verwendet. In der Dokumentation heißt es:quelle