Was ist der Unterschied zwischen sparse_softmax_cross_entropy_with_logits und softmax_cross_entropy_with_logits?

111

Ich bin kürzlich auf tf.nn.sparse_softmax_cross_entropy_with_logits gestoßen und kann nicht herausfinden, was der Unterschied zu tf.nn.softmax_cross_entropy_with_logits ist .

Der einzige Unterschied ist, dass Trainingsvektoren ysein one-hot kodierten bei der Verwendung sparse_softmax_cross_entropy_with_logits?

Beim Lesen der API konnte ich keinen anderen Unterschied feststellen als softmax_cross_entropy_with_logits. Aber warum brauchen wir dann die zusätzliche Funktion?

Sollte nicht softmax_cross_entropy_with_logitsdie gleichen Ergebnisse liefern wie sparse_softmax_cross_entropy_with_logitswenn es mit One-Hot-codierten Trainingsdaten / -vektoren geliefert wird?

daniel451
quelle
1
Ich bin daran interessiert, einen Vergleich ihrer Leistung zu sehen, wenn beide verwendet werden können (z. B. mit exklusiven Bildetiketten). Ich würde erwarten, dass die Version mit geringer Dichte effizienter ist, zumindest was den Speicher betrifft.
Yibo Yang
1
Siehe auch diese Frage , in der alle Kreuzentropiefunktionen im Tensorfluss behandelt werden (es stellt sich heraus, dass es viele davon gibt).
Maxim

Antworten:

175

Es ist praktisch , zwei verschiedene Funktionen zu haben , da sie das gleiche Ergebnis liefern.

Der Unterschied ist einfach:

  • Für sparse_softmax_cross_entropy_with_logitsEtiketten müssen die Form haben [batch_size] und die dtype int32 oder int64. Jedes Etikett ist ein int im Bereich [0, num_classes-1].
  • Für softmax_cross_entropy_with_logitsmuss Etiketten haben die Form [batch_size, num_classes] und dtype float32 oder float64.

Die in verwendeten Labels softmax_cross_entropy_with_logitssind die einzige heiße Version der in verwendeten Labels sparse_softmax_cross_entropy_with_logits.

Ein weiterer kleiner Unterschied ist, dass sparse_softmax_cross_entropy_with_logitsSie mit -1 als Etikett angeben können, um einen Verlust 0auf diesem Etikett zu haben.

Olivier Moindrot
quelle
15
Ist die -1 richtig? In der Dokumentation heißt es: "Jeder Eintrag in Labels muss ein Index in [0, num_classes) sein. Andere Werte lösen eine Ausnahme aus, wenn diese Operation auf der CPU ausgeführt wird, und geben NaN für entsprechende Verlust- und Gradientenzeilen auf der GPU zurück."
user1761806
1
[0, num_classes) = [0, num_classes-1]
Karthik C
24

Ich möchte der akzeptierten Antwort nur zwei Dinge hinzufügen, die Sie auch in der TF-Dokumentation finden.

Zuerst:

tf.nn.softmax_cross_entropy_with_logits

HINWEIS: Während sich die Klassen gegenseitig ausschließen, müssen ihre Wahrscheinlichkeiten nicht sein. Erforderlich ist lediglich, dass jede Etikettenreihe eine gültige Wahrscheinlichkeitsverteilung ist. Ist dies nicht der Fall, ist die Berechnung des Gradienten falsch.

Zweite:

tf.nn.sparse_softmax_cross_entropy_with_logits

HINWEIS: Für diesen Vorgang wird die Wahrscheinlichkeit eines bestimmten Etiketts als exklusiv betrachtet. Das heißt, weiche Klassen sind nicht zulässig, und der Beschriftungsvektor muss für jede Protokollzeile (jeden Minibatch-Eintrag) einen einzelnen spezifischen Index für die wahre Klasse bereitstellen.

Drag0
quelle
4
Was sollen wir verwenden, wenn sich die Klassen nicht gegenseitig ausschließen? Ich meine, wenn wir mehrere kategoriale Labels kombinieren?
Hayro
Ich habe das auch gelesen. Das heißt, wir wenden die Klassenwahrscheinlichkeit auf die Kreuzentropie an, anstatt sie als Onehot-Vektor zu verwenden.
Shamane Siriwardhana
@ Hayro - Meinst du, du kannst keine Hotcodierung durchführen? Ich denke, Sie müssten sich ein anderes Modell ansehen. Dies erwähnte etwas wie "Es wäre besser, 4 binäre logistische Regressionsklassifikatoren zu erstellen", um zunächst sicherzustellen, dass Sie die Klassen trennen können.
Ashley
21

Beide Funktionen berechnen die gleichen Ergebnisse und sparse_softmax_cross_entropy_with_logits berechnet die Kreuzentropie direkt auf den Sparse-Labels, anstatt sie mit One-Hot-Codierung zu konvertieren .

Sie können dies überprüfen, indem Sie das folgende Programm ausführen:

import tensorflow as tf
from random import randint

dims = 8
pos  = randint(0, dims - 1)

logits = tf.random_uniform([dims], maxval=3, dtype=tf.float32)
labels = tf.one_hot(pos, dims)

res1 = tf.nn.softmax_cross_entropy_with_logits(       logits=logits, labels=labels)
res2 = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=tf.constant(pos))

with tf.Session() as sess:
    a, b = sess.run([res1, res2])
    print a, b
    print a == b

Hier erstelle ich einen zufälligen logitsLängenvektor dimsund generiere One-Hot-codierte Beschriftungen (wobei Element in pos1 und andere 0 sind).

Danach berechne ich Softmax und Sparse Softmax und vergleiche deren Ausgabe. Versuchen Sie es einige Male erneut, um sicherzustellen, dass immer die gleiche Ausgabe erzeugt wird

Salvador Dali
quelle