6

Ich habe ein Netzwerk, das einen 4D-Ausgangstensor erzeugt, wobei der Wert an jeder Position in räumlichen Dimensionen (~ Pixel) als die Klassenwahrscheinlichkeiten für diese Position interpretiert werden soll. Mit anderen Worten, der Ausgang ist (num_batches, height, width, num_classes). Ich habe Etiketten der gleichen Größe, wo die echte Klasse als ein-hot codiert ist. Ich möchte den categorical-crossentropy Verlust damit berechnen.Wie man Punkt-kategorischen Crossentropie-Verlust in Keras macht?

Problem # 1: Die K.softmax Funktion erwartet einen 2D Tensor (num_batches, num_classes)

Problem # 2: Ich bin nicht sicher, wie die Verluste aus jeder Position kombiniert werden sollen. Ist es korrekt, reshape der Tensor zu (num_batches * height * width, num_classes) und dann K.categorical_crossentropy auf diesem Aufruf? Oder rufen Sie einfach K.categorical_crossentropy(num_batches, num_classes) Höhe * Breite mal und Durchschnitt der Ergebnisse?

+0

Welches Backend verwenden Sie? –

+0

@ MarcinMożejko Ich benutze TensorFlow - könnte entweder die Keras Backend API oder TF eigenen Funktionen, ist entweder in Ordnung. Vielen Dank! –

+0

Ich habe Ihre Frage beantwortet :-) –

Antwort

2

Verflachen Sie einfach den Ausgang zu einem 2D-Tensor der Größe (num_batches, height * width * num_classes). Sie können dies mit der Flatten Schicht tun. Stellen Sie sicher, dass Ihre y auf die gleiche Weise abgeflacht ist (normalerweise ist der Aufruf y = y.reshape((num_batches, height * width * num_classes)) ausreichend).

Für Ihre zweite Frage, kategorisch crossentropy über alle width*height Prognosen unter Verwendung von im Wesentlichen die gleiche wie die kategorische crossentropy für jede width*height Vorhersagen (durch die Definition von kategorischen crossentropy) gemittelt werden.

+0

Danke! Ich bin verwirrt von (num_batches, height * width * num_classes) obwohl. Ist das nicht im Wesentlichen die Berechnung der Kreuz-Entropie, als gäbe es num_batches-Samples mit height * width * num_classes-Klassen? Ich bin mir ziemlich sicher, dass ich möchte, dass jeder Punkt als ein separates Sample gezählt wird, ist das nicht dasselbe wie das Umformen zu (num_batches * height * width, num_classes)? Bitte lassen Sie mich wissen, ob die beiden mathematisch gleichwertig sind. –

+0

Sorry, kategorische Crossentropie allein wird im Wesentlichen die gleiche mathematisch sein. Aber die Verwendung zusammen mit Softmax wird nicht mathematisch gleich sein, da die Ausgabe normalisiert ist, was in meiner Antwort ein Fehltreffer ist. Ich glaube nicht, dass es möglich ist, die Stapelgröße des Eingabemittelpunkts im Modell zu ändern. Der beste Weg ist wahrscheinlich ein Workaround zu machen und eine eigene softmax-Aktivierungsfunktion zu implementieren, die die Ausgabe für jede Zelle der 'height * width' normalisiert. – oscfri

+0

Danke! Ich bin immer noch verwirrt darüber, wie man das in Arbeitscode übersetzt. Könnten Sie das ausprobieren? Ich habe ein Kopfgeld begonnen :) –

2

Gefunden this issue um meine Intuition zu bestätigen.

Kurz gesagt: Der Softmax nimmt 2D- oder 3D-Eingänge auf. Wenn sie 3D-Keras sind, nehmen sie eine solche Form an (Samples, Timedimension, Numclasses) und wenden das Softmax auf das letzte an. Aus seltsamen Gründen funktioniert das nicht für 4D-Tensoren.

Lösung: Ihre Ausgabe in eine Folge von Pixeln umformen

reshaped_output = Reshape((height*width, num_classes))(output_tensor) 

Dann bewerben Sie Ihre softmax

new_output = Activation('softmax')(reshaped_output) 

Und dann entweder Sie umformen Ihr Ziel Tensoren zu 2D oder Sie neu zu gestalten gerade die letzte Schicht in (Breite, Höhe, Anzahl_Klassen).

Sonst würde etwas, das ich versuchen würde, wenn ich nicht auf meinem Telefon jetzt war, eine zeitlich verteilt (Aktivierung ('softmax')) verwenden. Aber keine Ahnung, ob das funktionieren würde ... versuchen, später

Ich hoffe, das hilft :-)

2

Sie könnten auch nicht reshape etwas und beide softmax definieren und loss auf eigene Faust. Hier ist softmax, die auf der letzten Eingabe Dimension angewendet wird (wie in tf Backend):

def image_softmax(input): 
    label_dim = -1 
    d = K.exp(input - K.max(input, axis=label_dim, keepdims=True)) 
    return d/K.sum(d, axis=label_dim, keepdims=True) 

und hier haben Sie loss (es gibt keine Notwendigkeit, etwas neu zu gestalten):

__EPS = 1e-5 
def image_categorical_crossentropy(y_true, y_pred): 
    y_pred = K.clip(y_pred, __EPS, 1 - __EPS) 
    return -K.mean(y_true * K.log(y_pred) + (1 - y_true) * K.log(1 - y_pred)) 

Keine weiteren Reshapes brauchen.