2017-11-08 2 views
1

Mein aktueller Code mit sparse_softmax_cross_entropy funktioniert einwandfrei.Tensorflow - Die Verwendung von tf.losses.hinge_loss führt zu Inkompatiblen Shapes

loss_normal = (
    tf.reduce_mean(tf.losses 
        .sparse_softmax_cross_entropy(labels=labels, 
               logits=logits, 
               weights=class_weights)) 
    ) 

aber wenn ich versuche, das verwenden hinge_loss:

loss_normal = (
    tf.reduce_mean(tf.losses 
        .hinge_loss(labels=labels, 
           logits=logits, 
           weights=class_weights)) 
    ) 

Es hat einen Fehler gemeldet sagen:

ValueError: Shapes (1024, 2) and (1024,) are incompatible 

Der Fehler dieser Funktion in der losses_impl.py Datei entstanden zu sein scheint :

with ops.name_scope(scope, "hinge_loss", (logits, labels)) as scope: 
    ... 
    logits.get_shape().assert_is_compatible_with(labels.get_shape()) 
    ... 

modifizierte ich meinen Code wie unten nur 1 Spalte des Tensor Logits extrahieren:

loss_normal = (
    tf.reduce_mean(tf.losses 
        .hinge_loss(labels=labels, 
           logits=logits[:,1:], 
           weights=class_weights 
           )) 
    ) 

Aber es meldet noch einen ähnlichen Fehler:

ValueError: Shapes (1024, 1) and (1024,) are incompatible. 

Kann warum funktioniert mein Code helfen jemand bitte darauf hin, gut mit sparse_softmax_cross_entropy Verlust aber nicht hinge_loss?

Antwort

1

Der Tensor labels die Form hat [1024], hat der Tensor logits[1024, 2] Form. Dies funktioniert gut für tf.nn.sparse_softmax_cross_entropy_with_logits:

  • labels: Tensor of shape [d_0, d_1, ..., d_{r-1}] (where r is rank of labels and result) and dtype int32 or int64. Each entry in labels must be an index in [0, num_classes). Other values will raise an exception when this op is run on CPU, and return NaN for corresponding loss and gradient rows on GPU.
  • logits: Unscaled log probabilities of shape [d_0, d_1, ..., d_{r-1}, num_classes] and dtype float32 or float64.

Aber tf.hinge_loss Anforderungen sind unterschiedlich:

  • labels: The ground truth output tensor. Its shape should match the shape of logits. The values of the tensor are expected to be 0.0 or 1.0.
  • logits: The logits, a float tensor.

Sie dies auf zwei Arten lösen:

  • Reshape die Etiketten zu [1024, 1] und verwenden nur ein Reihe von logits, wie Sie es taten - logits[:,1:]:

    labels = tf.reshape(labels, [-1, 1]) 
    hinge_loss = (
        tf.reduce_mean(tf.losses.hinge_loss(labels=labels, 
                 logits=logits[:,1:], 
                 weights=class_weights)) 
        ) 
    

    Ich denke, Sie müssen auch die class_weights auf die gleiche Weise umgestalten.

  • Verwenden alle gelernt logits Funktionen über tf.reduce_sum, die ein flaches (1024,) Tensor machen:

    logits = tf.reduce_sum(logits, axis=1) 
    hinge_loss = (
        tf.reduce_mean(tf.losses.hinge_loss(labels=labels, 
                 logits=logits, 
                 weights=class_weights)) 
        ) 
    

    Auf diese Weise brauchen Sie nicht labels oder class_weights neu zu gestalten.

+0

Dank Maxim. Ich bin mir nicht sicher, ob ich den zweiten Ansatz verstehe, indem ich die Logiken entlang der Achse 1 summiere. Ich werde beide Ansätze morgen versuchen und ein Update bereitstellen. Vielen Dank. – Allen

0

Der Grund wurde in Maxims Antwort gut erklärt. Ich versuche, einige alternative Lösungen zu finden, basierend auf der Annahme, dass Sie Gewichte zu verschiedenen Klassen hinzufügen möchten.

Es scheint, dass Ihre Gewichte die gleiche Größe der Losgröße haben.Ich denke, man unterschiedliche Gewicht zu verschiedenen Klassen und die „Gewichte“ erhält man durch einige Codes ähnlich belowing eine hinzuzufügen Ziel:

class_weights = [0.4, 0.6] # The weights for each class 
weights = tf.reduce_sum(class_weights * tf.labels, axis = 1) 

Dieser Code ist es, die Klasse Gewicht zu konvertieren, um die zu jeder Probe hinzugefügt werden Gewichte jeder Stichprobe in einem Stapel, so dass wir die Klassen gewichten können, indem wir die Stichproben indirekt gewichten. (Für ein Beispiel, dessen Label [0, 1] ist, sind die Gewichte des berechneten Beispiels 0 * 0,4 + 1 * 0,6 = 0,6, was tatsächlich die Klassengewichte sind)

Aber wenn Sie tf verwenden. losses.hinge_loss, muss diese Konvertierung nicht durchgeführt werden. Das Gewichtungsargument muss "0" oder die gleiche Rangfolge von Labels sein und an Label übertragbar sein (dh alle Dimensionen müssen entweder 1 oder die gleiche sein wie die entsprechende Verlustdimension). "

Also Sie Sie müssen ein Klassengewicht mit Rang 1 (2 Dimensionen) und Dimension 0 entweder 1 oder Losgröße erstellen. Das folgende Programm kann ordnungsgemäß funktionieren.

weights = tf.expand_dims(class_weights, axis = 0) 
hinge_loss = tf.losses.hinge_loss(labels = self.label, logits = self.prediction, 
            weights = weights) 

Da ich nicht genug Ruf haben über die Frage zu äußern, kann ich nicht mehr Informationen Ihrer Aufgabe bekommen. Die obige Antwort basiert auf der Annahme, dass Sie Gewichtungen zu verschiedenen Klassen hinzufügen müssen. Also, wenn ich falsch liege, bitte informieren Sie mich, diese Antwort zu löschen :).

Verwandte Themen